<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-1654533831848812867</id><updated>2011-11-15T08:04:39.580-08:00</updated><category term='Misconception'/><category term='Projective Textures'/><category term='PIL'/><category term='GLSL'/><category term='Framebuffer'/><category term='PyGame'/><category term='Lighting'/><category term='Unusual'/><category term='Shaders'/><category term='Bugs'/><category term='Render to Texture'/><category term='PyOpenGL'/><title type='text'>Complete Python OpenGL examples</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://python-opengl-examples.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1654533831848812867/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://python-opengl-examples.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>basti_79</name><uri>http://www.blogger.com/profile/03249856320601693214</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>7</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1654533831848812867.post-8515246228042106719</id><published>2009-07-31T13:16:00.001-07:00</published><updated>2009-08-02T11:27:56.397-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Shaders'/><category scheme='http://www.blogger.com/atom/ns#' term='Unusual'/><category scheme='http://www.blogger.com/atom/ns#' term='Render to Texture'/><title type='text'>Fire!</title><content type='html'>This is the old-school fire effect from the 90's, rendered in OpenGL. It uses a combination of Buffer Feedback and Palette rendering, both implemented in GLSL.&lt;br /&gt;&lt;br /&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-8bee222e75d3a8b" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v22.nonxt1.googlevideo.com/videoplayback?id%3D08bee222e75d3a8b%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1331064281%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D66AD54975CDAD39F3E77083025D1C12ECFA5D351.749AB52E6B0DC1FEE87065FF3EFFA5B1AD37FCEA%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D8bee222e75d3a8b%26offsetms%3D5000%26itag%3Dw160%26sigh%3DGoSprYvvZVE9GMFieTtqjTMUOYQ&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="320" height="266" bgcolor="#FFFFFF"flashvars="flvurl=http://v22.nonxt1.googlevideo.com/videoplayback?id%3D08bee222e75d3a8b%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1331064281%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D66AD54975CDAD39F3E77083025D1C12ECFA5D351.749AB52E6B0DC1FEE87065FF3EFFA5B1AD37FCEA%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D8bee222e75d3a8b%26offsetms%3D5000%26itag%3Dw160%26sigh%3DGoSprYvvZVE9GMFieTtqjTMUOYQ&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;Quite a few things that I deemed infeasible to implement back then are easily possible in todays GC's, among them: dynamic convolution patterns, interpolation, correct side-to-side wrapping (clamp vertically, but wrap horizontally), arbitrary "fire pixel size". The example doesn't demonstrate this though.&lt;br /&gt;&lt;br /&gt;It even should be possible to distort the fire eg. to flow around objects, by simply not drawing a simple square in the blur/displace step but something else. However, due to the exponential nature of feedback processes, one ends up with bizarrely distorted images frequently.&lt;br /&gt;&lt;br /&gt;It appeared necessary to use two textures, since you don't want to be overwriting the texture you're reading from. However, I'm not aware if render-to-texture would overwrite a texture &lt;i&gt;while you're rendering&lt;/i&gt; instead of dumping all changes from a frame buffer after rendering. I don't even know if this is specified&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# Pygame/PyopenGL example by Bastiaan Zapf, Jul/Aug 2009&lt;br /&gt;&lt;br /&gt;# render a fire effect via blurring and displacing feedback&lt;br /&gt;# (similar to video feedback)&lt;br /&gt;&lt;br /&gt;# this effect was ubiquitous in the 90's, often used in&lt;br /&gt;# cracker's intros, demos and the like&lt;br /&gt;&lt;br /&gt;from OpenGL.GL import *&lt;br /&gt;from OpenGL.GLU import *&lt;br /&gt;&lt;br /&gt;from OpenGL.GL.ARB.framebuffer_object import *&lt;br /&gt;from OpenGL.GL.EXT.framebuffer_object import *&lt;br /&gt;&lt;br /&gt;from ctypes import *&lt;br /&gt;&lt;br /&gt;from math import *&lt;br /&gt;import pygame&lt;br /&gt;import random&lt;br /&gt;import screenshot&lt;br /&gt;import time&lt;br /&gt;import numpy # for black textures&lt;br /&gt;from shaderlib import *&lt;br /&gt;&lt;br /&gt;pygame.init()&lt;br /&gt;&lt;br /&gt;screenx=400&lt;br /&gt;screeny=300&lt;br /&gt;&lt;br /&gt;pygame.display.set_mode((screenx,screeny), pygame.OPENGL|pygame.DOUBLEBUF)&lt;br /&gt;&lt;br /&gt;glClearColor(0.0, 0.0, 0.0, 1.0)&lt;br /&gt;glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)&lt;br /&gt;&lt;br /&gt;# Create and Compile fragment and vertex shaders&lt;br /&gt;&lt;br /&gt;# Texturing&lt;br /&gt;&lt;br /&gt;vertex_shader=createAndCompileShader(GL_VERTEX_SHADER,"""&lt;br /&gt;varying vec3 v;&lt;br /&gt;varying vec3 N;&lt;br /&gt;&lt;br /&gt;void main(void)&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;   v = gl_ModelViewMatrix * gl_Vertex;&lt;br /&gt;   N = gl_NormalMatrix * gl_Normal;&lt;br /&gt;&lt;br /&gt;   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;&lt;br /&gt;   gl_TexCoord[0]=gl_TextureMatrix[0] * gl_MultiTexCoord0;&lt;br /&gt;}&lt;br /&gt;""");&lt;br /&gt;&lt;br /&gt;# Convolution shader - this is the Code that implements&lt;br /&gt;# the blur between two frames&lt;br /&gt;# this will be expensive.&lt;br /&gt;&lt;br /&gt;fire_shader=createAndCompileShader(GL_FRAGMENT_SHADER,"""&lt;br /&gt;&lt;br /&gt;const int MaxKernelSize=25;&lt;br /&gt;uniform vec3 OffsetWeight[MaxKernelSize];&lt;br /&gt;uniform int KernelSize;&lt;br /&gt;uniform sampler2D BaseImage; &lt;br /&gt;varying vec3 N;&lt;br /&gt;varying vec3 v;&lt;br /&gt;&lt;br /&gt;void main(void)&lt;br /&gt;{&lt;br /&gt;  int i;&lt;br /&gt;  vec4 sum=vec4(0.0);&lt;br /&gt;  for (i=0;i&amp;lt;KernelSize;i++) {&lt;br /&gt;     sum+=texture2D(BaseImage,gl_TexCoord[0].st+OffsetWeight[i].st)*OffsetWeight[i].z;&lt;br /&gt;  }&lt;br /&gt;  gl_FragColor=sum;&lt;br /&gt;}&lt;br /&gt;""");&lt;br /&gt;&lt;br /&gt;# build fire shader program&lt;br /&gt;&lt;br /&gt;fire_program=glCreateProgram()&lt;br /&gt;glAttachShader(fire_program,vertex_shader)&lt;br /&gt;glAttachShader(fire_program,fire_shader)&lt;br /&gt;glLinkProgram(fire_program)&lt;br /&gt;&lt;br /&gt;# reference the shader variables&lt;br /&gt;&lt;br /&gt;locOW = glGetUniformLocation(fire_program,"OffsetWeight");&lt;br /&gt;locKS = glGetUniformLocation(fire_program,"KernelSize");&lt;br /&gt;locBI = glGetUniformLocation(fire_program,"BaseImage");&lt;br /&gt;&lt;br /&gt;# try to activate/enable shader program&lt;br /&gt;# handle errors wisely&lt;br /&gt;&lt;br /&gt;try:&lt;br /&gt;    glUseProgram(fire_program)   &lt;br /&gt;except OpenGL.error.GLError:&lt;br /&gt;    print glGetProgramInfoLog(fire_program)&lt;br /&gt;    raise&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# Monochrome to fire colors shader&lt;br /&gt;&lt;br /&gt;color_shader=createAndCompileShader(GL_FRAGMENT_SHADER,"""&lt;br /&gt;&lt;br /&gt;const int MaxKernelSize=25;&lt;br /&gt;uniform sampler2D BaseImage;&lt;br /&gt;varying vec3 N;&lt;br /&gt;varying vec3 v;&lt;br /&gt;&lt;br /&gt;void main(void)&lt;br /&gt;{&lt;br /&gt;  int i;&lt;br /&gt;  vec4 sum=vec4(0.0);&lt;br /&gt;  sum=texture2D(BaseImage,gl_TexCoord[0].st+vec2(0,0));&lt;br /&gt;&lt;br /&gt;  if (sum.x&amp;lt;0.1) {&lt;br /&gt;    gl_FragColor=vec4(0.0,0.0,0.0,0.0);    &lt;br /&gt;  } else if (sum.x&amp;lt;0.2) {&lt;br /&gt;    gl_FragColor=vec4((sum.x-0.1)*10.0,0.0,0.0,0.0);&lt;br /&gt;  } else if (sum.x&amp;lt;0.3) {&lt;br /&gt;    gl_FragColor=vec4(1.0,(sum.x-0.2)*10.0,0.0,0.0);&lt;br /&gt;  } else if (sum.x&amp;lt;0.4) {&lt;br /&gt;    gl_FragColor=vec4(1.0,1.0,(sum.x-0.3)*10.0,0.0);&lt;br /&gt;  } else {&lt;br /&gt;    gl_FragColor=vec4(1.0,1.0,1.0,0.0);&lt;br /&gt;  } &lt;br /&gt;}&lt;br /&gt;""");&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;colors_program=glCreateProgram()&lt;br /&gt;glAttachShader(colors_program,vertex_shader)&lt;br /&gt;glAttachShader(colors_program,color_shader)&lt;br /&gt;glLinkProgram(colors_program)&lt;br /&gt;&lt;br /&gt;# try to activate/enable shader program&lt;br /&gt;# handle errors wisely&lt;br /&gt;&lt;br /&gt;try:&lt;br /&gt;    glUseProgram(colors_program)   &lt;br /&gt;except OpenGL.error.GLError:&lt;br /&gt;    print glGetProgramInfoLog(colors_program)&lt;br /&gt;    raise&lt;br /&gt;&lt;br /&gt;# return to fire program to set variables&lt;br /&gt;&lt;br /&gt;glUseProgram(fire_program);&lt;br /&gt;glMatrixMode(GL_MODELVIEW);&lt;br /&gt;&lt;br /&gt;# set a cheap convolution kernel of length 3&lt;br /&gt;&lt;br /&gt;glUniform1i(locKS,3);&lt;br /&gt;glUniform3fv(locOW,3,&lt;br /&gt;             [[  0.001,  0.0  , 0.32],&lt;br /&gt;              [ -0.001,  0.0  , 0.32],&lt;br /&gt;              [  0    , -0.001, 0.32],&lt;br /&gt;              ]); # just some blur&lt;br /&gt;&lt;br /&gt;glUniform1i(locBI,0); # we will be using the first texturing unit&lt;br /&gt;&lt;br /&gt;# get a monochromatic texture of the size specified below - low resolution&lt;br /&gt;# will mean large flames and cheap calculation&lt;br /&gt;&lt;br /&gt;firew=64&lt;br /&gt;fireh=64&lt;br /&gt;&lt;br /&gt;texture=glGenTextures( 1 )&lt;br /&gt;    &lt;br /&gt;glBindTexture( GL_TEXTURE_2D, texture );&lt;br /&gt;glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );&lt;br /&gt;glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,&lt;br /&gt;                 GL_REPEAT);&lt;br /&gt;glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,&lt;br /&gt;                     GL_REPEAT );&lt;br /&gt;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)&lt;br /&gt;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)&lt;br /&gt;&lt;br /&gt;glTexImage2D(GL_TEXTURE_2D, 0,GL_LUMINANCE,&lt;br /&gt;             firew,fireh,0,GL_LUMINANCE,GL_FLOAT,numpy.zeros([firew,fireh,1],float)) &lt;br /&gt;&lt;br /&gt;glEnable( GL_TEXTURE_2D );&lt;br /&gt;glBindTexture( GL_TEXTURE_2D, texture );&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# generate another texture we render the fire to, and set parameters&lt;br /&gt;&lt;br /&gt;newtexture=glGenTextures( 1 )&lt;br /&gt;    &lt;br /&gt;glBindTexture( GL_TEXTURE_2D, newtexture );&lt;br /&gt;glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );&lt;br /&gt;glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,&lt;br /&gt;                 GL_REPEAT );&lt;br /&gt;glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,&lt;br /&gt;                 GL_REPEAT );&lt;br /&gt;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)&lt;br /&gt;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)&lt;br /&gt;&lt;br /&gt;glTexImage2D(GL_TEXTURE_2D, 0,GL_LUMINANCE,firew,fireh,0,GL_LUMINANCE,&lt;br /&gt;             GL_FLOAT, numpy.zeros([firew,fireh,1],float))&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# other choices for the texture wrapping options might be &lt;br /&gt;# benefitial&lt;br /&gt;&lt;br /&gt;done = False&lt;br /&gt;&lt;br /&gt;t=0&lt;br /&gt;&lt;br /&gt;# prepare a frame buffer object&lt;br /&gt;&lt;br /&gt;fbo=c_uint(1)  # WTF? Did not find a way to get there easier&lt;br /&gt;# A simple number would always result in a "Segmentation &lt;br /&gt;# Fault" for me&lt;br /&gt;&lt;br /&gt;glGenFramebuffers(1,fbo)&lt;br /&gt;&lt;br /&gt;while not done:&lt;br /&gt;&lt;br /&gt;    t=t+1&lt;br /&gt;&lt;br /&gt;    # rotation and displacement during fire blur&lt;br /&gt;&lt;br /&gt;    alpha=sin(t/73.0)&lt;br /&gt;&lt;br /&gt;    x=0&lt;br /&gt;    y=0.004+(cos(t/43.0)+1.0)/50.0&lt;br /&gt;&lt;br /&gt;    # render to texture (render next step of fire effect)&lt;br /&gt;&lt;br /&gt;    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo)&lt;br /&gt;&lt;br /&gt;    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, &lt;br /&gt;                              GL_TEXTURE_2D, newtexture, 0)&lt;br /&gt;        &lt;br /&gt;    glPushAttrib(GL_VIEWPORT_BIT) # save viewport&lt;br /&gt;    &lt;br /&gt;    glViewport(0, 0, firew, fireh) # set to fire effect dimensions&lt;br /&gt;&lt;br /&gt;    glUseProgram(fire_program) # use fire blur&lt;br /&gt;&lt;br /&gt;    # first draw blurred/displaced fire&lt;br /&gt;&lt;br /&gt;    glBindTexture( GL_TEXTURE_2D, texture )&lt;br /&gt;    glLoadIdentity()&lt;br /&gt;&lt;br /&gt;    glTranslatef(x,y,0)&lt;br /&gt;    glRotatef(alpha,0,0,1)&lt;br /&gt;&lt;br /&gt;    glBegin(GL_QUADS)&lt;br /&gt;&lt;br /&gt;    glTexCoord2f(0,0)&lt;br /&gt;    glVertex2f(-1,-1)&lt;br /&gt;    glTexCoord2f(1,0)&lt;br /&gt;    glVertex2f( 1,-1)&lt;br /&gt;    glTexCoord2f(1,1)&lt;br /&gt;    glVertex2f( 1, 1)&lt;br /&gt;    glTexCoord2f(0,1)&lt;br /&gt;    glVertex2f(-1, 1)&lt;br /&gt;    &lt;br /&gt;    glEnd()&lt;br /&gt;&lt;br /&gt;    # then draw a few random pixels at the bottom to get the fire going&lt;br /&gt;&lt;br /&gt;    glUseProgram(0) # shaders interfer with pure pixel drawing&lt;br /&gt;&lt;br /&gt;    glBindTexture( GL_TEXTURE_2D, 0 ) # textures do so as well&lt;br /&gt;&lt;br /&gt;    for i in range(0,firew):&lt;br /&gt;        glRasterPos2f(-1+2*i/(firew+0.0),-0.999)&lt;br /&gt;        glDrawPixelsf(GL_LUMINANCE,[[[random.random()]]])&lt;br /&gt;        &lt;br /&gt;    # restore viewport&lt;br /&gt;&lt;br /&gt;    glPopAttrib(GL_VIEWPORT_BIT)&lt;br /&gt;&lt;br /&gt;    # don't render to texture anymore&lt;br /&gt;&lt;br /&gt;    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)&lt;br /&gt;&lt;br /&gt;    # fire "palette"&lt;br /&gt;    glLoadIdentity()&lt;br /&gt;    glUseProgram(colors_program)&lt;br /&gt;    glBindTexture( GL_TEXTURE_2D, texture )&lt;br /&gt;&lt;br /&gt;    # draw fire once, however, clip noise from top and bottom&lt;br /&gt;&lt;br /&gt;    glBegin(GL_QUADS)&lt;br /&gt;&lt;br /&gt;    glTexCoord2f(0,0.03)&lt;br /&gt;    glVertex3f(-1,-1,0)&lt;br /&gt;    glTexCoord2f(1,0.03)&lt;br /&gt;    glVertex3f( 1,-1,0)&lt;br /&gt;    glTexCoord2f(1,0.97)&lt;br /&gt;    glVertex3f( 1, 1,0)&lt;br /&gt;    glTexCoord2f(0,0.97)&lt;br /&gt;    glVertex3f(-1, 1,0)&lt;br /&gt;&lt;br /&gt;    glEnd()&lt;br /&gt;&lt;br /&gt;    pygame.display.flip()&lt;br /&gt;&lt;br /&gt;    # flip textures&lt;br /&gt;&lt;br /&gt;    oldtexture=texture&lt;br /&gt;    texture=newtexture&lt;br /&gt;    newtexture=oldtexture&lt;br /&gt;    &lt;br /&gt;    time.sleep(0.01)&lt;br /&gt;    t=t+1&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1654533831848812867-8515246228042106719?l=python-opengl-examples.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=8bee222e75d3a8b&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://python-opengl-examples.blogspot.com/feeds/8515246228042106719/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://python-opengl-examples.blogspot.com/2009/07/fire-preview-stage.html#comment-form' title='3 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1654533831848812867/posts/default/8515246228042106719'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1654533831848812867/posts/default/8515246228042106719'/><link rel='alternate' type='text/html' href='http://python-opengl-examples.blogspot.com/2009/07/fire-preview-stage.html' title='Fire!'/><author><name>basti_79</name><uri>http://www.blogger.com/profile/03249856320601693214</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1654533831848812867.post-1049529247625119123</id><published>2009-05-03T09:53:00.000-07:00</published><updated>2009-05-03T10:12:28.980-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='GLSL'/><category scheme='http://www.blogger.com/atom/ns#' term='Projective Textures'/><title type='text'>Projective Texture Mapping</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_v-eQ6-W94RU/Sf3MjrXQVbI/AAAAAAAAABg/6cEkaLIFjZ0/s1600-h/projection00927.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_v-eQ6-W94RU/Sf3MjrXQVbI/AAAAAAAAABg/6cEkaLIFjZ0/s320/projection00927.jpg" alt="" id="BLOGGER_PHOTO_ID_5331642447184287154" border="0"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-34f2a164248b3ec1" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v15.nonxt7.googlevideo.com/videoplayback?id%3D34f2a164248b3ec1%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1331064281%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D5FE513FE9A7159D73240039F6D4748C6E40FBE07.1DDB7DD2F834CA118E49BF87986308A8254914EB%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D34f2a164248b3ec1%26offsetms%3D5000%26itag%3Dw160%26sigh%3D_N6rvHZ460QJ9kpehan-9kvGRME&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="320" height="266" bgcolor="#FFFFFF"flashvars="flvurl=http://v15.nonxt7.googlevideo.com/videoplayback?id%3D34f2a164248b3ec1%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1331064281%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D5FE513FE9A7159D73240039F6D4748C6E40FBE07.1DDB7DD2F834CA118E49BF87986308A8254914EB%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D34f2a164248b3ec1%26offsetms%3D5000%26itag%3Dw160%26sigh%3D_N6rvHZ460QJ9kpehan-9kvGRME&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;This script will create a Texture containing a Ring image, then it will project this on some green cubes ("project" as in "overhead projector", not as in "flat projection"). This is usually called "projective Texturing". The secret in this is the GLSL Function texture2DProj, which does nothing more than to divide by the (usually useless) last Texture coordinate. Be careful however, as, since if you specify a vec4, the homogenous fourth coordinate, which is constant, will be used. Then you'd get a Projection without perspective.&lt;br /&gt;&lt;br /&gt;Try using "GL_REPEAT" for the projected texture's wrapping, it looks fun.&lt;br /&gt;&lt;br /&gt;The Distance measurement between projector and projection actually is a little clumsy, i bet there's a better way, but this one works so far.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# Pygame/PyopenGL example by Bastiaan Zapf, May 2009&lt;br /&gt;#&lt;br /&gt;# Projective Textures&lt;br /&gt;#&lt;br /&gt;# Employed techniques: &lt;br /&gt;#&lt;br /&gt;# - Vertex and Fragment shaders&lt;br /&gt;# - Display Lists&lt;br /&gt;# - Texturing&lt;br /&gt;&lt;br /&gt;from OpenGL.GL import *&lt;br /&gt;from OpenGL.GLU import *&lt;br /&gt;import random&lt;br /&gt;from math import * # trigonometry&lt;br /&gt;import numpy&lt;br /&gt;&lt;br /&gt;import pygame # just to get a display&lt;br /&gt;&lt;br /&gt;import Image&lt;br /&gt;import sys&lt;br /&gt;import time&lt;br /&gt;&lt;br /&gt;# get an OpenGL surface&lt;br /&gt;&lt;br /&gt;pygame.init() &lt;br /&gt;pygame.display.set_mode((800,600), pygame.OPENGL|pygame.DOUBLEBUF)&lt;br /&gt;&lt;br /&gt;def jpg_file_write(name, number, data):&lt;br /&gt;    im = Image.frombuffer("RGBA", (800,600), data, "raw", "RGBA", 0, 0)&lt;br /&gt;    fnumber = "%05d" % number&lt;br /&gt;    im.save(name + fnumber + ".jpg")&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;# Create and Compile a shader&lt;br /&gt;# but fail with a meaningful message if something goes wrong&lt;br /&gt;&lt;br /&gt;def createAndCompileShader(type,source):&lt;br /&gt;    shader=glCreateShader(type)&lt;br /&gt;    glShaderSource(shader,source)&lt;br /&gt;    glCompileShader(shader)&lt;br /&gt;&lt;br /&gt;    # get "compile status" - glCompileShader will not fail with &lt;br /&gt;    # an exception in case of syntax errors&lt;br /&gt;&lt;br /&gt;    result=glGetShaderiv(shader,GL_COMPILE_STATUS)&lt;br /&gt;&lt;br /&gt;    if (result!=1): # shader didn't compile&lt;br /&gt;        raise Exception("Couldn't compile shader\nShader compilation Log:\n"+glGetShaderInfoLog(shader))&lt;br /&gt;    return shader&lt;br /&gt;&lt;br /&gt;vertex_shader=createAndCompileShader(GL_VERTEX_SHADER,"""&lt;br /&gt;  &lt;br /&gt;varying vec3 normal, lightDir;&lt;br /&gt;&lt;br /&gt;void main()&lt;br /&gt;{ &lt;br /&gt;  normal = gl_NormalMatrix * gl_Normal;&lt;br /&gt;  vec4 posEye =  gl_ModelViewMatrix * gl_Vertex;&lt;br /&gt;&lt;br /&gt;  // Put World coordinates of Vertex, multiplied by TextureMatrix[0]&lt;br /&gt;  // into TexCoord[0]&lt;br /&gt;&lt;br /&gt;  gl_TexCoord[0] = gl_TextureMatrix[0]*gl_ModelViewMatrix*gl_Vertex;&lt;br /&gt;&lt;br /&gt;  // LightSource[0] position is assumed to be the projector position&lt;br /&gt;&lt;br /&gt;  lightDir = vec3(gl_LightSource[0].position.xyz - posEye.xyz);&lt;br /&gt;  gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;&lt;br /&gt;}&lt;br /&gt;""");&lt;br /&gt;&lt;br /&gt;fragment_shader=createAndCompileShader(GL_FRAGMENT_SHADER,"""&lt;br /&gt;uniform sampler2D projMap;&lt;br /&gt;varying vec3 normal, lightDir;&lt;br /&gt;&lt;br /&gt;void main (void)&lt;br /&gt;{&lt;br /&gt;  vec4 final_color = vec4(0.0,0.5,0,0.3); &lt;br /&gt;  vec3 N = normalize(normal);&lt;br /&gt;  vec3 L = normalize(lightDir);&lt;br /&gt; &lt;br /&gt;  float lambert = dot(N,L);&lt;br /&gt; &lt;br /&gt;  if( gl_TexCoord[0].z&gt;0.0 // in front of projector?&lt;br /&gt;      &amp;&amp; &lt;br /&gt;      lambert&gt;0 )          // facing projector?&lt;br /&gt;  {&lt;br /&gt;&lt;br /&gt;    // project texture - see notes for pitfall&lt;br /&gt;&lt;br /&gt;    vec4 ProjMapColor = texture2DProj(projMap, gl_TexCoord[0].xyz); &lt;br /&gt;    final_color += ProjMapColor*lambert*pow(length(L),-2.0);  &lt;br /&gt;  }&lt;br /&gt;  &lt;br /&gt;  gl_FragColor = final_color;   &lt;br /&gt;}&lt;br /&gt;""");&lt;br /&gt;&lt;br /&gt;# build shader program&lt;br /&gt;&lt;br /&gt;program=glCreateProgram()&lt;br /&gt;glAttachShader(program,vertex_shader)&lt;br /&gt;glAttachShader(program,fragment_shader)&lt;br /&gt;glLinkProgram(program)&lt;br /&gt;&lt;br /&gt;# try to activate/enable shader program&lt;br /&gt;# handle errors wisely&lt;br /&gt;&lt;br /&gt;try:&lt;br /&gt;    glUseProgram(program)   &lt;br /&gt;except OpenGL.error.GLError:&lt;br /&gt;    print glGetProgramInfoLog(program)&lt;br /&gt;    raise&lt;br /&gt;&lt;br /&gt;done = False&lt;br /&gt;&lt;br /&gt;t=0 &lt;br /&gt;&lt;br /&gt;# load a cube into a display list&lt;br /&gt;&lt;br /&gt;glNewList(1,GL_COMPILE)&lt;br /&gt;&lt;br /&gt;glBegin(GL_QUADS)&lt;br /&gt;&lt;br /&gt;glColor3f(1,1,1)&lt;br /&gt;&lt;br /&gt;glNormal3f(0,0,-1)&lt;br /&gt;glVertex3f( -1, -1, -1)&lt;br /&gt;glVertex3f(  1, -1, -1)&lt;br /&gt;glVertex3f(  1,  1, -1)&lt;br /&gt;glVertex3f( -1,  1, -1)&lt;br /&gt;&lt;br /&gt;glNormal3f(0,0,1)&lt;br /&gt;glVertex3f( -1, -1,  1)&lt;br /&gt;glVertex3f(  1, -1,  1)&lt;br /&gt;glVertex3f(  1,  1,  1)&lt;br /&gt;glVertex3f( -1,  1,  1)&lt;br /&gt;&lt;br /&gt;glNormal3f(0,-1,0) &lt;br /&gt;glVertex3f( -1, -1, -1)&lt;br /&gt;glVertex3f(  1, -1, -1)&lt;br /&gt;glVertex3f(  1, -1,  1)&lt;br /&gt;glVertex3f( -1, -1,  1)&lt;br /&gt;&lt;br /&gt;glNormal3f(0,1,0) &lt;br /&gt;glVertex3f( -1,  1, -1)&lt;br /&gt;glVertex3f(  1,  1, -1)&lt;br /&gt;glVertex3f(  1,  1,  1)&lt;br /&gt;glVertex3f( -1,  1,  1)&lt;br /&gt;&lt;br /&gt;glNormal3f(-1,0,0)     &lt;br /&gt;glVertex3f( -1, -1, -1)&lt;br /&gt;glVertex3f( -1,  1, -1)&lt;br /&gt;glVertex3f( -1,  1,  1)&lt;br /&gt;glVertex3f( -1, -1,  1)                      &lt;br /&gt;&lt;br /&gt;glNormal3f(1,0,0)        &lt;br /&gt;glVertex3f(  1, -1, -1)&lt;br /&gt;glVertex3f(  1,  1, -1)&lt;br /&gt;glVertex3f(  1,  1,  1)&lt;br /&gt;glVertex3f(  1, -1,  1)&lt;br /&gt;&lt;br /&gt;glEnd()&lt;br /&gt;glEndList()&lt;br /&gt;&lt;br /&gt;texture=glGenTextures( 1 )&lt;br /&gt;&lt;br /&gt;glActiveTexture(GL_TEXTURE0); # use first texturing unit&lt;br /&gt;glBindTexture( GL_TEXTURE_2D, texture );&lt;br /&gt;&lt;br /&gt;glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );&lt;br /&gt;&lt;br /&gt;glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,&lt;br /&gt;                GL_CLAMP ); # try GL_REPEAT for fun&lt;br /&gt;glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,&lt;br /&gt;                GL_CLAMP );&lt;br /&gt;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, &lt;br /&gt;                GL_LINEAR)&lt;br /&gt;glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, &lt;br /&gt;                GL_LINEAR)&lt;br /&gt;&lt;br /&gt;texdata=numpy.zeros((256,256,4))&lt;br /&gt;&lt;br /&gt;# a ring-shaped projection texture&lt;br /&gt;&lt;br /&gt;for i in range(0,256):&lt;br /&gt;    x=(i-128.1)/128.0&lt;br /&gt;    for j in range(0,256):&lt;br /&gt;        y=(j-128.1)/128.0&lt;br /&gt;        if ((x*x+y*y&gt;0.9) | (x*x+y*y&lt;0.3)):&lt;br /&gt;            texdata[i][j][0]=0&lt;br /&gt;            texdata[i][j][1]=0&lt;br /&gt;            texdata[i][j][2]=0&lt;br /&gt;            texdata[i][j][3]=0&lt;br /&gt;        else:&lt;br /&gt;            texdata[i][j][0]=1&lt;br /&gt;            texdata[i][j][1]=1&lt;br /&gt;            texdata[i][j][2]=1&lt;br /&gt;            texdata[i][j][3]=1&lt;br /&gt;&lt;br /&gt;glTexImage2Df(GL_TEXTURE_2D, 0,GL_RGBA,0,GL_RGBA,&lt;br /&gt;              texdata)&lt;br /&gt;&lt;br /&gt;loc=glGetUniformLocation(program,"projMap"); &lt;br /&gt;glUniform1i(loc, 0) # use first texturing unit in shader&lt;br /&gt;&lt;br /&gt;glEnable(GL_DEPTH_TEST)&lt;br /&gt;&lt;br /&gt;while not done:&lt;br /&gt;&lt;br /&gt;    t=t+1&lt;br /&gt;&lt;br /&gt;    # Projector position and angle - this is rather rough so far&lt;br /&gt;&lt;br /&gt;    ppos=[sin(t/260.0)*4,cos(t/240.0)*4,0]&lt;br /&gt;    palpha=t&lt;br /&gt;    pbeta=t/3.0&lt;br /&gt;&lt;br /&gt;    # the texture matrix stores the intended projection&lt;br /&gt;    # however, signs seem to be reversed. This somehow makes sense, as&lt;br /&gt;    # we're transforming the texture coordinates&lt;br /&gt;&lt;br /&gt;    glMatrixMode(GL_TEXTURE); &lt;br /&gt;    glLoadIdentity()&lt;br /&gt;&lt;br /&gt;    glRotate(-palpha,0,1,0);&lt;br /&gt;    glRotate(-pbeta ,0,0,1);&lt;br /&gt;    glTranslate(-ppos[0],-ppos[1],-ppos[2])&lt;br /&gt;&lt;br /&gt;    # set light source position&lt;br /&gt;&lt;br /&gt;    glLightfv(GL_LIGHT0,GL_POSITION,[ppos[0],ppos[1],ppos[2]]);&lt;br /&gt;&lt;br /&gt;    # Set view&lt;br /&gt;&lt;br /&gt;    glMatrixMode(GL_PROJECTION)&lt;br /&gt;    glLoadIdentity()&lt;br /&gt;    gluPerspective(90,1,0.01,1000) &lt;br /&gt;    gluLookAt(sin(t/200.0)*8,sin(t/500.0)*3+8,cos(t/200.0)*8,0,0,0,0,1,0)&lt;br /&gt;&lt;br /&gt;    glClearColor(0.0, 0.0, 0.0, 1.0)&lt;br /&gt;    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)&lt;br /&gt;    &lt;br /&gt;    glMatrixMode(GL_MODELVIEW)&lt;br /&gt;&lt;br /&gt;    # draw a triangle to visualize the projector&lt;br /&gt;    # i don't have a clue how to relate the angles correctly here&lt;br /&gt;&lt;br /&gt;    glLoadIdentity()&lt;br /&gt;&lt;br /&gt;    glTranslate(ppos[0],ppos[1],ppos[2])&lt;br /&gt;&lt;br /&gt;    glBegin(GL_TRIANGLES)&lt;br /&gt;    &lt;br /&gt;    glVertex3f(1,0,0)&lt;br /&gt;    glVertex3f(0,1,0)&lt;br /&gt;    glVertex3f(0,0,1)&lt;br /&gt;&lt;br /&gt;    glEnd()&lt;br /&gt;&lt;br /&gt;    # fallback&lt;br /&gt;&lt;br /&gt;    glColor3f(1,1,1)&lt;br /&gt;&lt;br /&gt;    glLoadIdentity()&lt;br /&gt;&lt;br /&gt;    # render a range of cubes&lt;br /&gt;&lt;br /&gt;    for i in range(-1,2):&lt;br /&gt;        for j in range(-1,2):&lt;br /&gt;            for k in range(-1,2):&lt;br /&gt;                glPushMatrix()&lt;br /&gt;                glTranslate(i*5,j*5,k*5)&lt;br /&gt;                glScale(1,1,1)&lt;br /&gt;                glCallList(1)&lt;br /&gt;                glPopMatrix()&lt;br /&gt;&lt;br /&gt;    time.sleep(0.01);&lt;br /&gt;&lt;br /&gt;    pygame.display.flip()&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1654533831848812867-1049529247625119123?l=python-opengl-examples.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://python-opengl-examples.blogspot.com/feeds/1049529247625119123/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://python-opengl-examples.blogspot.com/2009/05/projective-texture-mapping.html#comment-form' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1654533831848812867/posts/default/1049529247625119123'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1654533831848812867/posts/default/1049529247625119123'/><link rel='alternate' type='text/html' href='http://python-opengl-examples.blogspot.com/2009/05/projective-texture-mapping.html' title='Projective Texture Mapping'/><author><name>basti_79</name><uri>http://www.blogger.com/profile/03249856320601693214</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_v-eQ6-W94RU/Sf3MjrXQVbI/AAAAAAAAABg/6cEkaLIFjZ0/s72-c/projection00927.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1654533831848812867.post-6717406453949424367</id><published>2009-04-29T11:36:00.000-07:00</published><updated>2009-04-29T12:49:39.511-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lighting'/><category scheme='http://www.blogger.com/atom/ns#' term='Shaders'/><category scheme='http://www.blogger.com/atom/ns#' term='Misconception'/><title type='text'>Basic Shading</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_v-eQ6-W94RU/Sfijv-DEoHI/AAAAAAAAABY/83uqikaEtUo/s1600-h/shaders00303.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 240px;" src="http://2.bp.blogspot.com/_v-eQ6-W94RU/Sfijv-DEoHI/AAAAAAAAABY/83uqikaEtUo/s320/shaders00303.jpg" alt="" id="BLOGGER_PHOTO_ID_5330190203498045554" border="0"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-a53fc6fff83971de" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v20.nonxt3.googlevideo.com/videoplayback?id%3Da53fc6fff83971de%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1331064281%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D52886B0E0A2A519A68DC0496E86569A7BDF34C.64B6D300653DBC40ABC83F2A6CF0F8C57B824CE0%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Da53fc6fff83971de%26offsetms%3D5000%26itag%3Dw160%26sigh%3D8e6zGYxQZiOaS8dq9mGdboLhJWw&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="320" height="266" bgcolor="#FFFFFF"flashvars="flvurl=http://v20.nonxt3.googlevideo.com/videoplayback?id%3Da53fc6fff83971de%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1331064281%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D52886B0E0A2A519A68DC0496E86569A7BDF34C.64B6D300653DBC40ABC83F2A6CF0F8C57B824CE0%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Da53fc6fff83971de%26offsetms%3D5000%26itag%3Dw160%26sigh%3D8e6zGYxQZiOaS8dq9mGdboLhJWw&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;The following script demonstrates basic shading. A Vertex Shader and a Fragment (Pixel) Shader are defined. Vertex shaders are necissary to transfer important data to the Pixel shader which isn't accessible otherwise. A display list is used to keep the number of calls low. A (moving) light source position is transferred from python to GLSL via the GL_LIGHT0 variables. &lt;br /&gt;&lt;br /&gt;I think it is curious to call the (implicit) cosine (in GLSL "dot(L,N)") "Lambert's law", which is &lt;a href="http://www.opengl.org/sdk/docs/tutorials/ClockworkCoders/lighting.php"&gt;occasionally&lt;/a&gt; the &lt;a href="http://www.lighthouse3d.com/opengl/glsl/index.php?ogldir1"&gt;case&lt;/a&gt;. Lambert's law states that a glowing surface will look the same from every angle. This is implicit in that the color of a fragment will not change depending on the viewing angle (except if you specify it to do so). The point in this dot product is that a face will appear dimmer when struck by light at an acute angle, because it will span less of a solid angle viewed from the light source. This is &lt;b&gt;not&lt;/b&gt; the opposite of Lambert's law or something.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;&lt;br /&gt;# Pygame/PyopenGL example by Bastiaan Zapf, Apr 2009&lt;br /&gt;#&lt;br /&gt;# Draw a range of cubes, light them prettily&lt;br /&gt;#&lt;br /&gt;# Employed techniques: &lt;br /&gt;#&lt;br /&gt;# - Vertex and Fragment shaders&lt;br /&gt;# - Lightsource variables&lt;br /&gt;# - Display Lists&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;from OpenGL.GL import *&lt;br /&gt;from OpenGL.GLU import *&lt;br /&gt;import random&lt;br /&gt;from math import * # trigonometry&lt;br /&gt;&lt;br /&gt;import pygame # just to get a display&lt;br /&gt;&lt;br /&gt;import Image&lt;br /&gt;import sys&lt;br /&gt;import time&lt;br /&gt;&lt;br /&gt;# get an OpenGL surface&lt;br /&gt;&lt;br /&gt;pygame.init() &lt;br /&gt;pygame.display.set_mode((800,600), pygame.OPENGL|pygame.DOUBLEBUF)&lt;br /&gt;&lt;br /&gt;def jpg_file_write(name, number, data):&lt;br /&gt;    im = Image.frombuffer("RGBA", (800,600), data, "raw", "RGBA", 0, 0)&lt;br /&gt;    fnumber = "%05d" % number&lt;br /&gt;    im.save(name + fnumber + ".jpg")&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;glEnable(GL_DEPTH_TEST)&lt;br /&gt;&lt;br /&gt;# Create and Compile a shader&lt;br /&gt;# but fail with a meaningful message if something goes wrong&lt;br /&gt;&lt;br /&gt;def createAndCompileShader(type,source):&lt;br /&gt;    shader=glCreateShader(type)&lt;br /&gt;    glShaderSource(shader,source)&lt;br /&gt;    glCompileShader(shader)&lt;br /&gt;&lt;br /&gt;    # get "compile status" - glCompileShader will not fail with &lt;br /&gt;    # an exception in case of syntax errors&lt;br /&gt;&lt;br /&gt;    result=glGetShaderiv(shader,GL_COMPILE_STATUS)&lt;br /&gt;&lt;br /&gt;    if (result!=1): # shader didn't compile&lt;br /&gt;        raise Exception("Couldn't compile shader\nShader compilation Log:\n"+glGetShaderInfoLog(shader))&lt;br /&gt;    return shader&lt;br /&gt;&lt;br /&gt;# Create and Compile fragment and vertex shaders&lt;br /&gt;# Transfer data from fragment to vertex shader&lt;br /&gt;&lt;br /&gt;vertex_shader=createAndCompileShader(GL_VERTEX_SHADER,"""&lt;br /&gt;varying vec3 v;&lt;br /&gt;varying vec3 N;&lt;br /&gt;&lt;br /&gt;void main(void)&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;   v = gl_ModelViewMatrix * gl_Vertex;&lt;br /&gt;   N = gl_NormalMatrix * gl_Normal;&lt;br /&gt;&lt;br /&gt;   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;""");&lt;br /&gt;&lt;br /&gt;fragment_shader=createAndCompileShader(GL_FRAGMENT_SHADER,"""&lt;br /&gt;varying vec3 N;&lt;br /&gt;varying vec3 v;&lt;br /&gt;&lt;br /&gt;void main(void)&lt;br /&gt;{&lt;br /&gt;   vec3 L = gl_LightSource[0].position.xyz-v;&lt;br /&gt;&lt;br /&gt;   // "Lambert's law"? (see notes)&lt;br /&gt;   // Rather: faces will appear dimmer when struck in an acute angle&lt;br /&gt;   // distance attenuation&lt;br /&gt;&lt;br /&gt;   float Idiff = max(dot(normalize(L),N),0.0)*pow(length(L),-2.0); &lt;br /&gt;&lt;br /&gt;   gl_FragColor = vec4(0.5,0,0.5,1.0)+ // purple&lt;br /&gt;                  vec4(1.0,1.0,1.0,1.0)*Idiff; // diffuse reflection&lt;br /&gt;}&lt;br /&gt;""");&lt;br /&gt;&lt;br /&gt;# build shader program&lt;br /&gt;&lt;br /&gt;program=glCreateProgram()&lt;br /&gt;glAttachShader(program,vertex_shader)&lt;br /&gt;glAttachShader(program,fragment_shader)&lt;br /&gt;glLinkProgram(program)&lt;br /&gt;&lt;br /&gt;# try to activate/enable shader program&lt;br /&gt;# handle errors wisely&lt;br /&gt;&lt;br /&gt;try:&lt;br /&gt;    glUseProgram(program)   &lt;br /&gt;except OpenGL.error.GLError:&lt;br /&gt;    print glGetProgramInfoLog(program)&lt;br /&gt;    raise&lt;br /&gt;&lt;br /&gt;done = False&lt;br /&gt;&lt;br /&gt;t=0 &lt;br /&gt;&lt;br /&gt;# load a cube into a display list&lt;br /&gt;&lt;br /&gt;glNewList(1,GL_COMPILE)&lt;br /&gt;&lt;br /&gt;glBegin(GL_QUADS)&lt;br /&gt;&lt;br /&gt;glColor3f(1,1,1)&lt;br /&gt;&lt;br /&gt;glNormal3f(0,0,-1)&lt;br /&gt;glVertex3f( -1, -1, -1)&lt;br /&gt;glVertex3f(  1, -1, -1)&lt;br /&gt;glVertex3f(  1,  1, -1)&lt;br /&gt;glVertex3f( -1,  1, -1)&lt;br /&gt;&lt;br /&gt;glNormal3f(0,0,1)&lt;br /&gt;glVertex3f( -1, -1,  1)&lt;br /&gt;glVertex3f(  1, -1,  1)&lt;br /&gt;glVertex3f(  1,  1,  1)&lt;br /&gt;glVertex3f( -1,  1,  1)&lt;br /&gt;&lt;br /&gt;glNormal3f(0,-1,0) &lt;br /&gt;glVertex3f( -1, -1, -1)&lt;br /&gt;glVertex3f(  1, -1, -1)&lt;br /&gt;glVertex3f(  1, -1,  1)&lt;br /&gt;glVertex3f( -1, -1,  1)&lt;br /&gt;&lt;br /&gt;glNormal3f(0,1,0) &lt;br /&gt;glVertex3f( -1,  1, -1)&lt;br /&gt;glVertex3f(  1,  1, -1)&lt;br /&gt;glVertex3f(  1,  1,  1)&lt;br /&gt;glVertex3f( -1,  1,  1)&lt;br /&gt;&lt;br /&gt;glNormal3f(-1,0,0)     &lt;br /&gt;glVertex3f( -1, -1, -1)&lt;br /&gt;glVertex3f( -1,  1, -1)&lt;br /&gt;glVertex3f( -1,  1,  1)&lt;br /&gt;glVertex3f( -1, -1,  1)                      &lt;br /&gt;&lt;br /&gt;glNormal3f(1,0,0)        &lt;br /&gt;glVertex3f(  1, -1, -1)&lt;br /&gt;glVertex3f(  1,  1, -1)&lt;br /&gt;glVertex3f(  1,  1,  1)&lt;br /&gt;glVertex3f(  1, -1,  1)&lt;br /&gt;&lt;br /&gt;glEnd()&lt;br /&gt;glEndList()&lt;br /&gt;&lt;br /&gt;while not done:&lt;br /&gt;&lt;br /&gt;    t=t+1&lt;br /&gt;&lt;br /&gt;    glMatrixMode(GL_PROJECTION)&lt;br /&gt;    glLoadIdentity()&lt;br /&gt;    gluPerspective(90,1,0.01,1000)&lt;br /&gt;    gluLookAt(sin(t/260.0)*4,cos(t/260.0)*4,cos(t/687.0)*3,0,0,0,0,1,0)&lt;br /&gt;    &lt;br /&gt;    glClearColor(0.0, 0.0, 0.0, 1.0)&lt;br /&gt;    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)&lt;br /&gt;&lt;br /&gt;    glMatrixMode(GL_MODELVIEW)&lt;br /&gt;&lt;br /&gt;    # calculate light source position&lt;br /&gt;&lt;br /&gt;    ld=[sin(t/16.0)*4.0,sin(t/20.0)*4.0,cos(t/16.0)*4.0]&lt;br /&gt;&lt;br /&gt;    # pass data to fragment shader&lt;br /&gt;&lt;br /&gt;    glLightfv(GL_LIGHT0,GL_POSITION,[ld[0],ld[1],ld[2]]);&lt;br /&gt;    &lt;br /&gt;    # fallback&lt;br /&gt;&lt;br /&gt;    glColor3f(1,1,1)&lt;br /&gt;&lt;br /&gt;    glLoadIdentity()&lt;br /&gt;    # render a pretty range of cubes&lt;br /&gt;&lt;br /&gt;    for i in range(-5,5):&lt;br /&gt;        for j in range(-5,5):&lt;br /&gt;            for k in range(-5,5):&lt;br /&gt;                glPushMatrix()&lt;br /&gt;                &lt;br /&gt;                glTranslate(i,j,k)&lt;br /&gt;                glScale(0.1,0.1,0.1)&lt;br /&gt;                glCallList(1)&lt;br /&gt;                glPopMatrix()&lt;br /&gt;&lt;br /&gt;    pygame.display.flip()&lt;br /&gt;&lt;/code&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1654533831848812867-6717406453949424367?l=python-opengl-examples.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=a53fc6fff83971de&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://python-opengl-examples.blogspot.com/feeds/6717406453949424367/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://python-opengl-examples.blogspot.com/2009/04/basic-shading.html#comment-form' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1654533831848812867/posts/default/6717406453949424367'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1654533831848812867/posts/default/6717406453949424367'/><link rel='alternate' type='text/html' href='http://python-opengl-examples.blogspot.com/2009/04/basic-shading.html' title='Basic Shading'/><author><name>basti_79</name><uri>http://www.blogger.com/profile/03249856320601693214</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_v-eQ6-W94RU/Sfijv-DEoHI/AAAAAAAAABY/83uqikaEtUo/s72-c/shaders00303.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1654533831848812867.post-3257089650640651535</id><published>2009-04-11T13:15:00.000-07:00</published><updated>2009-04-11T13:44:21.793-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Render to Texture'/><category scheme='http://www.blogger.com/atom/ns#' term='Framebuffer'/><title type='text'>Render to Texture</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_v-eQ6-W94RU/SeD9zr4yzHI/AAAAAAAAABQ/xbZcT_FignA/s1600-h/rtt00023.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_v-eQ6-W94RU/SeD9zr4yzHI/AAAAAAAAABQ/xbZcT_FignA/s320/rtt00023.jpg" alt="" id="BLOGGER_PHOTO_ID_5323533823948016754" border="0"&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-25c8b6532de8f41" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v16.nonxt1.googlevideo.com/videoplayback?id%3D025c8b6532de8f41%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1331064281%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D59510D6565EA85993EA45B6F00AF7AF43D81402D.5312BF7E2A334DB297A8CBEA893334351E8394E%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D25c8b6532de8f41%26offsetms%3D5000%26itag%3Dw160%26sigh%3DMeP6oiyL8CGaZRQ2s0_JFXRZxHo&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="320" height="266" bgcolor="#FFFFFF"flashvars="flvurl=http://v16.nonxt1.googlevideo.com/videoplayback?id%3D025c8b6532de8f41%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1331064281%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D59510D6565EA85993EA45B6F00AF7AF43D81402D.5312BF7E2A334DB297A8CBEA893334351E8394E%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3D25c8b6532de8f41%26offsetms%3D5000%26itag%3Dw160%26sigh%3DMeP6oiyL8CGaZRQ2s0_JFXRZxHo&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;This Program demonstrates a "render to texture" effect. It uses the "Framebuffer Management"-Technique, which has superseded the "Render to Back buffer, GlCopyImage2D, Overwrite Back buffer"-Technique for a few years now.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;# Pygame/PyopenGL example by Bastiaan Zapf, Apr 2009&lt;br /&gt;#&lt;br /&gt;# "Render to Texture" demonstration: Render a helix to a&lt;br /&gt;# texture and project it onto the faces of a cube pattern.&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;from OpenGL.GL import *&lt;br /&gt;from OpenGL.GLU import *&lt;br /&gt;&lt;br /&gt;from OpenGL.GL.ARB.framebuffer_object import *&lt;br /&gt;from OpenGL.GL.EXT.framebuffer_object import *&lt;br /&gt;&lt;br /&gt;from ctypes import *&lt;br /&gt;&lt;br /&gt;from math import *&lt;br /&gt;import pygame&lt;br /&gt;&lt;br /&gt;pygame.init()&lt;br /&gt;&lt;br /&gt;pygame.display.set_mode((800,600), pygame.OPENGL|pygame.DOUBLEBUF)&lt;br /&gt;&lt;br /&gt;glClearColor(0.0, 0.0, 0.0, 1.0)&lt;br /&gt;glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)&lt;br /&gt;&lt;br /&gt;glMatrixMode(GL_MODELVIEW);&lt;br /&gt;&lt;br /&gt;done = False&lt;br /&gt;&lt;br /&gt;t=0&lt;br /&gt;&lt;br /&gt;while not done:&lt;br /&gt;&lt;br /&gt;    # step time&lt;br /&gt;&lt;br /&gt;    t=t+1&lt;br /&gt;&lt;br /&gt;    # render a helix (this is similar to the previous example, but &lt;br /&gt;    # this time we'll render to a texture)&lt;br /&gt;&lt;br /&gt;    # initialize projection&lt;br /&gt;&lt;br /&gt;    glClearColor(0.0, 0.0, 0.0, 1.0)&lt;br /&gt;    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)&lt;br /&gt;&lt;br /&gt;    glMatrixMode(GL_PROJECTION);    &lt;br /&gt;    glLoadIdentity()&lt;br /&gt;&lt;br /&gt;    gluPerspective(90,1,0.01,1000)&lt;br /&gt;    gluLookAt(sin(t/200.0)*2,sin(t/500.0)*2,cos(t/200.0)*2,0,0,0,0,1,0)&lt;br /&gt;    glMatrixMode(GL_MODELVIEW)&lt;br /&gt;&lt;br /&gt;    # generate the texture we render to, and set parameters&lt;br /&gt;&lt;br /&gt;    rendertarget=glGenTextures( 1 )&lt;br /&gt;&lt;br /&gt;    glBindTexture( GL_TEXTURE_2D, rendertarget );&lt;br /&gt;    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );&lt;br /&gt;    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,&lt;br /&gt;                     GL_REPEAT);&lt;br /&gt;    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,&lt;br /&gt;                     GL_REPEAT );&lt;br /&gt;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)&lt;br /&gt;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)&lt;br /&gt;&lt;br /&gt;    # occupy 512x512 texture memory&lt;br /&gt;&lt;br /&gt;    glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA,512,512,0,GL_RGBA,&lt;br /&gt;                 GL_UNSIGNED_INT, None)&lt;br /&gt;&lt;br /&gt;    # This is the interesting part: render-to-texture is initialized here&lt;br /&gt;&lt;br /&gt;    # generate a "Framebuffer" object and bind it&lt;br /&gt;&lt;br /&gt;    fbo=c_uint(1) # WTF? Did not find a way to get there easier&lt;br /&gt;                  # A simple number would always result in a "Segmentation &lt;br /&gt;                  # Fault" for me&lt;br /&gt;    glGenFramebuffers(1,fbo)&lt;br /&gt;    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);&lt;br /&gt;&lt;br /&gt;    # render to the texture&lt;br /&gt;&lt;br /&gt;    glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, &lt;br /&gt;                              GL_TEXTURE_2D, rendertarget, 0);&lt;br /&gt;&lt;br /&gt;    # In case of errors or suspect behaviour, try this:&lt;br /&gt;    #    print "Framebuffer Status:"&lt;br /&gt;    #    print glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);&lt;br /&gt;&lt;br /&gt;    # Save Viewport configuration&lt;br /&gt;&lt;br /&gt;    glPushAttrib(GL_VIEWPORT_BIT);&lt;br /&gt;&lt;br /&gt;    # Align viewport to Texture dimensions - Try rendering &lt;br /&gt;    # to different dimensions than the texture has to find out &lt;br /&gt;    # about how your hardware handles display pitch&lt;br /&gt;&lt;br /&gt;    glViewport(0, 0, 512, 512);&lt;br /&gt;&lt;br /&gt;    glEnable(GL_BLEND);&lt;br /&gt;    glBlendFunc (GL_SRC_ALPHA, GL_ONE);&lt;br /&gt;&lt;br /&gt;    # Black background for the Helix&lt;br /&gt;&lt;br /&gt;    glClearColor(0.0, 0.0, 0.0, 0.0)&lt;br /&gt;    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)&lt;br /&gt;&lt;br /&gt;    # Fallback to white&lt;br /&gt;&lt;br /&gt;    glColor4f(1,1,1,1);&lt;br /&gt;&lt;br /&gt;    # But try a fancy texture&lt;br /&gt;&lt;br /&gt;    texture=glGenTextures( 1 )&lt;br /&gt;&lt;br /&gt;    glBindTexture( GL_TEXTURE_2D, texture );&lt;br /&gt;    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );&lt;br /&gt;    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,&lt;br /&gt;                     GL_REPEAT);&lt;br /&gt;    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,&lt;br /&gt;                     GL_REPEAT );&lt;br /&gt;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)&lt;br /&gt;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)&lt;br /&gt;&lt;br /&gt;    texdata=[[[1.0,0,0,1],&lt;br /&gt;              [1.0,1,1,1],&lt;br /&gt;              [0.0,1,0,1],&lt;br /&gt;              [1.0,1,1,1]],&lt;br /&gt;             [[1.0,0,0,1],&lt;br /&gt;              [1.0,0,0,1],&lt;br /&gt;              [1.0,0,0,0.5],&lt;br /&gt;              [0.0,0,0,1]],&lt;br /&gt;             [[0.0,1,0,1],&lt;br /&gt;              [0.0,0,0,0],&lt;br /&gt;              [0.0,0,1,1],&lt;br /&gt;              [0.0,0,0,0]],&lt;br /&gt;             [[0.0,0,0,1],&lt;br /&gt;              [0.0,0,0,1],&lt;br /&gt;              [0.0,0,0,1],&lt;br /&gt;              [0.0,0,0,1]]];&lt;br /&gt;&lt;br /&gt;    glTexImage2Df(GL_TEXTURE_2D, 0,4,0,GL_RGBA,&lt;br /&gt;                  texdata)&lt;br /&gt;&lt;br /&gt;    glEnable( GL_TEXTURE_2D );&lt;br /&gt;    glBindTexture( GL_TEXTURE_2D, texture );&lt;br /&gt;&lt;br /&gt;    # The helix&lt;br /&gt;&lt;br /&gt;    glBegin(GL_TRIANGLE_STRIP);&lt;br /&gt;&lt;br /&gt;    for i in range(0,100):&lt;br /&gt;&lt;br /&gt;        r=5.0;&lt;br /&gt;        if (i%2==0):&lt;br /&gt;            glTexCoord2f(0,i);&lt;br /&gt;            glVertex3f( cos(i/r)*1.5, -2.5+i*0.05, sin(i/r)*1.5);&lt;br /&gt;        else:&lt;br /&gt;            glTexCoord2f(1,i);&lt;br /&gt;            glVertex3f( cos(i/r+2)*1.5, -2.5+i*0.05, sin(i/r+2)*1.5);&lt;br /&gt;        &lt;br /&gt;&lt;br /&gt;    glEnd();&lt;br /&gt;    glPopAttrib(); # Reset viewport to screen format&lt;br /&gt;    # do not render to texture anymore - "switch off" rtt&lt;br /&gt;    glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); &lt;br /&gt;&lt;br /&gt;    glDisable( GL_BLEND );&lt;br /&gt;    glEnable( GL_TEXTURE_2D );&lt;br /&gt;    glEnable( GL_DEPTH_TEST );&lt;br /&gt;&lt;br /&gt;    glMatrixMode(GL_PROJECTION);    &lt;br /&gt;    glLoadIdentity()&lt;br /&gt;&lt;br /&gt;    gluPerspective(90,1,0.01,1000)&lt;br /&gt;&lt;br /&gt;    gluLookAt(-1.4+sin(t/100.0)*2.5,&lt;br /&gt;               -1.4+sin(t/90.0)*0.4,&lt;br /&gt;               -1.4+sin(t/100.0+3.14)*0.5,&lt;br /&gt;               0,0,0,&lt;br /&gt;               0,1,0)&lt;br /&gt;&lt;br /&gt;    glMatrixMode(GL_MODELVIEW);    &lt;br /&gt;&lt;br /&gt;    # use the rendered texture from above!&lt;br /&gt;    glBindTexture( GL_TEXTURE_2D, rendertarget ); &lt;br /&gt;&lt;br /&gt;    glBegin(GL_QUADS)&lt;br /&gt;    glColor3f(1,1,1) # fallback&lt;br /&gt;&lt;br /&gt;    # render a range of half cubes&lt;br /&gt;&lt;br /&gt;    for x in range(-2,3,2):&lt;br /&gt;        for y in range(-2,3,2):&lt;br /&gt;            glTexCoord2f(0,0);&lt;br /&gt;            glVertex3f(-1-x, -1+x+y, 1-y) &lt;br /&gt;            glTexCoord2f(0,1);&lt;br /&gt;            glVertex3f(-1-x, 1+x+y, 1-y) &lt;br /&gt;            glTexCoord2f(1,1);&lt;br /&gt;            glVertex3f(1-x, 1+x+y, 1-y) &lt;br /&gt;            glTexCoord2f(1,0);&lt;br /&gt;            glVertex3f(1-x, -1+x+y, 1-y) &lt;br /&gt;&lt;br /&gt;            glTexCoord2f(1,1);&lt;br /&gt;            glVertex3f(1-x,-1+x+y, -1-y) &lt;br /&gt;            glTexCoord2f(1,0);&lt;br /&gt;            glVertex3f(1-x,-1+x+y, 1-y) &lt;br /&gt;            glTexCoord2f(0,0);&lt;br /&gt;            glVertex3f(1-x,1+x+y, 1-y) &lt;br /&gt;            glTexCoord2f(0,1);&lt;br /&gt;            glVertex3f(1-x,1+x+y, -1-y) &lt;br /&gt;&lt;br /&gt;            glTexCoord2f(1,1);&lt;br /&gt;            glVertex3f(-1-x,1+x+y, -1-y) &lt;br /&gt;            glTexCoord2f(0,1);&lt;br /&gt;            glVertex3f(-1-x,1+x+y, 1-y) &lt;br /&gt;            glTexCoord2f(0,0);&lt;br /&gt;            glVertex3f(1-x,1+x+y, 1-y) &lt;br /&gt;            glTexCoord2f(1,0);&lt;br /&gt;            glVertex3f(1-x,1+x+y, -1-y) &lt;br /&gt;&lt;br /&gt;    glEnd()&lt;br /&gt;    glFlush()&lt;br /&gt;&lt;br /&gt;    pygame.display.flip()&lt;br /&gt;&lt;br /&gt;    # do not leak any mem&lt;br /&gt;&lt;br /&gt;    glDeleteTextures(texture) &lt;br /&gt;    glDeleteTextures(rendertarget)&lt;br /&gt;    glDeleteFramebuffers(1,fbo)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1654533831848812867-3257089650640651535?l=python-opengl-examples.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=25c8b6532de8f41&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://python-opengl-examples.blogspot.com/feeds/3257089650640651535/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://python-opengl-examples.blogspot.com/2009/04/render-to-texture.html#comment-form' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1654533831848812867/posts/default/3257089650640651535'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1654533831848812867/posts/default/3257089650640651535'/><link rel='alternate' type='text/html' href='http://python-opengl-examples.blogspot.com/2009/04/render-to-texture.html' title='Render to Texture'/><author><name>basti_79</name><uri>http://www.blogger.com/profile/03249856320601693214</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_v-eQ6-W94RU/SeD9zr4yzHI/AAAAAAAAABQ/xbZcT_FignA/s72-c/rtt00023.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1654533831848812867.post-6826683024731553110</id><published>2009-04-04T06:31:00.000-07:00</published><updated>2009-04-04T06:36:33.305-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PIL'/><title type='text'>Screenshots from OpenGL</title><content type='html'>The shortest way I found to bring OpenGL screenshots to the hard drive is using the function "frombuffer" from the "imaging Library" "Image", which understands the same format that OpenGL outputs.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.pythonware.com/library/pil/handbook/image.htm"&gt;Documentation for Image&lt;/a&gt;&lt;br /&gt;&lt;a href="http://pyopengl.sourceforge.net/documentation/manual/glReadPixels.3G.html"&gt;Documentation for glReadPixels&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;screenshot = glReadPixels( 0,0, 800, 600, GL_RGBA, GL_UNSIGNED_BYTE)&lt;br /&gt;im = Image.frombuffer("RGBA", (800,600), screenshot, "raw", "RGBA", 0, 0)&lt;br /&gt;im.save("test.jpg")&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1654533831848812867-6826683024731553110?l=python-opengl-examples.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://python-opengl-examples.blogspot.com/feeds/6826683024731553110/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://python-opengl-examples.blogspot.com/2009/04/screenshots-from-opengl.html#comment-form' title='1 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1654533831848812867/posts/default/6826683024731553110'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1654533831848812867/posts/default/6826683024731553110'/><link rel='alternate' type='text/html' href='http://python-opengl-examples.blogspot.com/2009/04/screenshots-from-opengl.html' title='Screenshots from OpenGL'/><author><name>basti_79</name><uri>http://www.blogger.com/profile/03249856320601693214</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1654533831848812867.post-3097779802805915268</id><published>2009-04-04T06:24:00.000-07:00</published><updated>2009-04-04T06:29:42.093-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Bugs'/><title type='text'>Bizarro Error "AttributeError: __class__"</title><content type='html'>In case of errors of the following form:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;$ python test.py &lt;br /&gt;No handlers could be found for logger "OpenGL.arrays.arraydatatype"&lt;br /&gt;Traceback (most recent call last):&lt;br /&gt;  File "test.py", line 135, in &lt;module&gt;&lt;br /&gt;    jpg_file_write("helix/helix", t, glReadPixels( 0,0, 800, 600, GL_RGBA, GL_UNSIGNED_BYTE))&lt;br /&gt;  File "/var/lib/python-support/python2.5/OpenGL/GL/images.py", line 319, in glReadPixels&lt;br /&gt;    imageData = arrayType.dataPointer(array)&lt;br /&gt;  File "/var/lib/python-support/python2.5/OpenGL/arrays/arraydatatype.py", line 38, in dataPointer&lt;br /&gt;    return cls.getHandler(value).dataPointer( value )&lt;br /&gt;  File "/var/lib/python-support/python2.5/OpenGL/arrays/formathandler.py", line 17, in __call__&lt;br /&gt;    typ = value.__class__&lt;br /&gt;AttributeError: __class__&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Try to install the latest PyOpenGL package.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1654533831848812867-3097779802805915268?l=python-opengl-examples.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://python-opengl-examples.blogspot.com/feeds/3097779802805915268/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://python-opengl-examples.blogspot.com/2009/04/bizarro-error-attributeerror-class.html#comment-form' title='0 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1654533831848812867/posts/default/3097779802805915268'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1654533831848812867/posts/default/3097779802805915268'/><link rel='alternate' type='text/html' href='http://python-opengl-examples.blogspot.com/2009/04/bizarro-error-attributeerror-class.html' title='Bizarro Error &quot;AttributeError: __class__&quot;'/><author><name>basti_79</name><uri>http://www.blogger.com/profile/03249856320601693214</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1654533831848812867.post-1506651907538126060</id><published>2009-04-03T14:23:00.000-07:00</published><updated>2009-04-04T01:35:05.689-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PyOpenGL'/><category scheme='http://www.blogger.com/atom/ns#' term='PyGame'/><title type='text'>Rotating Helix</title><content type='html'>&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_v-eQ6-W94RU/SdaK8RihGfI/AAAAAAAAABI/F-Ef9IIw-Gs/s1600-h/helix.jpg"&gt;&lt;img style="margin: 0pt 0pt 10px 10px; cursor: pointer; width: 320px; height: 240px;" src="http://3.bp.blogspot.com/_v-eQ6-W94RU/SdaK8RihGfI/AAAAAAAAABI/F-Ef9IIw-Gs/s320/helix.jpg" alt="" id="BLOGGER_PHOTO_ID_5320592777889782258" border="0"&gt;&lt;/a&gt;&lt;br /&gt;&lt;object width="320" height="266" class="BLOG_video_class" id="BLOG_video-f0a1f49ac91074c4" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"&gt;&lt;param name="movie" value="http://www.youtube.com/get_player"&gt;&lt;param name="bgcolor" value="#FFFFFF"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="flashvars" value="flvurl=http://v20.nonxt4.googlevideo.com/videoplayback?id%3Df0a1f49ac91074c4%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1331064281%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D77AC1E7D71DA9BCBE941F86EFB9BBCC845611336.21C37A16595B604633133D0E1DC3AFF3D0C0E2FF%26key%3Dck1&amp;amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Df0a1f49ac91074c4%26offsetms%3D5000%26itag%3Dw160%26sigh%3Dwyi4O4-tVtprks0GkRoOAE2UDnQ&amp;amp;autoplay=0&amp;amp;ps=blogger"&gt;&lt;embed src="http://www.youtube.com/get_player" type="application/x-shockwave-flash"width="320" height="266" bgcolor="#FFFFFF"flashvars="flvurl=http://v20.nonxt4.googlevideo.com/videoplayback?id%3Df0a1f49ac91074c4%26itag%3D5%26app%3Dblogger%26ip%3D0.0.0.0%26ipbits%3D0%26expire%3D1331064281%26sparams%3Did,itag,ip,ipbits,expire%26signature%3D77AC1E7D71DA9BCBE941F86EFB9BBCC845611336.21C37A16595B604633133D0E1DC3AFF3D0C0E2FF%26key%3Dck1&amp;iurl=http://video.google.com/ThumbnailServer2?app%3Dblogger%26contentid%3Df0a1f49ac91074c4%26offsetms%3D5000%26itag%3Dw160%26sigh%3Dwyi4O4-tVtprks0GkRoOAE2UDnQ&amp;autoplay=0&amp;ps=blogger"allowFullScreen="true" /&gt;&lt;/object&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The following script will display a rotating Helix. It depends on both PyGame and PyOpenGL. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;It demonstrates:&lt;ul&gt;&lt;li&gt;Texturing&lt;/li&gt;&lt;li&gt;Blending (Alpha Channel)&lt;/li&gt;&lt;li&gt;Projection/Modelview Basics&lt;/li&gt;&lt;li&gt;Fun with Trigonometric Functions&lt;/li&gt;&lt;li&gt;Animation (Double Buffered)&lt;/li&gt;&lt;/ul&gt;It also demonstrates missing Optimisation:&lt;ul&gt;&lt;br /&gt;&lt;li&gt;The Texture does not have to be reloaded every frame. Animation (see comments for Variable "pulse") would be harder, but could be achieved by blending textures (or blending display data, if blending textures isn't possible)&lt;/li&gt;&lt;li&gt;The Helix vertex data could be stored in a Display List. However, we'd lose the possibility to modify the Helix. A vertex shader might be able to do that in the Graphics Controller.&lt;/li&gt;&lt;li&gt;The shown version might act as a template for coarse benchmarks. (eg. for answering the question "How many fps will I get when i Upload a 512x512 texture every frame?")&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;I hope someone will find this fun and educating. Read the comments to get some suggestions about what to toy with first. Comments welcome.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;# Pygame/PyopenGL example by Bastiaan Zapf, Apr 2009&lt;br /&gt;#&lt;br /&gt;# Draw an helix, wiggle it pleasantly&lt;br /&gt;#&lt;br /&gt;# Keywords: Alpha Blending, Textures, Animation, Double Buffer&lt;br /&gt;&lt;br /&gt;from OpenGL.GL import *&lt;br /&gt;from OpenGL.GLU import *&lt;br /&gt;&lt;br /&gt;from math import * # trigonometry&lt;br /&gt;&lt;br /&gt;import pygame # just to get a display&lt;br /&gt;&lt;br /&gt;# get an OpenGL surface&lt;br /&gt;&lt;br /&gt;pygame.init() &lt;br /&gt;pygame.display.set_mode((800,600), pygame.OPENGL|pygame.DOUBLEBUF)&lt;br /&gt;&lt;br /&gt;# How to catch errors here?&lt;br /&gt;&lt;br /&gt;done = False&lt;br /&gt;&lt;br /&gt;t=0&lt;br /&gt;&lt;br /&gt;while not done:&lt;br /&gt;&lt;br /&gt;    t=t+1&lt;br /&gt;    &lt;br /&gt;    # for fun comment out these two lines&lt;br /&gt;&lt;br /&gt;    glClearColor(0.0, 0.0, 0.0, 1.0)&lt;br /&gt;    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)&lt;br /&gt;&lt;br /&gt;    # Get a perspective at the helix&lt;br /&gt;&lt;br /&gt;    glMatrixMode(GL_PROJECTION);    &lt;br /&gt;&lt;br /&gt;    glLoadIdentity()&lt;br /&gt;    gluPerspective(90,1,0.01,1000)&lt;br /&gt;    gluLookAt(sin(t/200.0)*3,sin(t/500.0)*3,cos(t/200.0)*3,0,0,0,0,1,0)&lt;br /&gt;&lt;br /&gt;    # Draw the helix (this ought to be a display list call)&lt;br /&gt;&lt;br /&gt;    glMatrixMode(GL_MODELVIEW)&lt;br /&gt;&lt;br /&gt;    # get a texture (this ought not to be inside the inner loop)&lt;br /&gt;&lt;br /&gt;    texture=glGenTextures( 1 )&lt;br /&gt;&lt;br /&gt;    glBindTexture( GL_TEXTURE_2D, texture );&lt;br /&gt;    glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );&lt;br /&gt;&lt;br /&gt;    # set sane defaults for a plethora of potentially uninitialized&lt;br /&gt;    # variables&lt;br /&gt;&lt;br /&gt;    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,&lt;br /&gt;                     GL_REPEAT);&lt;br /&gt;    glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,&lt;br /&gt;                     GL_REPEAT );&lt;br /&gt;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)&lt;br /&gt;    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)&lt;br /&gt;&lt;br /&gt;    # a texture&lt;br /&gt;&lt;br /&gt;    #pulse = sin(t/30)*0.5+0.5 # try this one&lt;br /&gt;    pulse = 0&lt;br /&gt;&lt;br /&gt;    texdata=[[[0.0,0,1,1],&lt;br /&gt;              [0.0,0,0,0],&lt;br /&gt;              [0.0,1,0,1],&lt;br /&gt;              [0.0,0,0,0]],&lt;br /&gt;             [[0.0,0,0,0],&lt;br /&gt;              [pulse,pulse,pulse,1],&lt;br /&gt;              [pulse,pulse,pulse,1],&lt;br /&gt;              [0.0,0,0,0]],&lt;br /&gt;             [[0.0,1,0,1],&lt;br /&gt;              [1,pulse,pulse,1],&lt;br /&gt;              [pulse,pulse,0,1],&lt;br /&gt;              [0.0,0,0,0]],&lt;br /&gt;             [[0.0,0,0,0],&lt;br /&gt;              [0.0,0,0,0],&lt;br /&gt;              [0.0,0,0,0],&lt;br /&gt;              [0.0,0,0,0]]];&lt;br /&gt;&lt;br /&gt;    glTexImage2Df(GL_TEXTURE_2D, 0,4,0,GL_RGBA,&lt;br /&gt;                  texdata)&lt;br /&gt;&lt;br /&gt;    glEnable(GL_BLEND);&lt;br /&gt;    glBlendFunc (GL_SRC_ALPHA, GL_ONE); # XXX Why GL_ONE?&lt;br /&gt;# alternatively:&lt;br /&gt;#    glEnable(GL_DEPTH_TEST);&lt;br /&gt;&lt;br /&gt;    glEnable( GL_TEXTURE_2D );&lt;br /&gt;    # use the texture&lt;br /&gt;    glBindTexture( GL_TEXTURE_2D, texture );&lt;br /&gt;&lt;br /&gt;    # vertices &amp;amp; texture data&lt;br /&gt;&lt;br /&gt;    glBegin(GL_TRIANGLE_STRIP);&lt;br /&gt;&lt;br /&gt;    for i in range(0,100):&lt;br /&gt;&lt;br /&gt;        r=5.0 # try other values - integers as well&lt;br /&gt;        d=1   # try other values&lt;br /&gt;&lt;br /&gt;        if (i%2==0):&lt;br /&gt;            glTexCoord2f(0,i);&lt;br /&gt;            glVertex3f( cos(i/r), -2.5+i*0.05, sin(i/r));            &lt;br /&gt;#            glVertex3f( cos(i/r)*pulse2, -2.5+i*0.05, sin(i/r)*pulse2);&lt;br /&gt;        else:&lt;br /&gt;            glTexCoord2f(1,i);&lt;br /&gt;            glVertex3f( cos(i/r+3.14), -2.5+i*0.05+d, sin(i/r+3.14));&lt;br /&gt;#            glVertex3f( cos(i/r+3.14)*pulse2, -2.5+i*0.05+d+pulse2*1, sin(i/r+3.14)*pulse2);&lt;br /&gt;        &lt;br /&gt;&lt;br /&gt;    glEnd();&lt;br /&gt;&lt;br /&gt;    glFlush()&lt;br /&gt;&lt;br /&gt;    glDeleteTextures(texture)&lt;br /&gt;    pygame.display.flip()&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1654533831848812867-1506651907538126060?l=python-opengl-examples.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='enclosure' type='video/mp4' href='http://www.blogger.com/video-play.mp4?contentId=f0a1f49ac91074c4&amp;type=video%2Fmp4' length='0'/><link rel='replies' type='application/atom+xml' href='http://python-opengl-examples.blogspot.com/feeds/1506651907538126060/comments/default' title='Kommentare zum Post'/><link rel='replies' type='text/html' href='http://python-opengl-examples.blogspot.com/2009/04/rotating-helix.html#comment-form' title='2 Kommentare'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/1654533831848812867/posts/default/1506651907538126060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/1654533831848812867/posts/default/1506651907538126060'/><link rel='alternate' type='text/html' href='http://python-opengl-examples.blogspot.com/2009/04/rotating-helix.html' title='Rotating Helix'/><author><name>basti_79</name><uri>http://www.blogger.com/profile/03249856320601693214</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_v-eQ6-W94RU/SdaK8RihGfI/AAAAAAAAABI/F-Ef9IIw-Gs/s72-c/helix.jpg' height='72' width='72'/><thr:total>2</thr:total></entry></feed>
