Demo 10 of 13 in category Nopper
|  | 
| ## OpenGL 3.3 with GLEW - Example 11
 #
 # @author   Norbert Nopper norbert@nopper.tv
 # @version  1.0
 #
 # Homepage: https://github.com/McNopper/OpenGL
 #
 # Copyright Norbert Nopper
 #
 # Modified for Tcl3D by Paul Obermeier 2011/02/03
 # See www.tcl3d.org for the Tcl3D extension.
 
 package require Tk
 package require tcl3d
 
 # Font to be used in the Tk listbox.
 set g_Demo(listFont) {-family {Courier} -size 10}
 
 # Obtain the name of this script file.
 set g_Demo(scriptDir) [file dirname [info script]]
 
 # Window size.
 set g_Demo(winWidth)  640
 set g_Demo(winHeight) 480
 
 # Camera position.
 set g_Demo(camera) [tcl3dVectorFromArgs GLfloat -5.0 5.0 10.0]
 
 # Light.
 set g_Demo(light) [tcl3dVectorFromArgs GLfloat 0.0 0.0 10.0]
 
 # Shadow matrix.
 set g_Demo(shadowMatrix) [tcl3dVector GLfloat 16]
 
 # Projection matrix.
 set g_Demo(projection) [tcl3dVector GLfloat 16]
 
 # Move the cube along the minus z axis for making it visible. Also rotated.
 set g_Demo(modelView) [tcl3dVector GLfloat 16]
 
 # Move the cube along the minus z axis for making it visible. Also rotated.
 set g_Demo(modelViewBackground) [tcl3dVector GLfloat 16]
 
 # Move the cube along the minus z axis for making it visible. Also rotated.
 set g_Demo(modelViewShadow) [tcl3dVector GLfloat 16]
 
 # Move the cube along the minus z axis for making it visible. Also rotated.
 set g_Demo(modelViewShadowBackground) [tcl3dVector GLfloat 16]
 
 # The shadow texture size.
 set g_Demo(shadowTextureSize) 1024
 
 set g_Demo(angle) 0.0
 
 # A stop watch to get current time.
 set g_Demo(stopWatch) [tcl3dNewSwatch]
 tcl3dStartSwatch $g_Demo(stopWatch)
 set g_Demo(lastTime) [tcl3dLookupSwatch $g_Demo(stopWatch)]
 
 # Show errors occuring in the Togl callbacks.
 proc bgerror { msg } {
 tk_messageBox -icon error -type ok -message "Error: $msg\n\n$::errorInfo"
 ExitProg
 }
 
 # Print info message into widget a the bottom of the window.
 proc PrintInfo { msg } {
 if { [winfo exists .fr.info] } {
 .fr.info configure -text $msg
 }
 }
 
 proc Animate {} {
 global g_Demo
 
 .fr.toglwin postredisplay
 set g_Demo(animateId) [tcl3dAfterIdle Animate]
 }
 
 proc StartAnimation {} {
 global g_Demo
 
 if { ! [info exists g_Demo(animateId)] } {
 Animate
 tcl3dStartSwatch $g_Demo(stopWatch)
 }
 }
 
 proc StopAnimation {} {
 global g_Demo
 
 if { [info exists g_Demo(animateId)] } {
 after cancel $g_Demo(animateId)
 unset g_Demo(animateId)
 tcl3dStopSwatch $g_Demo(stopWatch)
 }
 }
 
 # Function for initialization.
 proc Init {} {
 global g_Demo
 
 # Matrix for the model
 set model [tcl3dVector GLfloat 16]
 set lightCamera [tcl3dVector GLfloat 3]
 
 set g_Demo(shadowTexture) [tcl3dVector GLuint 1]
 glGenTextures 1 $g_Demo(shadowTexture)
 
 glBindTexture GL_TEXTURE_2D [$g_Demo(shadowTexture) get 0]
 
 glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MIN_FILTER $::GL_NEAREST
 glTexParameteri GL_TEXTURE_2D GL_TEXTURE_MAG_FILTER $::GL_NEAREST
 glTexParameterf GL_TEXTURE_2D GL_TEXTURE_WRAP_S $::GL_CLAMP
 glTexParameterf GL_TEXTURE_2D GL_TEXTURE_WRAP_T $::GL_CLAMP
 
 glTexImage2D GL_TEXTURE_2D 0 $::GL_DEPTH_COMPONENT \
 $g_Demo(shadowTextureSize) $g_Demo(shadowTextureSize) \
 0 GL_DEPTH_COMPONENT GL_UNSIGNED_BYTE "NULL"
 
 glBindTexture GL_TEXTURE_2D 0
 
 set g_Demo(fbo) [tcl3dVector GLuint 1]
 glGenFramebuffers 1 $g_Demo(fbo)
 
 glBindFramebuffer GL_FRAMEBUFFER [$g_Demo(fbo) get 0]
 
 glDrawBuffer GL_NONE
 glReadBuffer GL_NONE
 
 glFramebufferTexture2D GL_FRAMEBUFFER GL_DEPTH_ATTACHMENT GL_TEXTURE_2D \
 [$g_Demo(shadowTexture) get 0] 0
 
 if { [glCheckFramebufferStatus $::GL_FRAMEBUFFER] != $::GL_FRAMEBUFFER_COMPLETE } {
 puts [format "GL_FRAMEBUFFER_COMPLETE error 0x%x" \
 [glCheckFramebufferStatus GL_FRAMEBUFFER]]
 }
 
 glClearDepth 1.0
 glEnable GL_DEPTH_TEST
 glEnable GL_CULL_FACE
 
 glBindFramebuffer GL_FRAMEBUFFER 0
 
 # Load the source of the shadow vertex shader.
 set vertexSource [tcl3dOglReadShaderFile [file join $g_Demo(scriptDir) "VertexShadow.vs"]]
 
 # Load the source of the shadow fragment shader.
 set fragmentSource [tcl3dOglReadShaderFile [file join $g_Demo(scriptDir) "FragmentShadow.fs"]]
 
 set g_Demo(programShadow) [tcl3dOglBuildProgram $vertexSource "" "" "" $fragmentSource]
 set programShadow [dict get $g_Demo(programShadow) program]
 
 set g_Demo(projectionShadowLocation) [glGetUniformLocation $programShadow "projectionMatrix"]
 set g_Demo(modelViewShadowLocation)  [glGetUniformLocation $programShadow "modelViewMatrix"]
 set g_Demo(vertexShadowLocation)     [glGetAttribLocation  $programShadow "vertex"]
 
 # Load the source of the vertex shader.
 set vertexSource [tcl3dOglReadShaderFile [file join $g_Demo(scriptDir) "Vertex.vs"]]
 
 # Load the source of the fragment shader.
 set fragmentSource [tcl3dOglReadShaderFile [file join $g_Demo(scriptDir) "Fragment.fs"]]
 
 set g_Demo(program) [tcl3dOglBuildProgram $vertexSource "" "" "" $fragmentSource]
 set program [dict get $g_Demo(program) program]
 
 set g_Demo(projectionLocation)    [glGetUniformLocation $program "projectionMatrix"]
 set g_Demo(modelViewLocation)     [glGetUniformLocation $program "modelViewMatrix"]
 set g_Demo(shadowMatrixLocation)  [glGetUniformLocation $program "shadowMatrix"]
 set g_Demo(shadowTextureLocation) [glGetUniformLocation $program "shadowTexture"]
 set g_Demo(colorLocation)         [glGetUniformLocation $program "shapeColor"]
 set g_Demo(lightLocation)         [glGetUniformLocation $program "lightDirection"]
 set g_Demo(vertexLocation)        [glGetAttribLocation  $program "vertex"]
 set g_Demo(normalLocation)        [glGetAttribLocation  $program "normal"]
 
 glUseProgram $program
 
 tcl3dLookAt [$g_Demo(camera) get 0] [$g_Demo(camera) get 1] [$g_Demo(camera) get 2] \
 0.0 0.0 0.0 0.0 1.0 0.0 $model
 tcl3dMatfTransformVector $g_Demo(light) $model $lightCamera
 
 glUniform3f $g_Demo(lightLocation) [$lightCamera get 0] [$lightCamera get 1] [$lightCamera get 2]
 glUniform1i $g_Demo(shadowTextureLocation) 0
 
 # Torus
 
 set g_Demo(vao) [tcl3dVector GLuint 1]
 glGenVertexArrays 1 $g_Demo(vao)
 glBindVertexArray [$g_Demo(vao) get 0]
 
 set torus [glusCreateTorus 0.5 1.0 32 32]
 set g_Demo(numberIndices) [dict get $torus numIndices]
 
 set g_Demo(vertices) [tcl3dVector GLuint 1]
 glGenBuffers 1 $g_Demo(vertices)
 glBindBuffer GL_ARRAY_BUFFER [$g_Demo(vertices) get 0]
 set vertexVec [dict get $torus vertexVec]
 glBufferData GL_ARRAY_BUFFER \
 [expr [dict get $torus numVertices]*4*[$vertexVec elemsize]] \
 $vertexVec GL_STATIC_DRAW
 
 set g_Demo(normals) [tcl3dVector GLuint 1]
 glGenBuffers 1 $g_Demo(normals)
 glBindBuffer GL_ARRAY_BUFFER [$g_Demo(normals) get 0]
 set normalVec [dict get $torus normalVec]
 glBufferData GL_ARRAY_BUFFER \
 [expr [dict get $torus numVertices]*3*[$vertexVec elemsize]] \
 $normalVec GL_STATIC_DRAW
 
 set g_Demo(indices) [tcl3dVector GLuint 1]
 glGenBuffers 1 $g_Demo(indices)
 glBindBuffer GL_ELEMENT_ARRAY_BUFFER [$g_Demo(indices) get 0]
 set indexVec [dict get $torus indexVec]
 glBufferData GL_ELEMENT_ARRAY_BUFFER \
 [expr [dict get $torus numIndices]*[$indexVec elemsize]] \
 $indexVec GL_STATIC_DRAW
 
 glusDestroyShape $torus
 
 glUseProgram $program
 
 tcl3dMatfIdentity $model
 tcl3dLookAt [$g_Demo(camera) get 0] [$g_Demo(camera) get 1] [$g_Demo(camera) get 2] \
 0.0 0.0 0.0 0.0 1.0 0.0 $g_Demo(modelView)
 tcl3dMatfMult $g_Demo(modelView) $model $g_Demo(modelView)
 
 glBindBuffer GL_ARRAY_BUFFER [$g_Demo(vertices) get 0]
 glVertexAttribPointer $g_Demo(vertexLocation) 4 GL_FLOAT GL_FALSE 0 "NULL"
 glEnableVertexAttribArray $g_Demo(vertexLocation)
 
 glBindBuffer GL_ARRAY_BUFFER [$g_Demo(normals) get 0]
 glVertexAttribPointer $g_Demo(normalLocation) 3 GL_FLOAT GL_FALSE 0 "NULL"
 glEnableVertexAttribArray $g_Demo(normalLocation)
 
 glBindTexture GL_TEXTURE_2D [$g_Demo(shadowTexture) get 0]
 
 set g_Demo(vaoShadow) [tcl3dVector GLuint 1]
 glGenVertexArrays 1 $g_Demo(vaoShadow)
 glBindVertexArray [$g_Demo(vaoShadow) get 0]
 
 glUseProgram $programShadow
 
 glBindBuffer GL_ARRAY_BUFFER [$g_Demo(vertices) get 0]
 glVertexAttribPointer $g_Demo(vertexShadowLocation) 4 GL_FLOAT GL_FALSE 0 "NULL"
 glEnableVertexAttribArray $g_Demo(vertexShadowLocation)
 
 glBindBuffer GL_ELEMENT_ARRAY_BUFFER [$g_Demo(indices) get 0]
 
 # Background plane
 
 set g_Demo(vaoBackground) [tcl3dVector GLuint 1]
 glGenVertexArrays 1 $g_Demo(vaoBackground)
 glBindVertexArray [$g_Demo(vaoBackground) get 0]
 
 set background [glusCreatePlane 10.0 10.0]
 set g_Demo(numberIndicesBackground) [dict get $background numIndices]
 
 set g_Demo(verticesBackground) [tcl3dVector GLuint 1]
 glGenBuffers 1 $g_Demo(verticesBackground)
 glBindBuffer GL_ARRAY_BUFFER [$g_Demo(verticesBackground) get 0]
 set vertexVec [dict get $background vertexVec]
 glBufferData GL_ARRAY_BUFFER \
 [expr [dict get $background numVertices]*4*[$vertexVec elemsize]] \
 $vertexVec GL_STATIC_DRAW
 
 set g_Demo(normalsBackground) [tcl3dVector GLuint 1]
 glGenBuffers 1 $g_Demo(normalsBackground)
 glBindBuffer GL_ARRAY_BUFFER [$g_Demo(normalsBackground) get 0]
 set normalVec [dict get $background normalVec]
 glBufferData GL_ARRAY_BUFFER \
 [expr [dict get $background numVertices]*3*[$vertexVec elemsize]] \
 $normalVec GL_STATIC_DRAW
 
 set g_Demo(indicesBackground) [tcl3dVector GLuint 1]
 glGenBuffers 1 $g_Demo(indicesBackground)
 glBindBuffer GL_ELEMENT_ARRAY_BUFFER [$g_Demo(indicesBackground) get 0]
 set indexVec [dict get $background indexVec]
 glBufferData GL_ELEMENT_ARRAY_BUFFER \
 [expr [dict get $background numIndices]*[$indexVec elemsize]] \
 $indexVec GL_STATIC_DRAW
 
 glusDestroyShape $background
 glUseProgram $program
 
 tcl3dMatfIdentity $model
 tcl3dLookAt [$g_Demo(camera) get 0] [$g_Demo(camera) get 1] [$g_Demo(camera) get 2] \
 0.0 0.0 0.0 0.0 1.0 0.0 $g_Demo(modelViewBackground)
 tcl3dMatfMult $g_Demo(modelViewBackground) $model $g_Demo(modelViewBackground)
 
 glBindBuffer GL_ARRAY_BUFFER [$g_Demo(verticesBackground) get 0]
 glVertexAttribPointer $g_Demo(vertexLocation) 4 GL_FLOAT GL_FALSE 0 "NULL"
 glEnableVertexAttribArray $g_Demo(vertexLocation)
 
 glBindBuffer GL_ARRAY_BUFFER [$g_Demo(normalsBackground) get 0]
 glVertexAttribPointer $g_Demo(normalLocation) 3 GL_FLOAT GL_FALSE 0 "NULL"
 glEnableVertexAttribArray $g_Demo(normalLocation)
 
 glBindTexture GL_TEXTURE_2D [$g_Demo(shadowTexture) get 0]
 
 set g_Demo(vaoShadowBackground) [tcl3dVector GLuint 1]
 glGenVertexArrays 1 $g_Demo(vaoShadowBackground)
 glBindVertexArray [$g_Demo(vaoShadowBackground) get 0]
 
 glUseProgram $program
 
 glBindBuffer GL_ARRAY_BUFFER [$g_Demo(verticesBackground) get 0]
 glVertexAttribPointer $g_Demo(vertexShadowLocation) 4 GL_FLOAT GL_FALSE 0 "NULL"
 glEnableVertexAttribArray $g_Demo(vertexShadowLocation)
 glBindBuffer GL_ELEMENT_ARRAY_BUFFER [$g_Demo(indicesBackground) get 0]
 
 $model delete
 $lightCamera delete
 }
 
 proc CreateCallback { toglwin } {
 glClearColor 0.0 0.0 0.0 0.0
 glClearDepth 1.0
 glEnable GL_DEPTH_TEST
 glEnable GL_CULL_FACE
 }
 
 proc ReshapeCallback { toglwin { w -1 } { h -1 } } {
 global g_Demo
 
 set w [$toglwin width]
 set h [$toglwin height]
 set g_Demo(winWidth)  $w
 set g_Demo(winHeight) $h
 
 if { ! $g_Demo(haveNeededVersion) } {
 return
 }
 
 set bias [tcl3dVectorFromArgs GLfloat \
 0.5 0.0 0.0 0.0 \
 0.0 0.5 0.0 0.0 \
 0.0 0.0 0.5 0.0 \
 0.5 0.5 0.5 1.0 \
 ]
 set model            [tcl3dVector GLfloat 16]
 set modelViewInverse [tcl3dVector GLfloat 16]
 
 glUseProgram [dict get $g_Demo(programShadow) program]
 
 tcl3dPerspective 40.0 1.0 1.0 100.0 $g_Demo(projection)
 
 set projectionAsList [tcl3dVectorToList $g_Demo(projection) 16]
 glUniformMatrix4fv $g_Demo(projectionShadowLocation) 1 GL_FALSE $projectionAsList
 
 tcl3dLookAt [$g_Demo(light) get 0] [$g_Demo(light) get 1] [$g_Demo(light) get 2] \
 0.0 0.0 0.0 0.0 1.0 0.0 $g_Demo(modelViewShadow)
 
 tcl3dMatfIdentity $g_Demo(shadowMatrix)
 tcl3dMatfMult $g_Demo(shadowMatrix) $bias                    $g_Demo(shadowMatrix)
 tcl3dMatfMult $g_Demo(shadowMatrix) $g_Demo(projection)      $g_Demo(shadowMatrix)
 tcl3dMatfMult $g_Demo(shadowMatrix) $g_Demo(modelViewShadow) $g_Demo(shadowMatrix)
 
 tcl3dMatfIdentity $model
 tcl3dLookAt [$g_Demo(camera) get 0] [$g_Demo(camera) get 1] [$g_Demo(camera) get 2] \
 0.0 0.0 0.0 0.0 1.0 0.0 $model
 
 tcl3dMatfInvert $model $modelViewInverse
 tcl3dMatfMult $g_Demo(shadowMatrix) $modelViewInverse $g_Demo(shadowMatrix)
 
 glUseProgram [dict get $g_Demo(program) program]
 
 tcl3dPerspective 40.0 [expr double($w)/double($h)] 1.0 100.0 $g_Demo(projection)
 
 set projectionAsList [tcl3dVectorToList $g_Demo(projection) 16]
 glUniformMatrix4fv $g_Demo(projectionLocation) 1 GL_FALSE $projectionAsList
 
 $model delete
 $modelViewInverse delete
 $bias delete
 }
 
 proc DisplayCallback { toglwin } {
 global g_Demo
 
 if { ! $g_Demo(haveNeededVersion) } {
 glClear [expr $::GL_COLOR_BUFFER_BIT | $::GL_DEPTH_BUFFER_BIT]
 $toglwin swapbuffer
 return
 }
 
 set model [tcl3dVector GLfloat 16]
 
 glBindFramebuffer GL_FRAMEBUFFER [$g_Demo(fbo) get 0]
 
 glColorMask GL_FALSE GL_FALSE GL_FALSE GL_FALSE
 
 glViewport 0 0 $g_Demo(shadowTextureSize) $g_Demo(shadowTextureSize)
 
 tcl3dMatfIdentity $model
 tcl3dMatfRotateY $g_Demo(angle) $model
 tcl3dLookAt [$g_Demo(light) get 0] [$g_Demo(light) get 1] [$g_Demo(light) get 2] \
 0.0 0.0 0.0 0.0 1.0 0.0 $g_Demo(modelViewShadow)
 tcl3dMatfMult $g_Demo(modelViewShadow) $model $g_Demo(modelViewShadow)
 
 tcl3dMatfIdentity $model
 tcl3dMatfTranslate 0.0 0.0 -5.0 $model
 tcl3dLookAt [$g_Demo(light) get 0] [$g_Demo(light) get 1] [$g_Demo(light) get 2] \
 0.0 0.0 0.0 0.0 1.0 0.0 $g_Demo(modelViewShadowBackground)
 tcl3dMatfMult $g_Demo(modelViewShadowBackground) $model $g_Demo(modelViewShadowBackground)
 
 glClear GL_DEPTH_BUFFER_BIT
 
 glUseProgram [dict get $g_Demo(programShadow) program]
 
 glBindVertexArray [$g_Demo(vaoShadowBackground) get 0]
 
 set modelViewShadowBackgroundAsList [tcl3dVectorToList $g_Demo(modelViewShadowBackground) 16]
 glUniformMatrix4fv $g_Demo(modelViewShadowLocation) 1 GL_FALSE $modelViewShadowBackgroundAsList
 
 glDrawElements GL_TRIANGLES $g_Demo(numberIndicesBackground) GL_UNSIGNED_INT "NULL"
 
 glBindVertexArray [$g_Demo(vaoShadow) get 0]
 
 set modelViewShadowAsList [tcl3dVectorToList $g_Demo(modelViewShadow) 16]
 glUniformMatrix4fv $g_Demo(modelViewShadowLocation) 1 GL_FALSE $modelViewShadowAsList
 
 glDrawElements GL_TRIANGLES $g_Demo(numberIndices) GL_UNSIGNED_INT "NULL"
 
 glBindFramebuffer GL_FRAMEBUFFER 0
 
 glColorMask GL_TRUE GL_TRUE GL_TRUE GL_TRUE
 
 glViewport 0 0 $g_Demo(winWidth) $g_Demo(winHeight)
 
 tcl3dMatfIdentity $model
 tcl3dMatfRotateY $g_Demo(angle) $model
 tcl3dLookAt [$g_Demo(camera) get 0] [$g_Demo(camera) get 1] [$g_Demo(camera) get 2] \
 0.0 0.0 0.0 0.0 1.0 0.0 $g_Demo(modelView)
 tcl3dMatfMult $g_Demo(modelView) $model $g_Demo(modelView)
 
 tcl3dMatfIdentity $model
 tcl3dMatfTranslate 0.0 0.0 -5.0 $model
 tcl3dLookAt [$g_Demo(camera) get 0] [$g_Demo(camera) get 1] [$g_Demo(camera) get 2] \
 0.0 0.0 0.0 0.0 1.0 0.0 $g_Demo(modelViewBackground)
 tcl3dMatfMult $g_Demo(modelViewBackground) $model $g_Demo(modelViewBackground)
 
 glClear [expr $::GL_COLOR_BUFFER_BIT | $::GL_DEPTH_BUFFER_BIT]
 
 glUseProgram [dict get $g_Demo(program) program]
 
 glBindVertexArray [$g_Demo(vaoBackground) get 0]
 
 set shadowMatrixAsList [tcl3dVectorToList $g_Demo(shadowMatrix) 16]
 glUniformMatrix4fv $g_Demo(shadowMatrixLocation) 1 GL_FALSE $shadowMatrixAsList
 
 set modelViewBackgroundAsList [tcl3dVectorToList $g_Demo(modelViewBackground) 16]
 glUniformMatrix4fv $g_Demo(modelViewLocation) 1 GL_FALSE $modelViewBackgroundAsList
 
 glUniform4f $g_Demo(colorLocation) 0.0 0.5 0.0 1.0
 
 glDrawElements GL_TRIANGLES $g_Demo(numberIndicesBackground) GL_UNSIGNED_INT "NULL"
 
 glBindVertexArray [$g_Demo(vao) get 0]
 
 glUniformMatrix4fv $g_Demo(shadowMatrixLocation) 1 GL_FALSE $shadowMatrixAsList
 
 set modelViewAsList [tcl3dVectorToList $g_Demo(modelView) 16]
 glUniformMatrix4fv $g_Demo(modelViewLocation) 1 GL_FALSE $modelViewAsList
 
 glUniform4f $g_Demo(colorLocation) 0.33 0.0 0.5 1.0
 
 glDrawElements GL_TRIANGLES $g_Demo(numberIndices) GL_UNSIGNED_INT "NULL"
 
 set curTime [tcl3dLookupSwatch $g_Demo(stopWatch)]
 set elapsedTime [expr $curTime - $g_Demo(lastTime)]
 set g_Demo(lastTime) $curTime
 
 set g_Demo(angle) [expr $g_Demo(angle) + 20.0 * $elapsedTime]
 
 $model delete
 $toglwin swapbuffer
 }
 
 proc Cleanup {} {
 global g_Demo
 
 if { [info exists g_Demo(vertices)] } {
 glDeleteBuffers 1 [$g_Demo(vertices) get 0]
 $g_Demo(vertices) delete
 }
 
 if { [info exists g_Demo(normals)] } {
 glDeleteBuffers 1 [$g_Demo(normals) get 0]
 $g_Demo(normals) delete
 }
 
 if { [info exists g_Demo(indices)] } {
 glDeleteBuffers 1 [$g_Demo(indices) get 0]
 $g_Demo(indices) delete
 }
 
 if { [info exists g_Demo(vao)] } {
 glDeleteVertexArrays 1 [$g_Demo(vao) get 0]
 $g_Demo(vao) delete
 }
 
 if { [info exists g_Demo(vaoShadow)] } {
 glDeleteVertexArrays 1 [$g_Demo(vaoShadow) get 0]
 $g_Demo(vaoShadow) delete
 }
 
 if { [info exists g_Demo(verticesBackground)] } {
 glDeleteBuffers 1 [$g_Demo(verticesBackground) get 0]
 $g_Demo(verticesBackground) delete
 }
 
 if { [info exists g_Demo(normalsBackground)] } {
 glDeleteBuffers 1 [$g_Demo(normalsBackground) get 0]
 $g_Demo(normalsBackground) delete
 }
 
 if { [info exists g_Demo(indicesBackground)] } {
 glDeleteBuffers 1 [$g_Demo(indicesBackground) get 0]
 $g_Demo(indicesBackground) delete
 }
 
 if { [info exists g_Demo(vaoBackground)] } {
 glDeleteVertexArrays 1 [$g_Demo(vaoBackground) get 0]
 $g_Demo(vaoBackground) delete
 }
 
 if { [info exists g_Demo(vaoShadowBackground)] } {
 glDeleteVertexArrays 1 [$g_Demo(vaoShadowBackground) get 0]
 $g_Demo(vaoShadowBackground) delete
 }
 
 if { [info exists g_Demo(fbo)] } {
 glDeleteFramebuffers 1 [$g_Demo(fbo) get 0]
 $g_Demo(fbo) delete
 }
 
 if { [info exists g_Demo(shadowTexture)] } {
 glDeleteRenderbuffers 1 [$g_Demo(shadowTexture) get 0]
 $g_Demo(shadowTexture) delete
 }
 
 if { [info exists g_Demo(program)] } {
 tcl3dOglDestroyProgram $g_Demo(program)
 }
 
 if { [info exists g_Demo(programShadow)] } {
 tcl3dOglDestroyProgram $g_Demo(programShadow)
 }
 
 tcl3dDeleteSwatch $g_Demo(stopWatch)
 
 # Unset all global variables.
 # Needed when running the demo in the Tcl3D presentation framework.
 foreach var [info globals g_*] {
 uplevel #0 unset $var
 }
 }
 
 # Put all exit related code here.
 proc ExitProg {} {
 exit
 }
 
 # Create the OpenGL window and some Tk helper widgets.
 proc CreateWindow {} {
 global g_Demo
 
 frame .fr
 pack .fr -expand 1 -fill both
 
 # Create a Togl window with an OpenGL core profile using version 3.3.
 # Reshape and Display callbacks are configured later after knowing if
 # the needed OpenGL profile version is available.
 togl .fr.toglwin -width $g_Demo(winWidth) -height $g_Demo(winHeight) \
 -double true -depth true -alpha true \
 -createcommand CreateCallback \
 -coreprofile true -major 3 -minor 3
 
 set g_Demo(haveNeededVersion) true
 set numRows 2
 set haveGL3 [tcl3dOglHaveVersion 3]
 if { ! $haveGL3 } {
 set msgStr [format \
 "Demo needs core profile 3.3. Only have GL version %s" \
 [tcl3dOglGetVersion]]
 set g_Demo(haveNeededVersion) false
 incr numRows
 } else {
 set profile [tcl3dOglGetProfile .fr.toglwin]
 if { [dict get $profile "coreprofile"] != true } {
 set msgStr [format \
 "Demo needs core profile 3.3. Only have compatibility profile %d.%d" \
 [dict get $profile "major"] \
 [dict get $profile "minor"]]
 incr numRows
 }
 }
 if { $g_Demo(haveNeededVersion) } {
 # If OpenGL 3.3 or higher is available, initialize the buffers.
 Init
 }
 
 # Now attach the Reshape and Display callbacks to the Togl window.
 .fr.toglwin configure \
 -reshapecommand ReshapeCallback \
 -displaycommand DisplayCallback
 
 listbox .fr.usage -font $g_Demo(listFont) -height $numRows
 label .fr.info
 grid .fr.toglwin -row 0 -column 0 -sticky news
 grid .fr.usage   -row 1 -column 0 -sticky news
 grid .fr.info    -row 2 -column 0 -sticky news
 grid rowconfigure .fr 0 -weight 1
 grid columnconfigure .fr 0 -weight 1
 wm title . "Tcl3D demo: Nopper's core profile tutorials (Example 11 - Shadow mapping)"
 
 # Watch for Esc key and Quit messages
 wm protocol . WM_DELETE_WINDOW "ExitProg"
 bind . <Key-Escape> "ExitProg"
 
 bind .fr.toglwin <1> "StartAnimation"
 bind .fr.toglwin <2> "StopAnimation"
 bind .fr.toglwin <3> "StopAnimation"
 bind .fr.toglwin <Control-Button-1> "StopAnimation"
 
 .fr.usage insert end "Key-Escape Exit"
 .fr.usage insert end "Mouse-L|MR Start|Stop animation"
 if { [info exists msgStr] } {
 .fr.usage insert end $msgStr
 .fr.usage itemconfigure end -background red
 } else {
 .fr.usage configure -state disabled
 }
 }
 
 CreateWindow
 ReshapeCallback .fr.toglwin
 
 PrintInfo [tcl3dOglGetInfoString]
 
 if { [file tail [info script]] eq [file tail $::argv0] } {
 # If started directly from tclsh or wish, then start animation.
 update
 StartAnimation
 }
 
 | 
