was quite impressed with this (technique) so ported it (mainly to see if stencil buffers actually were working!!)
Rem /* * Conway's Game of Life in OpenGL * Simon Green (simes@...) 3/00 * * This uses roughly the same algorithm described in the OpenGL * red book (p.590 in 3rd edition) to compute Life in the frame buffer: * * - Reads frame buffer contents to texture using CopyTexImage. * - Renders textured quad 8 times offset one pixel in each direction, * using alpha test and stencil buffer increment to count neighbours. * - Uses stencil test to determine deaths and births for next generation * * This is not very efficient (10 passes), but leaves results in texture map. * Requires stencil buffer, destination alpha. * */ 'bodged to work on max by Chris C EndRem Global winw:Int = 512, winh:Int = 512 Global lifew:Int = 512, lifeh:Int = 512 Global gen:Int = 0 Global animating:Int = 0 Global wraparound:Int = 1 Global alivecol:Float[] = [ 0.0, 1.0, 0.0, 1.0 ] Global deadcol:Float[]=[ 0.0, 0.0, 0.0, 0.0 ] SetGraphicsDriver GLGraphicsDriver() Graphics(winw,winh,0,0,GRAPHICS_STENCILBUFFER|GRAPHICS_ALPHABUFFER) glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); glReadBuffer(GL_FRONT); glDrawBuffer(GL_FRONT); glClearColor(0.0, 0.0, 0.0, 0.0); glClearStencil(0); glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, Float(winw), 0.0, Float(winh), -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glViewport(0.0, 0.0, Float(winw), Float(winh)); randdots() While Not KeyHit(KEY_ESCAPE) If AppTerminate() Then End If KeyDown(KEY_R) Then 'FlushKeys() randdots() EndIf generation() glFinish() Wend Function randdots() glColor4fv(alivecol) glBegin(GL_POINTS) For Local n:Int=1 To 10000 glvertex2f Rand(0,winw),Rand(0,winh) Next glend() glfinish() EndFunction Function drawQuad(x:Int, y:Int) glBegin(GL_QUADS) If wraparound Then ' // this is clever - use texture coordinate wrapping For edge wraparound Local tx:Float, ty:Float tx = Float(x) / Float(lifew) ty = Float(y) / Float(lifeh) glTexCoord2f(tx, ty) glVertex2i(0, 0) glTexCoord2f(tx + 1.0, ty) glVertex2i(lifew, 0) glTexCoord2f(tx + 1.0, ty + 1.0) glVertex2i(lifew, lifeh) glTexCoord2f(tx, ty + 1.0) glVertex2i(0, lifeh); Else glTexCoord2f(0.0, 0.0); glVertex2i(x, y); glTexCoord2f(1.0, 0.0); glVertex2i(x + lifew, y); glTexCoord2f(1.0, 1.0); glVertex2i(x + lifew, y + lifeh); glTexCoord2f(0.0, 1.0); glVertex2i(x, y + lifeh); EndIf glEnd() EndFunction Function generation() glClear(GL_STENCIL_BUFFER_BIT); ' /* read frame buffer To texture memory */ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 0, 0, lifew, lifeh, 0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable(GL_TEXTURE_2D); ' /* draw image 8 times offset with stencil To count neighbours */ glAlphaFunc(GL_GREATER, 0.0); '/* only write pixels with alpha > 0.0 */ glEnable(GL_ALPHA_TEST); glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); ' /* no need To write To color buffer */ glStencilFunc(GL_ALWAYS, 0, $ff); glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);' /* fail, zfail, zpass */ glEnable(GL_STENCIL_TEST); drawQuad(-1, -1); drawQuad( 0, -1); drawQuad( 1, -1); drawQuad(-1, 0); drawQuad( 1, 0); drawQuad(-1, 1); drawQuad( 0, 1); drawQuad( 1, 1); glDisable(GL_STENCIL_TEST); glDisable(GL_ALPHA_TEST); glDisable(GL_TEXTURE_2D); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); ' /* enable writes To color buffer */ ' // draw births (neighbours == 3) glStencilFunc(GL_EQUAL, 3, $ff); ' /* write And decr, only If stencil == 3 */ glStencilOp(GL_KEEP, GL_DECR, GL_DECR); '/* fail, zfail, zpass */ glEnable(GL_STENCIL_TEST); glColor4fv(alivecol); drawQuad(0, 0); ' // clear everything but survivors (neighbours == 2 Or 3) */ glStencilFunc(GL_NOTEQUAL, 2, $ff); '/* write only If stencil != 2 */ glColor4fv(deadcol); drawQuad(0, 0); glDisable(GL_STENCIL_TEST); ' checkErrors("generation"); gen:+1; EndFunction