virtual void operator () (osg::RenderInfo& renderInfo) const { osg::BufferBindingReadBack::operator () (renderInfo) ; //_acbb->readData(*renderInfo.getState(), *_atomicCounterArray); osg::UIntArray * _atomicCounterArray=dynamic_cast<osg::UIntArray *>(_bb->getBufferData()); unsigned int numPixel = osg::maximum(1u, _atomicCounterArray->front()); if ((renderInfo.getView()->getFrameStamp()->getFrameNumber() % 10) == 0) { OSG_WARN << "osgatomiccounter : draw " << numPixel << " pixels." << std::endl; } _invNumPixelUniform->set( 1.0f / static_cast<float>(numPixel) ); }
void TritonNode::OceanDrawable::drawImplementation( osg::RenderInfo& renderInfo ) const { osg::State* state = renderInfo.getState(); state->disableAllVertexArrays(); _triton->initializeTriton( renderInfo ); #ifdef USE_SILVERLINING_SKY if ( _triton->atmosphere() && _triton->environment() ) { void* ptr = NULL; if ( _triton->atmosphere()->GetEnvironmentMap(ptr) ) _triton->environment()->SetEnvironmentMap( (Triton::TextureHandle)ptr ); } #endif if ( _triton->ocean() ) { double time = renderInfo.getView()->getFrameStamp()->getSimulationTime(); Triton::Ocean* ocean = _triton->ocean(); if ( _oceanMeshes.size()>0 ) { for ( unsigned int i=0; i<_oceanMeshes.size(); ++i ) { // Bind VBO before SetPatchShader() state->setVertexPointer( _oceanMeshes[i].vertices.get() ); // Render mesh in an ocean favor ocean->SetPatchShader( time, 3 * sizeof(float), 0, false, NULL ); _oceanMeshes[i].primitiveSet->draw( *state, true ); ocean->UnsetPatchShader(); } state->unbindVertexBufferObject(); state->unbindElementBufferObject(); } else ocean->Draw( time ); } state->dirtyAllVertexArrays(); }
void NoesisDrawable::drawImplementation( osg::RenderInfo& renderInfo ) const { unsigned int contextID = renderInfo.getContextID(); if ( !_initialized ) { if ( !NoesisSystemManager::contextInitialized ) { NsGetKernel()->InitSystems(); NoesisSystemManager::contextInitialized = true; } NoesisDrawable* constMe = const_cast<NoesisDrawable*>( this ); constMe->initializeUI( renderInfo ); constMe->registerEventHandlers(); _activeContextID = contextID; _initialized = true; } else if ( contextID==_activeContextID ) { if ( _dirty ) { _uiRenderer->SetSize( _width, _height ); _dirty = false; } osg::State* state = renderInfo.getState(); state->disableAllVertexArrays(); // Make sure the client unit and active unit are unified state->setClientActiveTextureUnit( 0 ); state->setActiveTextureUnit( 0 ); #if !PARALLEL_UPDATING_AND_RENDERING // Update NsGetKernel()->Tick(); osg::FrameStamp* fs = renderInfo.getView()->getFrameStamp(); if ( fs ) _uiRenderer->Update( fs->getSimulationTime() ); #endif // Obtain commands RenderCommands renderCommands = _uiRenderer->WaitForUpdate(); osg::FBOExtensions* fbo = osg::FBOExtensions::instance(contextID, true); // Render offscreen if ( fbo ) {; _uiRenderer->Render( renderCommands.offscreenCommands.GetPtr() ); fbo->glBindFramebuffer( GL_FRAMEBUFFER_EXT, 0 ); } // Render _uiRenderer->Render( renderCommands.commands.GetPtr() ); // Restore buffer states osg::GLBufferObject::Extensions* buf = osg::GLBufferObject::getExtensions(contextID, true); buf->glBindBuffer( GL_ARRAY_BUFFER_ARB, 0 ); buf->glBindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); osg::GL2Extensions* gl2 = osg::GL2Extensions::Get(contextID, true); gl2->glDisableVertexAttribArray( 0 ); gl2->glDisableVertexAttribArray( 1 ); gl2->glDisableVertexAttribArray( 2 ); gl2->glDisableVertexAttribArray( 3 ); gl2->glDisableVertexAttribArray( 4 ); gl2->glDisableVertexAttribArray( 5 ); gl2->glDisableVertexAttribArray( 6 ); } else std::cout << "Multiple contexts are not supported at present!" << std::endl; }
void TritonDrawable::drawImplementation(osg::RenderInfo& renderInfo) const { osg::State* state = renderInfo.getState(); state->disableAllVertexArrays(); _TRITON->initialize( renderInfo ); if ( !_TRITON->ready() ) return; // Configure the height map generator. // If configuration fails, attempt to continue without a heightmap. if (_heightMapGenerator.valid()) { bool configOK = _heightMapGenerator->configure(_TRITON->getHeightMapSize(), *state); if (configOK == false) { _heightMapGenerator = 0L; OE_WARN << LC << "Failed to establish a legal FBO configuration; disabling height map generator!" << std::endl; } } ::Triton::Environment* environment = _TRITON->getEnvironment(); // Find or create the Triton camera for this OSG camera: CameraLocal& local = _local.get(renderInfo.getCurrentCamera()); if (local._tritonCam == 0L) { local._tritonCam = environment->CreateCamera(); local._tritonCam->SetName(renderInfo.getCurrentCamera()->getName().c_str()); } ::Triton::Camera* tritonCam = local._tritonCam; osgEarth::NativeProgramAdapterCollection& adapters = _adapters[ state->getContextID() ]; if ( adapters.empty() ) { OE_INFO << LC << "Initializing Triton program adapters" << std::endl; const char* prefix = "oe_"; // because, don't forget osg_* adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::WATER_SURFACE, 0L, tritonCam), prefix, "WATER_SURFACE")); adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::WATER_SURFACE_PATCH, 0L, tritonCam), prefix, "WATER_SURFACE_PATCH")); adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::GOD_RAYS, 0L, tritonCam), prefix, "GOD_RAYS")); adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::SPRAY_PARTICLES, 0L, tritonCam), prefix, "SPRAY_PARTICLES")); adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::WAKE_SPRAY_PARTICLES, 0L, tritonCam), prefix, "WAKE_SPRAY_PARTICLES")); #if 0 // In older Triton (3.91), this line causes problems in Core profile and prevents the ocean from drawing. In newer Triton (4.01), // this line causes a crash because there is no context passed in to GetShaderObject(), resulting in multiple NULL references. adapters.push_back( new osgEarth::NativeProgramAdapter(state, getOceanShader(_TRITON->getOcean(), ::Triton::WATER_DECALS, 0L, tritonCam), prefix, "WATER_DECALS")); #endif } adapters.apply( state ); // Pass the final view and projection matrices into Triton. if ( environment ) { tritonCam->SetCameraMatrix(state->getModelViewMatrix().ptr()); tritonCam->SetProjectionMatrix(state->getProjectionMatrix().ptr()); } if (_heightMapGenerator.valid()) { GLint texName; osg::Matrix hMM; if (_heightMapGenerator->getTextureAndMatrix(renderInfo, texName, hMM)) { // copy the OSG matrix to a Triton matrix: ::Triton::Matrix4 texMat( hMM(0, 0), hMM(0, 1), hMM(0, 2), hMM(0, 3), hMM(1, 0), hMM(1, 1), hMM(1, 2), hMM(1, 3), hMM(2, 0), hMM(2, 1), hMM(2, 2), hMM(2, 3), hMM(3, 0), hMM(3, 1), hMM(3, 2), hMM(3, 3)); environment->SetHeightMap((::Triton::TextureHandle)texName, texMat, 0L, tritonCam); OE_DEBUG << LC << "Updating height map, FN=" << renderInfo.getState()->getFrameStamp()->getFrameNumber() << std::endl; } } state->dirtyAllVertexArrays(); // Now light and draw the ocean: if ( environment ) { // User pre-draw callback: if (_TRITON->getCallback()) { _TRITON->getCallback()->onDrawOcean( _TRITON->getEnvironmentWrapper(), _TRITON->getOceanWrapper()); } // The sun position is roughly where it is in our skybox texture: // Since this is a simple example we will just assume that Sun is the light from View light source // TODO: fix this... osg::Light* light = renderInfo.getView() ? renderInfo.getView()->getLight() : NULL; // This is the light attached to View so there are no transformations above.. // But in general case you would need to accumulate all transforms above the light into this matrix osg::Matrix lightLocalToWorldMatrix = osg::Matrix::identity(); // If you don't know where the sun lightsource is attached and don't know its local to world matrix you may use // following elaborate scheme to grab the light source while drawing Triton ocean: // - Install cull callback to catch CullVisitor and record pointer to its associated RenderStage // I was hoping RenderStage can be found from renderInfo in drawImplementation but I didn't figure how ... // - When TritonDrawable::drawImplementation is called all lights will be already applied to OpenGL // then just find proper infinite directional light by scanning renderStage->PositionalStateContainer. // - Note that we canot scan for the lights inside cull because they may not be traversed before Triton drawable // - When you found interesting ligt source that can work as Sun, read its modelview matrix and lighting params // Multiply light position by ( modelview * inverse camera view ) and pass this to Triton with lighting colors if ( light && light->getPosition().w() == 0 ) { osg::Vec4 ambient = light->getAmbient(); osg::Vec4 diffuse = light->getDiffuse(); osg::Vec4 position = light->getPosition(); // Compute light position/direction in the world position = position * lightLocalToWorldMatrix; // Diffuse direction and color environment->SetDirectionalLight( ::Triton::Vector3( position[0], position[1], position[2] ), ::Triton::Vector3( diffuse[0], diffuse[1], diffuse[2] ) ); // Sun-based ambient value: osg::Vec3d up = osg::Vec3d(0,0,0) * renderInfo.getCurrentCamera()->getInverseViewMatrix(); up.normalize(); osg::Vec3d pos3 = osg::Vec3d(position.x(), position.y(), position.z()); pos3.normalize(); float dot = osg::clampAbove(up*pos3, 0.0); dot*=dot; float sunAmbient = (float)osg::clampBetween( dot, 0.0f, 0.88f ); float fa = osg::maximum(sunAmbient, ambient[0]); // Ambient color based on the zenith color in the cube map environment->SetAmbientLight( ::Triton::Vector3(fa, fa, fa) ); } else { environment->SetDirectionalLight( ::Triton::Vector3(0,0,1), ::Triton::Vector3(1,1,1) ); environment->SetAmbientLight( ::Triton::Vector3(0.88f, 0.88f, 0.88f) ); } if ( _cubeMap.valid() ) { // Build transform from our cube map orientation space to native Triton orientation // See worldToCubeMap function used in SkyBox to orient sky texture so that sky is up and earth is down osg::Matrix m = osg::Matrix::rotate( osg::PI_2, osg::X_AXIS ); // = worldToCubeMap ::Triton::Matrix3 transformFromYUpToZUpCubeMapCoords( m(0,0), m(0,1), m(0,2), m(1,0), m(1,1), m(1,2), m(2,0), m(2,1), m(2,2) ); // Grab the cube map from our sky box and give it to Triton to use as an _environment map // GLenum texture = renderInfo.getState()->getLastAppliedTextureAttribute( _stage, osg::StateAttribute::TEXTURE ); environment->SetEnvironmentMap( (::Triton::TextureHandle)_cubeMap->getTextureObject( state->getContextID() )->id(), transformFromYUpToZUpCubeMapCoords ); if( _planarReflectionMap.valid() && _planarReflectionProjection.valid() ) { osg::Matrix & p = *_planarReflectionProjection; ::Triton::Matrix3 planarProjection( p(0,0), p(0,1), p(0,2), p(1,0), p(1,1), p(1,2), p(2,0), p(2,1), p(2,2) ); environment->SetPlanarReflectionMap( (::Triton::TextureHandle)_planarReflectionMap->getTextureObject( state->getContextID() )->id(), planarProjection, 0.125 ); } } // Draw the ocean for the current time sample if ( _TRITON->getOcean() ) { osg::GLExtensions* ext = osg::GLExtensions::Get(state->getContextID(), true); bool writeDepth = true; const osg::Depth* depth = static_cast<const osg::Depth*>(state->getLastAppliedAttribute(osg::StateAttribute::DEPTH)); if (depth) writeDepth = depth->getWriteMask(); double simTime = renderInfo.getView()->getFrameStamp()->getSimulationTime(); simTime = fmod(simTime, 86400.0); _TRITON->getOcean()->Draw( simTime, writeDepth, // depth writes true, // draw water true, // draw particles NULL, // optional context tritonCam); } } // Put GL back in a state that won't confuse the OSG state tracking: state->dirtyAllVertexArrays(); state->dirtyAllAttributes(); state->dirtyAllModes(); #ifndef OSG_GL_FIXED_FUNCTION_AVAILABLE // Keep OSG from reapplying GL_LIGHTING on next state change after dirtyAllModes(). state->setModeValidity(GL_LIGHTING, false); #endif // Keep an eye on this. // I had to remove something similar in another module (Rex engine) because it was causing // positional attributes (like clip planes) to re-apply with an incorrect MVM. -gw state->apply(); }
void FadeText::drawImplementation(osg::RenderInfo& renderInfo) const { osg::State& state = *renderInfo.getState(); ViewBlendColourMap::iterator itr = _viewBlendColourMap.find(renderInfo.getView()); if (itr != _viewBlendColourMap.end()) { Text::drawImplementation(*renderInfo.getState(), itr->second ); } else { Text::drawImplementation(*renderInfo.getState(), osg::Vec4(1.0f,1.0f,1.0f,1.0f) ); } // now pass on new details FadeTextUserData* userData = dynamic_cast<FadeTextUserData*>(renderInfo.getUserData()); if (!userData) { if (renderInfo.getUserData()) { OSG_NOTICE<<"Warning user data not of supported type."<<std::endl; return; } userData = getGlobalFadeText()->createNewFadeTextUserData(renderInfo.getView()); if (!userData) { OSG_NOTICE<<"Memory error, unable to create FadeTextUserData."<<std::endl; return; } renderInfo.setUserData(userData); } unsigned int frameNumber = renderInfo.getState()->getFrameStamp()->getFrameNumber(); if (frameNumber != userData->_frameNumber) { // new frame so must reset UserData structure. userData->_frameNumber = frameNumber; userData->_fadeTextInView.clear(); } osg::Matrix lmv = state.getModelViewMatrix(); computeMatrix(lmv, &state); lmv.postMult(state.getModelViewMatrix()); if (renderInfo.getView() && renderInfo.getView()->getCamera()) { // move from camera into the view space. lmv.postMult(state.getInitialInverseViewMatrix()); lmv.postMult(renderInfo.getView()->getCamera()->getViewMatrix()); } FadeTextData ftd(const_cast<osgText::FadeText*>(this)); ftd._vertices[0].set(osg::Vec3d(_textBB.xMin(),_textBB.yMin(),_textBB.zMin())*lmv); ftd._vertices[1].set(osg::Vec3d(_textBB.xMax(),_textBB.yMin(),_textBB.zMin())*lmv); ftd._vertices[2].set(osg::Vec3d(_textBB.xMax(),_textBB.yMax(),_textBB.zMin())*lmv); ftd._vertices[3].set(osg::Vec3d(_textBB.xMin(),_textBB.yMax(),_textBB.zMin())*lmv); userData->_fadeTextInView.push_back(ftd); }
void TritonDrawable::drawImplementation(osg::RenderInfo& renderInfo) const { osg::State* state = renderInfo.getState(); state->disableAllVertexArrays(); _TRITON->initialize( renderInfo ); if ( !_TRITON->ready() ) return; if ( _TRITON->passHeightMapToTriton() && !_terrainChangedCallback.valid() ) { const_cast<TritonDrawable*>(this)->setupHeightMap(*state); } ::Triton::Environment* environment = _TRITON->getEnvironment(); osgEarth::NativeProgramAdapterCollection& adapters = _adapters[ state->getContextID() ]; if ( adapters.empty() ) { const char* prefix = "oe_"; adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::GOD_RAYS), prefix)); adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::SPRAY_PARTICLES), prefix)); adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WAKE_SPRAY_PARTICLES), prefix)); adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WATER_DECALS), prefix)); adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WATER_SURFACE_PATCH), prefix)); adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WATER_SURFACE), prefix)); } adapters.apply( state ); // Pass the final view and projection matrices into Triton. if ( environment ) { environment->SetCameraMatrix( state->getModelViewMatrix().ptr() ); environment->SetProjectionMatrix( state->getProjectionMatrix().ptr() ); } if ( _TRITON->passHeightMapToTriton() ) { unsigned cid = renderInfo.getContextID(); bool dirty = ( _contextDirty[cid] ) || ( renderInfo.getView()->getCamera()->getViewMatrix() != _viewMatrix ) || ( renderInfo.getView()->getCamera()->getProjectionMatrix() != _projMatrix ); if ( dirty ) { updateHeightMap( renderInfo ); _contextDirty[renderInfo.getContextID()] = 0; _viewMatrix = renderInfo.getView()->getCamera()->getViewMatrix(); _projMatrix = renderInfo.getView()->getCamera()->getProjectionMatrix(); } } state->dirtyAllVertexArrays(); // Now light and draw the ocean: if ( environment ) { // User pre-draw callback: if (_TRITON->getCallback()) { _TRITON->getCallback()->onDrawOcean( _TRITON->getEnvironmentWrapper(), _TRITON->getOceanWrapper()); } // The sun position is roughly where it is in our skybox texture: // Since this is a simple example we will just assume that Sun is the light from View light source // TODO: fix this... osg::Light* light = renderInfo.getView() ? renderInfo.getView()->getLight() : NULL; // This is the light attached to View so there are no transformations above.. // But in general case you would need to accumulate all transforms above the light into this matrix osg::Matrix lightLocalToWorldMatrix = osg::Matrix::identity(); // If you don't know where the sun lightsource is attached and don't know its local to world matrix you may use // following elaborate scheme to grab the light source while drawing Triton ocean: // - Install cull callback to catch CullVisitor and record pointer to its associated RenderStage // I was hoping RenderStage can be found from renderInfo in drawImplementation but I didn't figure how ... // - When TritonDrawable::drawImplementation is called all lights will be already applied to OpenGL // then just find proper infinite directional light by scanning renderStage->PositionalStateContainer. // - Note that we canot scan for the lights inside cull because they may not be traversed before Triton drawable // - When you found interesting ligt source that can work as Sun, read its modelview matrix and lighting params // Multiply light position by ( modelview * inverse camera view ) and pass this to Triton with lighting colors if ( light && light->getPosition().w() == 0 ) { osg::Vec4 ambient = light->getAmbient(); osg::Vec4 diffuse = light->getDiffuse(); osg::Vec4 position = light->getPosition(); // Compute light position/direction in the world position = position * lightLocalToWorldMatrix; // Diffuse direction and color environment->SetDirectionalLight( ::Triton::Vector3( position[0], position[1], position[2] ), ::Triton::Vector3( diffuse[0], diffuse[1], diffuse[2] ) ); // Sun-based ambient value: osg::Vec3d up = osg::Vec3d(0,0,0) * renderInfo.getCurrentCamera()->getInverseViewMatrix(); up.normalize(); osg::Vec3d pos3 = osg::Vec3d(position.x(), position.y(), position.z()); pos3.normalize(); float dot = osg::clampAbove(up*pos3, 0.0); dot*=dot; float sunAmbient = (float)osg::clampBetween( dot, 0.0f, 0.88f ); float fa = std::max(sunAmbient, ambient[0]); // Ambient color based on the zenith color in the cube map environment->SetAmbientLight( ::Triton::Vector3(fa, fa, fa) ); //::Triton::Vector3( ambient[0], ambient[1], ambient[2] ) ); } else { environment->SetDirectionalLight( ::Triton::Vector3(0,0,1), ::Triton::Vector3(1,1,1) ); environment->SetAmbientLight( ::Triton::Vector3(0.88f, 0.88f, 0.88f) ); } // Build transform from our cube map orientation space to native Triton orientation // See worldToCubeMap function used in SkyBox to orient sky texture so that sky is up and earth is down osg::Matrix m = osg::Matrix::rotate( osg::PI_2, osg::X_AXIS ); // = worldToCubeMap ::Triton::Matrix3 transformFromYUpToZUpCubeMapCoords( m(0,0), m(0,1), m(0,2), m(1,0), m(1,1), m(1,2), m(2,0), m(2,1), m(2,2) ); // Grab the cube map from our sky box and give it to Triton to use as an _environment map // GLenum texture = renderInfo.getState()->getLastAppliedTextureAttribute( _stage, osg::StateAttribute::TEXTURE ); if ( _cubeMap.valid() ) { environment->SetEnvironmentMap( (::Triton::TextureHandle)_cubeMap->getTextureObject( state->getContextID() )->id(), transformFromYUpToZUpCubeMapCoords ); if( _planarReflectionMap.valid() && _planarReflectionProjection.valid() ) { osg::Matrix & p = *_planarReflectionProjection; ::Triton::Matrix3 planarProjection( p(0,0), p(0,1), p(0,2), p(1,0), p(1,1), p(1,2), p(2,0), p(2,1), p(2,2) ); environment->SetPlanarReflectionMap( (::Triton::TextureHandle) _planarReflectionMap->getTextureObject( state->getContextID() )->id(), planarProjection, 0.125 ); } } // Draw the ocean for the current time sample if ( _TRITON->getOcean() ) { _TRITON->getOcean()->Draw( renderInfo.getView()->getFrameStamp()->getSimulationTime() ); } } // Put GL back in a state that won't confuse the OSG state tracking: state->dirtyAllVertexArrays(); state->dirtyAllAttributes(); //osg::GL2Extensions* api = osg::GL2Extensions::Get(state->getContextID(), true); //api->glUseProgram((GLuint)0); //state->setLastAppliedProgramObject( 0L ); state->apply(); }
void TritonDrawable::drawImplementation(osg::RenderInfo& renderInfo) const { osg::State* state = renderInfo.getState(); state->disableAllVertexArrays(); _TRITON->initialize( renderInfo ); if ( !_TRITON->ready() ) return; #ifdef USE_HEIGHT_MAP if( !_terrainChangedCallback.valid()) const_cast< TritonDrawable *>( this )->setupHeightMap(_mapNode.get()); #endif ::Triton::Environment* environment = _TRITON->getEnvironment(); osgEarth::NativeProgramAdapterCollection& adapters = _adapters[ state->getContextID() ]; if ( adapters.empty() ) { adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::GOD_RAYS)) ); adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::SPRAY_PARTICLES)) ); adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WAKE_SPRAY_PARTICLES)) ); adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WATER_DECALS)) ); adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WATER_SURFACE)) ); adapters.push_back( new osgEarth::NativeProgramAdapter(state, (GLint)_TRITON->getOcean()->GetShaderObject(::Triton::WATER_SURFACE_PATCH)) ); } adapters.apply( state ); // Pass the final view and projection matrices into Triton. if ( environment ) { environment->SetCameraMatrix( state->getModelViewMatrix().ptr() ); environment->SetProjectionMatrix( state->getProjectionMatrix().ptr() ); } if(_terrainChangedCallback.valid()) { OceanTerrainChangedCallback* c = static_cast<OceanTerrainChangedCallback*>(_terrainChangedCallback.get()); c->setViewMatrix( renderInfo.getView()->getCamera()->getViewMatrix() ); c->setProjectionMatrix(renderInfo.getView()->getCamera()->getProjectionMatrix() ); c->setContextID(renderInfo.getView()->getCamera()->getGraphicsContext()->getState()->getContextID() ); } state->dirtyAllVertexArrays(); // Now light and draw the ocean: if ( environment ) { // The sun position is roughly where it is in our skybox texture: // Since this is a simple example we will just assume that Sun is the light from View light source // TODO: fix this... osg::Light* light = renderInfo.getView() ? renderInfo.getView()->getLight() : NULL; // This is the light attached to View so there are no transformations above.. // But in general case you would need to accumulate all transforms above the light into this matrix osg::Matrix lightLocalToWorldMatrix = osg::Matrix::identity(); // If you don't know where the sun lightsource is attached and don't know its local to world matrix you may use // following elaborate scheme to grab the light source while drawing Triton ocean: // - Install cull callback to catch CullVisitor and record pointer to its associated RenderStage // I was hoping RenderStage can be found from renderInfo in drawImplementation but I didn't figure how ... // - When TritonDrawable::drawImplementation is called all lights will be already applied to OpenGL // then just find proper infinite directional light by scanning renderStage->PositionalStateContainer. // - Note that we canot scan for the lights inside cull because they may not be traversed before Triton drawable // - When you found interesting ligt source that can work as Sun, read its modelview matrix and lighting params // Multiply light position by ( modelview * inverse camera view ) and pass this to Triton with lighting colors if ( light && light->getPosition().w() == 0 ) { osg::Vec4 ambient = light->getAmbient(); osg::Vec4 diffuse = light->getDiffuse(); osg::Vec4 position = light->getPosition(); // Compute light position/direction in the world position = position * lightLocalToWorldMatrix; // Diffuse direction and color environment->SetDirectionalLight( ::Triton::Vector3( position[0], position[1], position[2] ), ::Triton::Vector3( diffuse[0], diffuse[1], diffuse[2] ) ); // Ambient color based on the zenith color in the cube map environment->SetAmbientLight( ::Triton::Vector3( ambient[0], ambient[1], ambient[2] ) ); } // Build transform from our cube map orientation space to native Triton orientation // See worldToCubeMap function used in SkyBox to orient sky texture so that sky is up and earth is down osg::Matrix m = osg::Matrix::rotate( osg::PI_2, osg::X_AXIS ); // = worldToCubeMap ::Triton::Matrix3 transformFromYUpToZUpCubeMapCoords( m(0,0), m(0,1), m(0,2), m(1,0), m(1,1), m(1,2), m(2,0), m(2,1), m(2,2) ); // Grab the cube map from our sky box and give it to Triton to use as an _environment map // GLenum texture = renderInfo.getState()->getLastAppliedTextureAttribute( _stage, osg::StateAttribute::TEXTURE ); if ( _cubeMap.valid() ) { environment->SetEnvironmentMap( (::Triton::TextureHandle)_cubeMap->getTextureObject( state->getContextID() )->id(), transformFromYUpToZUpCubeMapCoords ); if( _planarReflectionMap.valid() && _planarReflectionProjection.valid() ) { osg::Matrix & p = *_planarReflectionProjection; ::Triton::Matrix3 planarProjection( p(0,0), p(0,1), p(0,2), p(1,0), p(1,1), p(1,2), p(2,0), p(2,1), p(2,2) ); environment->SetPlanarReflectionMap( (::Triton::TextureHandle) _planarReflectionMap->getTextureObject( state->getContextID() )->id(), planarProjection, 0.125 ); } } // Draw the ocean for the current time sample if ( _TRITON->getOcean() ) { _TRITON->getOcean()->Draw( renderInfo.getView()->getFrameStamp()->getSimulationTime() ); } } state->dirtyAllVertexArrays(); }