// Update the scenegraph nodes and lights scene->graph()->updateAttachedEntities( delta, scene->lights() ); // Load the identity matrix so we can position our lights glLoadIdentity(); // Set up the ambient light GLColour ambient( 0, 0, 0, 1 ); scene->lights().getAmbient( ambient ); glLightModelfv( GL_LIGHT_MODEL_AMBIENT, &ambient.R ); // Enable depth testing glEnable( GL_DEPTH_TEST ); // Enable depth writes glDepthMask( true );
// Apply the camera pCamera->apply(); // Clear the buffer glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // Set the dof pass m_DepthPass->activate(); // RENDER THE SCENEGRAPH NODES // Unset the depth pass m_DepthPass->deactivate(); // Disable depth writes glDepthMask( false );
// Set up the diffuse pass m_DiffusePass->activate(); // Render the diffuse pass renderDiffusePass( scene, delta ); // Copy back m_DiffusePass->deactivate();
// Enable depth writes glDepthMask( true ); // Bind the pass m_MotionPass->activate(); // Render the motion vectors renderMotionPass( scene, delta ); // Upload m_MotionPass->deactivate(); // Unbind the textures unbindTextures();
m_LightScenePass->deactivate() as we will be modifying this pass further in the next two stages.
// Bind the lit scene pass
m_LitScenePass->activate();
And rendering the pass:
// Disable depth testing glDisable( GL_DEPTH_TEST ); // Disable depth writes glDepthMask( false ); // Reset the camera glMatrixMode( GL_PROJECTION ); glPushMatrix(); glLoadIdentity(); glMatrixMode( GL_MODELVIEW ); glPushMatrix(); glLoadIdentity(); // Use the shader m_LightShader->useProgram(); m_LightShader->update( m_Time, delta ); // Get the appropriate texture unit glActiveTextureARB( GL_TEXTURE0_ARB ); diffuse->bind(); glActiveTextureARB( GL_TEXTURE1_ARB ); lightpass->bind(); // Draw the quad renderFullScreenQuad(); // Enable depth writes glDepthMask( true ); // Enable depth testing glEnable( GL_DEPTH_TEST ); // Revert back to the old matrices glMatrixMode( GL_PROJECTION ); glPopMatrix(); glMatrixMode( GL_MODELVIEW ); glPopMatrix();
// Enable blending glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); // Apply the camera pCamera->apply();
For rendering the pass, see Rendering the Specular Pass.
// Enable blending glBlendFunc( GL_ONE, GL_ONE ); // RENDER EMISSIVE PASS // Disable blending glDisable( GL_BLEND ); // Deactivate the litscene pass m_LitScenePass->deactivate();
For rendering the pass, see Rendering the Emissive Pass.
resetCamera();
// Reset the viewport m_BlurV->activate(); // Clear the buffer glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // Use the shader m_BlurPrepShader->useProgram(); m_BlurPrepShader->update( m_Time, delta ); // Set the blur m_BlurPrepShader->getUniform( "threshold", temp ); m_BlurPrepShader->setUniform1f( temp, threshold ); // Get the appropriate texture unit glActiveTextureARB( GL_TEXTURE0_ARB ); glBindTexture( GL_TEXTURE_2D, m_LitScenePass->target()->id() ); // Draw the quad renderFullScreenQuad(); // Copy it m_BlurV->deactivate();
Now we render the horizontal and vertical blur passes. The code is similar to the above, only different targets and shaders are used. The final result is stored in the pass called m_BlurV. The shaders for this are blurpph.shader and blurppv.shader.
// Set the viewport GLPass::SetDefaultViewport( m_DiffusePass->target()->width(), m_DiffusePass->target()->height() ); // Bind the default texture glActiveTextureARB( GL_TEXTURE0_ARB ); glBindTexture( GL_TEXTURE_2D, m_LitScenePass->target()->id() ); // Set the depth buffer glActiveTextureARB( GL_TEXTURE1_ARB ); glBindTexture( GL_TEXTURE_2D, m_DepthPass->target()->id() );
// Activate the diffuse pass m_DiffusePass->activate(); // Use the DOF shader m_DOFShader->useProgram(); m_DOFShader->update( m_Time, delta ); // Set the bias m_DOFShader->getUniform( "bias", temp ); m_DOFShader->setUniform1f( temp, DOFbias ); m_DOFShader->getUniform( "blurclamp", temp ); m_DOFShader->setUniform1f( temp, DOFclamp ); // Draw the quad renderFullScreenQuad(); // Upload to the diffuse pass m_DiffusePass->deactivate();
// Bind the default texture glActiveTextureARB( GL_TEXTURE0_ARB ); glBindTexture( GL_TEXTURE_2D, m_DiffusePass->target()->id() ); // Use the shader m_PassCombineShader->useProgram(); m_PassCombineShader->update( m_Time, delta ); // Set the count variable m_PassCombineShader->getUniform( "count", temp ); m_PassCombineShader->setUniform1f( temp, 2 ); m_PassCombineShader->getUniform( "mult", temp ); m_PassCombineShader->setUniform1f( temp, 1 ); // Get the appropriate extra texture unit glActiveTextureARB( GL_TEXTURE1_ARB ); glBindTexture( GL_TEXTURE_2D, m_BlurV->target()->id() ); // Draw the quad renderFullScreenQuad();
And that's the end.
// Ignore if we haven't got a shadow shader if ( !m_WhiteShader ) return; // Clear to black glClear( GL_COLOR_BUFFER_BIT ); // Switch of colour writes glColorMask( false, false, false, false ); // This helps to reduce artefacts glPolygonOffset(8.0f, 4.0f); // This will reduce artefacts glEnable( GL_POLYGON_OFFSET_FILL ); // Get the scenegraph GLSceneGraph * graph = scene->graph(); // For each spot light... for ( uint i = 0; i < scene->lights().spotLightCount(); ++i ) { // Get the light const GLSpotLight * light = scene->lights().getSpotLight( i ); // Render the pass renderShadowPasses( graph, delta, light ); } // For each point light... for ( uint i = 0; i < scene->lights().pointLightCount(); ++i ) { // Get the light const GLPointLight * light = scene->lights().getPointLight( i ); // Render the pass renderShadowPasses( graph, delta, light ); } // Switch on colour writes glColorMask( true, true, true, true ); // Disable the offset fill glDisable( GL_POLYGON_OFFSET_FILL );
void Logic::renderShadowPasses( const GLSceneGraph * graph, float delta, const GLLight * light ) { // If it's not shadowed, ignore it if ( !light->shadowed() ) return; // The shadow map settings const GLRenderTarget * target = 0; // Get each shadow map for ( uint m = 0; m < light->shadowMapCount(); ++m ) { // Get the shadow target if ( FAILED( light->getShadowMapTarget( m, &target ) ) ) return; // Render the scene renderShadowPass( graph, delta, light, m, target ); // Reset the target target = 0; } }
void Logic::renderShadowPass( const GLSceneGraph * graph, float delta, const GLLight * light, uint map, const GLRenderTarget * target ) { GLGeometry * oldGeom = 0; GLShader * shader = m_ZShader; // Bind the target target->prepare(); // Get the matrices TBMath::CMatrix P, V; // Get the light's projection and view matrix light->getMatrices( map, V, P ); // Set the matices glMatrixMode( GL_PROJECTION ); glLoadMatrix( P ); glMatrixMode( GL_MODELVIEW ); glLoadMatrix( V ); // Clear the depth buffer glClear( GL_DEPTH_BUFFER_BIT ); // Draw the scenegraph for ( uint i = 0; i < (uint)graph->nodeCount(); ++i ) { // Get the node GLSceneGraphNode * node = graph->getNode( i ); // Get it's geometry GLGeometry * geometry = node->geometry(); // If it has no geometry, skip this node if ( !initRenderID( oldGeom, geometry, &oldGeom ) ) continue; // Set up the shader bindShader( shader, geometry, m_Time, delta ); // Render the geometry renderNode( node, geometry, shader ); // Finish shader->endVertexAttrs(); } // Copy to the target target->upload(); }
See Rendering a Cube Map.
const GLSceneGraph * graph = scene->graph(); // Load it glMatrixMode( GL_PROJECTION ); glLoadIdentity(); gluPerspective( 90, 1, 0.01f, 50.0f ); glMatrixMode( GL_MODELVIEW ); // Draw the scenegraph for ( uint i = 0; i < (uint)graph->nodeCount(); ++i ) { // Get the node GLSceneGraphNode * node = graph->getNode( i ); // Get the cubemap const GLCubeMapTarget * cube = node->cubeMapTarget(); // If there is no cubemap, skip if ( !cube ) continue; // Ignore this node m_IgnoreNode = i; // Get the position GLVector p = node->transform().matrix().Origin(); // Render this cube map renderCubeMap( scene, delta, cube, p ); } // Reset the ignore flag m_IgnoreNode = -1;
// For each face... for ( uint i = 0; i < viewCubeFace; ++i ) { // Clear the matrix glLoadIdentity(); // Look in the face's direction // Rotate so we are facing in the correct direction switch ( i ) { case GL_CUBEMAP_RIGHT: gluLookAt( p.x, p.y, p.z, p.x + 1, p.y , p.z , 0, 1, 0 ); break; // +x case GL_CUBEMAP_LEFT: gluLookAt( p.x, p.y, p.z, p.x - 1, p.y , p.z , 0, 1, 0 ); break; // -x case GL_CUBEMAP_UP: gluLookAt( p.x, p.y, p.z, p.x , p.y - 1, p.z , 0, 0, 1 ); break; // +y case GL_CUBEMAP_DOWN: gluLookAt( p.x, p.y, p.z, p.x , p.y + 1, p.z , 0, 0, 1 ); break; // -y case GL_CUBEMAP_FORWARD: gluLookAt( p.x, p.y, p.z, p.x , p.y , p.z + 1, 0, 1, 0 ); break; // -z . case GL_CUBEMAP_BACKWARD: gluLookAt( p.x, p.y, p.z, p.x , p.y , p.z - 1, 0, 1, 0 ); break; // +z . } // Clear the depth buffer glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); // Render the diffuse scene m_CubeMapFaces[0]->activate(); renderDiffusePass( scene, delta ); m_CubeMapFaces[0]->deactivate(); // Render the lights m_CubeMapFaces[1]->activate(); renderLightPass( scene, delta ); m_CubeMapFaces[1]->deactivate(); // Set up the target cubemap->prepare(); // Render the scene glPushMatrix(); renderLitScene( scene, delta, m_CubeMapFaces[0]->target(), m_CubeMapFaces[1]->target() ); glPopMatrix(); // Push the target cubemap->upload( i ); }
const GLSceneGraph * graph = scene->graph(); // Clear the buffers glClear( GL_COLOR_BUFFER_BIT ); // Switch on blending glEnable( GL_BLEND ); // Set to add glBlendFunc( GL_ONE, GL_ONE ); // Switch on the lights glEnable( GL_LIGHTING ); // Write all the point light passes for ( uint i = 0; i < scene->lights().pointLightCount(); ++i ) { // Get the light const GLPointLight * light = scene->lights().getPointLight( i ); // Render the light renderLightPass( graph, delta, light, m_NormalPointShader ); } // Write all the point light passes for ( uint i = 0; i < scene->lights().spotLightCount(); ++i ) { // Get the light const GLSpotLight * light = scene->lights().getSpotLight( i ); // Render the light renderLightPass( graph, delta, light, light->projectedTexture() ? m_NormalProjShader : m_NormalSpotShader ); } // Disable blending glDisable( GL_BLEND ); // Disable the lights glDisable( GL_LIGHTING );
static const float mNormalizeMatrix[] = { 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.5f, 0.5f, 1.0f }; uint shadowCount = 0; TBMath::CMatrix V, P, I; // If there is no shader, skip this if ( !shader ) return;
Get the inverse of the model-view matrix so we can convert our shadow maps into a different space.
// Get the inverse of the view matrix
glGetFloatv( GL_MODELVIEW_MATRIX, V.m );
V.InverseQuick( I );
Update the shader and loop through each entity.
// Use the shader shader->useProgram(); // Update the shader with some // standard variables shader->update( m_Time, delta ); // Bind the shadow maps to all the slots above 0 int maps = 1; for ( uint i = 0; i < light->shadowMapCount(); ++i ) {
Now get our shadow map from the light and bind it to the relevant slot, setting up the texture compare parameters.
// Get the target const GLRenderTarget * target = 0; if ( FAILED( light->getShadowMapTarget( i, &target ) ) ) continue; // Activate the slot glActiveTextureARB( GL_TEXTURE0_ARB + maps ); // Bind the shadow map glBindTexture( GL_TEXTURE_2D, target->id() ); // Set up the shadow parameters glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE_ARB, GL_COMPARE_R_TO_TEXTURE_ARB ); glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC_ARB, GL_LEQUAL );
Get the light's projection and view matrix, so we can look from it's direction. Stick this in the first texture matrix for our shader to access.
// Get the light's projection and view matrix // and the camera's inverse view matrix light->getMatrices( i, V, P ); // Switch to texture mode for this texture glMatrixMode( GL_TEXTURE ); // Bind the light's projection matrix and the inverse view matrix glLoadMatrixf( mNormalizeMatrix ); glMultMatrix( P ); glMultMatrix( V ); glMultMatrix( I ); // Switch back to modelview glMatrixMode( GL_MODELVIEW ); // Increment the map counter maps++; }
Get the projected texture (if any) and activate it in the last free slot. Set the shadow map count too.
// Get the projected texture const GLTexture * project = light->projectedTexture(); // Set the projected texture? glActiveTextureARB( GL_TEXTURE0_ARB + maps ); if ( project ) glBindTexture( GL_TEXTURE_2D, project->id() ); else glBindTexture( GL_TEXTURE_2D, 0 ); // Set the shadow count if ( !shader->getUniform( "vShadowCount", shadowCount ) ) shader->setUniform1i( shadowCount, maps );
Now bind the light's parameters, enable it, and render each node.
// Bind it light->bindParameters( 0 ); // Set up the light light->enable( 0 ); // The geometry and normal map GLGeometry * oldGeom = 0; const GLTexture * normalMap = 0; // Draw the scenegraph for ( uint i = 0; i < (uint)graph->nodeCount(); ++i ) { // Ignore? if ( (int)i == m_IgnoreNode ) continue; // Get the node GLSceneGraphNode * node = graph->getNode( i ); // Get it's geometry GLGeometry * geometry = node->geometry(); // If it has no geometry, skip this node if ( !initRenderID( oldGeom, geometry, &oldGeom ) ) continue; // Set the material geometry->material().apply(); // Activate the texture slot glActiveTextureARB( GL_TEXTURE0_ARB ); normalMap = geometry->texture( Logic::TEXTURE_NORMAL ); // Bind it if ( normalMap ) normalMap->bind(); else glBindTexture( GL_TEXTURE_2D, GLTexture::DefaultID() ); // Bind the vertex attributes shader->beginVertexAttrs( geometry->vertexBufferData(), geometry->vertexBufferStride() ); // Render the geometry renderNode( node, geometry, shader ); // Finish shader->endVertexAttrs(); } Finally, disable our light: \code // Switch of the base light light->disable( 0 );
// Enable cube mapping glActiveTextureARB( GL_TEXTURE2_ARB ); glEnable( GL_TEXTURE_CUBE_MAP ); glDisable( GL_TEXTURE_2D ); // The matrices used in this process TBMath::CMatrix mViewMatrix, mViewInvMatrix; // Draw the scenegraph for ( uint i = 0; i < (uint)graph->nodeCount(); ++i ) { // Get the node GLSceneGraphNode * node = graph->getNode( i ); // Get it's geometry GLGeometry * geometry = node->geometry(); // If it has no geometry, skip this node if ( !initRenderID( oldGeom, geometry, &oldGeom ) ) continue; // Set the material geometry->material().apply(); // Activate the texture slot diffusemap = geometry->texture( Logic::TEXTURE_DIFFUSE ); normalmap = geometry->texture( Logic::TEXTURE_NORMAL ); shinymap = geometry->texture( Logic::TEXTURE_SHINYMAP ); // Get the cubemap const IGLCubeMap * cube = node->cubeMapTarget(); // If there's no cube, break if ( !cube ) continue; // Use the test cube? if ( useTestCube && testCube ) cube = testCube; // Bind the diffuse map glActiveTextureARB( GL_TEXTURE0_ARB ); if ( diffusemap )diffusemap->bind(); else glBindTexture( GL_TEXTURE_2D, GLTexture::DefaultID() ); // Bind the normal map glActiveTextureARB( GL_TEXTURE1_ARB ); if ( normalmap )normalmap->bind(); else glBindTexture( GL_TEXTURE_2D, 0 ); // Bind the cube map glActiveTextureARB( GL_TEXTURE2_ARB ); if ( cube ) cube->bind(); else glBindTexture( GL_TEXTURE_CUBE_MAP, 0 ); // Bind the shininess map glActiveTextureARB( GL_TEXTURE3_ARB ); if ( shinymap ) shinymap->bind(); else glBindTexture( GL_TEXTURE_2D, 0 ); // Get the shader const GLShader * shader = selectShader( node, true, 0 ); // Set up the shader if ( shader ) bindShader( shader, geometry, m_Time, delta ); // Push the matrix glPushMatrix(); // Get the eye position TBMath::CMatrix mViewMatrix, mViewInvMatrix; glGetFloatv( GL_MODELVIEW_MATRIX, mViewMatrix.m ); mViewMatrix.InverseQuick( mViewInvMatrix ); // Plug the inverted modelview matrix into the first texture matrix glActiveTextureARB( GL_TEXTURE0_ARB ); glMatrixMode( GL_TEXTURE ); glLoadMatrix( mViewInvMatrix ); glMatrixMode( GL_MODELVIEW ); // Multiply the node's matrix with the current world matrix glMultMatrix( node->transform().matrix() ); // Spin glRotatef( m_Time * node->spin(), 0, 1, 0 ); // Set the reflectivity and refractive index uint tmp = 0; if ( !shader->getUniform( "reflectivity", tmp ) ) shader->setUniform1f( tmp, geometry->material().reflectivity ); if ( !shader->getUniform( "refractiveindex", tmp ) ) shader->setUniform1f( tmp, geometry->material().refractiveindex ); // Render the geometry geometry->render( shader ); // Pop the world matrix glPopMatrix(); // Finish if ( shader ) shader->endVertexAttrs(); } // Disable cube mapping glActiveTextureARB( GL_TEXTURE2_ARB ); glDisable( GL_TEXTURE_CUBE_MAP ); glEnable( GL_TEXTURE_2D );
// Draw the scenegraph for ( uint i = 0; i < (uint)graph->nodeCount(); ++i ) { // Get the node GLSceneGraphNode * node = graph->getNode( i ); // Get it's geometry GLGeometry * geometry = node->geometry(); // If it has no geometry, skip this node if ( !initRenderID( oldGeom, geometry, &oldGeom ) ) continue; // Set the material geometry->material().apply(); // Activate the texture slot emissive = geometry->texture( Logic::TEXTURE_EMISSIVE ); // Ignore if no emissive if ( !emissive ) continue; // Bind the emissive map glActiveTextureARB( GL_TEXTURE0_ARB ); if ( emissive ) emissive->bind(); else glBindTexture( GL_TEXTURE_2D, 0 ); // Get the shader const GLShader * shader = selectShader( node, true, 0 ); // Set up the shader if ( shader ) bindShader( shader, geometry, m_Time, delta ); // Render the node renderNode( node, geometry, shader ); // Finish if ( shader ) shader->endVertexAttrs(); }
// Clear the buffers glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT ); // Get the projection matrix float mProjection[16]; glGetFloatv( GL_PROJECTION_MATRIX, mProjection ); // Draw the scenegraph for ( uint i = 0; i < (uint)graph->nodeCount(); ++i ) { // Get the node GLSceneGraphNode * node = graph->getNode( i ); // Get it's geometry GLGeometry * geometry = node->geometry(); // If it has no geometry, skip this node if ( !initRenderID( oldGeom, geometry, &oldGeom ) ) continue; // Get the previous world matrix M = node->oldTransform(); // Get the shader const GLShader * shader = m_MotionVecs; // Set up the shader if ( shader ) bindShader( shader, geometry, m_Time, delta ); // Update with the previous matrix uint temp = 0; if ( !m_MotionVecs->getUniform( "motionscale", temp ) ) m_MotionVecs->setUniform1f( temp, motionscale ); // Load the motion matrix into the texture matrix glActiveTextureARB( GL_TEXTURE0_ARB ); glMatrixMode( GL_TEXTURE ); glLoadMatrixf( mProjection ); glMultMatrix ( M ); glMatrixMode( GL_MODELVIEW ); // Render the node renderNode( node, geometry, shader, true ); // Finish if ( shader ) shader->endVertexAttrs(); }
1.5.1-p1