From 1194f1f9910476eb6880c43c420e33bd2ecc19e0 Mon Sep 17 00:00:00 2001 From: Frederic Bouvier <fredfgfs01@free.fr> Date: Fri, 30 Mar 2012 07:26:29 +0200 Subject: [PATCH] Implement Cascade Shadow Mapping in the Rembrandt renderer. Shadow map size is set by the /sim/rendering/shadows/map-size property before starting fgfs. Its default value is 4096. Maximum value is 16384 in most card --- src/Main/CameraGroup.cxx | 11 +- src/Main/CameraGroup.hxx | 7 +- src/Main/renderer.cxx | 219 +++++++++++++++++++++++++++++++++------ src/Main/renderer.hxx | 7 ++ 4 files changed, 209 insertions(+), 35 deletions(-) diff --git a/src/Main/CameraGroup.cxx b/src/Main/CameraGroup.cxx index 0cf9ad7a0..2795191a8 100644 --- a/src/Main/CameraGroup.cxx +++ b/src/Main/CameraGroup.cxx @@ -185,11 +185,13 @@ void CameraInfo::updateCameras() { for (CameraMap::iterator ii = cameras.begin(); ii != cameras.end(); ++ii ) { float f = ii->second.scaleFactor; + if ( f == 0.0f ) continue; ii->second.camera->getViewport()->setViewport(x*f, y*f, width*f, height*f); } for (RenderBufferMap::iterator ii = buffers.begin(); ii != buffers.end(); ++ii ) { float f = ii->second.scaleFactor; + if ( f == 0.0f ) continue; osg::Texture2D* texture = ii->second.texture.get(); if ( texture->getTextureHeight() != height*f || texture->getTextureWidth() != width*f ) { texture->setTextureSize( width*f, height*f ); @@ -202,13 +204,16 @@ void CameraInfo::resized(double w, double h) { for (RenderBufferMap::iterator ii = buffers.begin(); ii != buffers.end(); ++ii) { float s = ii->second.scaleFactor; + if ( s == 0.0f ) continue; ii->second.texture->setTextureSize( w * s, h * s ); ii->second.texture->dirtyTextureObject(); } for (CameraMap::iterator ii = cameras.begin(); ii != cameras.end(); ++ii) { RenderStageInfo& rsi = ii->second; - if (!rsi.resizable || rsi.camera->getRenderTargetImplementation() != osg::Camera::FRAME_BUFFER_OBJECT) + if (!rsi.resizable || + rsi.camera->getRenderTargetImplementation() != osg::Camera::FRAME_BUFFER_OBJECT || + rsi.scaleFactor == 0.0f ) continue; Viewport* vp = rsi.camera->getViewport(); @@ -350,6 +355,10 @@ void CameraGroup::update(const osg::Vec3d& position, bool projectionDone = false; Matrix projectionMatrix; for ( CameraMap::const_iterator ii = info->cameras.begin(); ii != info->cameras.end(); ++ii ) { + if ( ii->first == SHADOW_CAMERA ) { + globals->get_renderer()->updateShadowCamera(info, position); + continue; + } if ( ii->second.fullscreen ) continue; diff --git a/src/Main/CameraGroup.hxx b/src/Main/CameraGroup.hxx index 17c0ad003..5877429d5 100644 --- a/src/Main/CameraGroup.hxx +++ b/src/Main/CameraGroup.hxx @@ -27,6 +27,7 @@ #include <osg/Node> #include <osg/TextureRectangle> #include <osg/Texture2D> +#include <osg/TexGen> #include <osgUtil/RenderBin> // For osgUtil::LineSegmentIntersector::Intersections, which is a typedef. @@ -54,7 +55,8 @@ struct RenderBufferInfo { NORMAL_BUFFER, DIFFUSE_BUFFER, SPEC_EMIS_BUFFER, - LIGHTING_BUFFER + LIGHTING_BUFFER, + SHADOW_BUFFER }; RenderBufferInfo(osg::Texture2D* t = 0, float s = 1.0 ) : texture(t), scaleFactor(s) {} @@ -147,6 +149,7 @@ struct CameraInfo : public osg::Referenced CameraMap cameras; void addCamera( CameraKind k, osg::Camera* c, int si = -1, bool fs = false ) { cameras[k].camera = c; cameras[k].slaveIndex = si; cameras[k].fullscreen = fs; } void addCamera( CameraKind k, osg::Camera* c, bool fs ) { cameras[k].camera = c; cameras[k].fullscreen = fs; } + void addCamera( CameraKind k, osg::Camera* c, float s ) { cameras[k].camera = c; cameras[k].scaleFactor = s; } osg::Camera* getCamera(CameraKind k) const; int getMainSlaveIndex() const; RenderStageInfo& getRenderStageInfo( CameraKind k ) { return cameras[k]; } @@ -157,6 +160,8 @@ struct CameraInfo : public osg::Referenced void addBuffer(RenderBufferInfo::Kind k, osg::Texture2D* tex, float scale = 1.0 ) { buffers[k] = RenderBufferInfo(tex,scale); } osg::Texture2D* getBuffer(RenderBufferInfo::Kind k) { return buffers[k].texture.get(); } + osg::ref_ptr<osg::TexGen> shadowTexGen[4]; + osg::ref_ptr<osg::Uniform> bufferSize; //osg::ref_ptr<osg::Uniform> bloomOffset[2]; osg::ref_ptr<osg::Uniform> projInverse; diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index 771f02317..db17e0a86 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -450,6 +450,7 @@ void FGRenderer::init( void ) { _classicalRenderer = !fgGetBool("/sim/rendering/rembrandt", false); + _shadowMapSize = fgGetInt( "/sim/rendering/shadows/map-size", 4096 ); _scenery_loaded = fgGetNode("/sim/sceneryloaded", true); _scenery_override = fgGetNode("/sim/sceneryloaded-override", true); _panel_hotspots = fgGetNode("/sim/panel-hotspots", true); @@ -641,23 +642,24 @@ public: } } } else if ( kind == flightgear::LIGHTING_CAMERA ) { - //if (info->mainShadowCamera.valid()) { - // osg::Group* grp = info->mainShadowCamera->getChild(0)->asGroup(); - // for (int i = 0; i < 4; ++i ) { - // osg::TexGen* shadowTexGen = info->shadowTexGen[i]; - // shadowTexGen->setMode(osg::TexGen::EYE_LINEAR); + osg::ref_ptr<osg::Camera> mainShadowCamera = info->getCamera( SHADOW_CAMERA ); + if (mainShadowCamera.valid()) { + osg::Group* grp = mainShadowCamera->getChild(0)->asGroup(); + for (int i = 0; i < 4; ++i ) { + osg::TexGen* shadowTexGen = info->shadowTexGen[i]; + shadowTexGen->setMode(osg::TexGen::EYE_LINEAR); - // osg::Camera* cascadeCam = static_cast<osg::Camera*>( grp->getChild(i) ); - // // compute the matrix which takes a vertex from view coords into tex coords - // shadowTexGen->setPlanesFromMatrix( cascadeCam->getProjectionMatrix() * - // osg::Matrix::translate(1.0,1.0,1.0) * - // osg::Matrix::scale(0.5f,0.5f,0.5f) ); + osg::Camera* cascadeCam = static_cast<osg::Camera*>( grp->getChild(i) ); + // compute the matrix which takes a vertex from view coords into tex coords + shadowTexGen->setPlanesFromMatrix( cascadeCam->getProjectionMatrix() * + osg::Matrix::translate(1.0,1.0,1.0) * + osg::Matrix::scale(0.5f,0.5f,0.5f) ); - // osg::RefMatrix * refMatrix = new osg::RefMatrix( cascadeCam->getInverseViewMatrix() * *cv->getModelViewMatrix() ); + osg::RefMatrix * refMatrix = new osg::RefMatrix( cascadeCam->getInverseViewMatrix() * *cv->getModelViewMatrix() ); - // cv->getRenderStage()->getPositionalStateContainer()->addPositionedTextureAttribute( i+1, refMatrix, shadowTexGen ); - // } - //} + cv->getRenderStage()->getPositionalStateContainer()->addPositionedTextureAttribute( i+1, refMatrix, shadowTexGen ); + } + } // Render saved transparent render bins osgUtil::RenderStage* renderStage = cv->getRenderStage(); osgUtil::RenderBin::RenderBinList& rbl = renderStage->getRenderBinList(); @@ -673,13 +675,19 @@ private: CameraInfo* info; }; -osg::Texture2D* buildDeferredBuffer(GLint internalFormat, GLenum sourceFormat, GLenum sourceType, osg::Texture::WrapMode wrapMode) +osg::Texture2D* buildDeferredBuffer(GLint internalFormat, GLenum sourceFormat, GLenum sourceType, osg::Texture::WrapMode wrapMode, bool shadowComparison = false) { osg::Texture2D* tex = new osg::Texture2D; tex->setResizeNonPowerOfTwoHint( false ); tex->setInternalFormat( internalFormat ); - tex->setSourceFormat( sourceFormat ); - tex->setSourceType( sourceType ); + tex->setShadowComparison(shadowComparison); + if (shadowComparison) { + tex->setShadowTextureMode(osg::Texture2D::LUMINANCE); + tex->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); + } else { + tex->setSourceFormat(sourceFormat); + tex->setSourceType(sourceType); + } tex->setFilter( osg::Texture2D::MIN_FILTER, osg::Texture2D::LINEAR ); tex->setFilter( osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR ); tex->setWrap( osg::Texture::WRAP_S, wrapMode ); @@ -687,13 +695,15 @@ osg::Texture2D* buildDeferredBuffer(GLint internalFormat, GLenum sourceFormat, G return tex; } -void buildDeferredBuffers( flightgear::CameraInfo* info ) +void buildDeferredBuffers( flightgear::CameraInfo* info, int shadowMapSize ) { - info->addBuffer(flightgear::RenderBufferInfo::DEPTH_BUFFER, buildDeferredBuffer( GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, osg::Texture::CLAMP_TO_BORDER) ); + info->addBuffer(flightgear::RenderBufferInfo::DEPTH_BUFFER, buildDeferredBuffer( GL_DEPTH_COMPONENT32, GL_DEPTH_COMPONENT, GL_FLOAT, osg::Texture::CLAMP_TO_BORDER) ); info->addBuffer(flightgear::RenderBufferInfo::NORMAL_BUFFER, buildDeferredBuffer( 0x822C /*GL_RG16*/, 0x8227 /*GL_RG*/, GL_UNSIGNED_SHORT, osg::Texture::CLAMP_TO_BORDER) ); info->addBuffer(flightgear::RenderBufferInfo::DIFFUSE_BUFFER, buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) ); info->addBuffer(flightgear::RenderBufferInfo::SPEC_EMIS_BUFFER, buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) ); info->addBuffer(flightgear::RenderBufferInfo::LIGHTING_BUFFER, buildDeferredBuffer( GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, osg::Texture::CLAMP_TO_BORDER) ); + info->addBuffer(flightgear::RenderBufferInfo::SHADOW_BUFFER, buildDeferredBuffer( GL_DEPTH_COMPONENT, GL_DEPTH_COMPONENT, GL_FLOAT, osg::Texture::CLAMP_TO_BORDER, true), 0.0f ); + info->getBuffer(RenderBufferInfo::SHADOW_BUFFER)->setTextureSize(shadowMapSize,shadowMapSize); } void attachBufferToCamera( flightgear::CameraInfo* info, osg::Camera* camera, osg::Camera::BufferComponent c, flightgear::CameraKind ck, flightgear::RenderBufferInfo::Kind bk ) @@ -728,6 +738,140 @@ osg::Camera* FGRenderer::buildDeferredGeometryCamera( flightgear::CameraInfo* in return camera; } +static void setShadowCascadeStateSet( osg::Camera* cam ) { + osg::StateSet* ss = cam->getOrCreateStateSet(); + ss->setAttribute( new osg::PolygonOffset( 1.1f, 5.0f ), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE ); + ss->setMode( GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE ); + ss->setRenderBinDetails( 0, "RenderBin", osg::StateSet::OVERRIDE_RENDERBIN_DETAILS ); + ss->setAttributeAndModes( new osg::AlphaFunc( osg::AlphaFunc::GREATER, 0.05 ), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE ); + ss->setAttributeAndModes( new osg::ColorMask( false, false, false, false ), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE ); + ss->setAttributeAndModes( new osg::CullFace( osg::CullFace::FRONT ), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE ); + osg::Program* program = new osg::Program; + ss->setAttribute( program, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON ); + ss->setMode( GL_LIGHTING, osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF ); + ss->setMode( GL_BLEND, osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF ); + //ss->setTextureMode( 0, GL_TEXTURE_2D, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON ); + ss->setTextureMode( 0, GL_TEXTURE_3D, osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF ); + ss->setTextureMode( 1, GL_TEXTURE_2D, osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF ); + ss->setTextureMode( 1, GL_TEXTURE_3D, osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF ); + ss->setTextureMode( 2, GL_TEXTURE_2D, osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF ); + ss->setTextureMode( 2, GL_TEXTURE_3D, osg::StateAttribute::OVERRIDE | osg::StateAttribute::OFF ); +} + +static osg::Camera* createShadowCascadeCamera( int no, int cascadeSize ) { + osg::Camera* cascadeCam = new osg::Camera; + setShadowCascadeStateSet( cascadeCam ); + + std::ostringstream oss; + oss << "CascadeCamera" << (no + 1); + cascadeCam->setName( oss.str() ); + cascadeCam->setClearMask(0); + cascadeCam->setCullMask(~( simgear::MODELLIGHT_BIT /* | simgear::NO_SHADOW_BIT */ ) ); + cascadeCam->setCullingMode( cascadeCam->getCullingMode() & ~osg::CullSettings::SMALL_FEATURE_CULLING ); + cascadeCam->setAllowEventFocus(false); + cascadeCam->setReferenceFrame(osg::Transform::ABSOLUTE_RF_INHERIT_VIEWPOINT); + cascadeCam->setRenderOrder(osg::Camera::NESTED_RENDER); + cascadeCam->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR); + cascadeCam->setViewport( int( no / 2 ) * cascadeSize, (no & 1) * cascadeSize, cascadeSize, cascadeSize ); + return cascadeCam; +} + +osg::Camera* FGRenderer::buildDeferredShadowCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc ) +{ + osg::Camera* mainShadowCamera = new osg::Camera; + info->addCamera(flightgear::SHADOW_CAMERA, mainShadowCamera, 0.0f ); + + mainShadowCamera->setName( "ShadowCamera" ); + mainShadowCamera->setClearMask( GL_DEPTH_BUFFER_BIT ); + mainShadowCamera->setClearDepth( 1.0 ); + mainShadowCamera->setAllowEventFocus(false); + mainShadowCamera->setGraphicsContext(gc); + mainShadowCamera->setRenderTargetImplementation( osg::Camera::FRAME_BUFFER_OBJECT ); + attachBufferToCamera( info, mainShadowCamera, osg::Camera::DEPTH_BUFFER, flightgear::SHADOW_CAMERA, flightgear::RenderBufferInfo::SHADOW_BUFFER ); + mainShadowCamera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); + mainShadowCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF); + mainShadowCamera->setViewport( 0, 0, _shadowMapSize, _shadowMapSize ); + mainShadowCamera->setDrawBuffer(GL_FRONT); + mainShadowCamera->setReadBuffer(GL_FRONT); + + osg::Switch* shadowSwitch = new osg::Switch; + mainShadowCamera->addChild( shadowSwitch ); + + for (int i = 0; i < 4; ++i ) { + osg::Camera* cascadeCam = createShadowCascadeCamera( i, _shadowMapSize/2 ); + cascadeCam->addChild( mDeferredRealRoot.get() ); + shadowSwitch->addChild( cascadeCam ); + info->shadowTexGen[i] = new osg::TexGen; + } + shadowSwitch->setAllChildrenOn(); + + return mainShadowCamera; +} + +void FGRenderer::updateShadowCascade(const CameraInfo* info, osg::Camera* camera, osg::Group* grp, int idx, double left, double right, double bottom, double top, double zNear, double f1, double f2) +{ + osg::Camera* cascade = static_cast<osg::Camera*>( grp->getChild(idx) ); + osg::Matrixd &viewMatrix = cascade->getViewMatrix(); + osg::Matrixd &projectionMatrix = cascade->getProjectionMatrix(); + + osg::BoundingSphere bs; + bs.expandBy(osg::Vec3(left,bottom,-zNear) * f1); + bs.expandBy(osg::Vec3(right,top,-zNear) * f2); + bs.expandBy(osg::Vec3(left,bottom,-zNear) * f2); + bs.expandBy(osg::Vec3(right,top,-zNear) * f1); + + osg::Vec4 aim = osg::Vec4(bs.center(), 1.0) * camera->getInverseViewMatrix(); + + projectionMatrix.makeOrtho( -bs.radius(), bs.radius(), -bs.radius(), bs.radius(), 1., 15000.0 ); + osg::Vec3 position( aim.x(), aim.y(), aim.z() ); + viewMatrix.makeLookAt( position + (getSunDirection() * 10000.0), position, position ); +} + +osg::Vec3 FGRenderer::getSunDirection() const +{ + osg::Vec3 val; + _sunDirection->get( val ); + return val; +} + +void FGRenderer::updateShadowCamera(const flightgear::CameraInfo* info, const osg::Vec3d& position) +{ + ref_ptr<Camera> mainShadowCamera = info->getCamera( SHADOW_CAMERA ); + if (mainShadowCamera.valid()) { + ref_ptr<Switch> shadowSwitch = mainShadowCamera->getChild( 0 )->asSwitch(); + osg::Vec3d up = position, + dir = getSunDirection(); + up.normalize(); + dir.normalize(); + // cos(100 deg) == -0.17 + if (up * dir < -0.17 ) { + shadowSwitch->setAllChildrenOff(); + } else { + double left,right,bottom,top,zNear,zFar; + ref_ptr<Camera> camera = info->getCamera(GEOMETRY_CAMERA); + camera->getProjectionMatrix().getFrustum(left,right,bottom,top,zNear,zFar); + + shadowSwitch->setAllChildrenOn(); + osg::Group* grp = mainShadowCamera->getChild(0)->asGroup(); + updateShadowCascade(info, camera, grp, 0, left, right, bottom, top, zNear, 1.0, 5.0/zNear); + updateShadowCascade(info, camera, grp, 1, left, right, bottom, top, zNear, 5.0/zNear,50.0/zNear); + updateShadowCascade(info, camera, grp, 2, left, right, bottom, top, zNear, 50.0/zNear,512.0/zNear); + updateShadowCascade(info, camera, grp, 3, left, right, bottom, top, zNear, 512.0/zNear,10000.0/zNear); + { + osg::Camera* cascade = static_cast<osg::Camera*>( mainShadowCamera ); + osg::Matrixd &viewMatrix = cascade->getViewMatrix(); + osg::Matrixd &projectionMatrix = cascade->getProjectionMatrix(); + + osg::Vec4 aim = osg::Vec4( 0.0, 0.0, -7500., 1.0 ) * camera->getInverseViewMatrix(); + + projectionMatrix.makeOrtho( -7500., 7500., -7500., 7500., 1., 15000.0 ); + osg::Vec3 position( aim.x(), aim.y(), aim.z() ); + viewMatrix.makeLookAt( position + (getSunDirection() * 10000.0), position, position ); + } + } + } +} + #define STRINGIFY(x) #x #define TOSTRING(x) STRINGIFY(x) @@ -741,7 +885,7 @@ const char *ambient_vert_src = "" const char *ambient_frag_src = "" "#line " TOSTRING(__LINE__) " 1\n" "uniform sampler2D color_tex;\n" - "uniform sampler2D ao_tex;\n" +// "uniform sampler2D ao_tex;\n" "uniform sampler2D normal_tex;\n" "uniform sampler2D spec_emis_tex;\n" "uniform vec4 fg_SunAmbientColor;\n" @@ -751,8 +895,9 @@ const char *ambient_frag_src = "" " if ( initialized < 0.1 )\n" " discard;\n" " vec3 tcolor = texture2D( color_tex, coords ).rgb;\n" - " float ao = texture2D( ao_tex, coords ).r;\n" - " gl_FragColor = vec4(tcolor*fg_SunAmbientColor.rgb*ao, 1.0);\n" +// " float ao = texture2D( ao_tex, coords ).r;\n" +// " gl_FragColor = vec4(tcolor*fg_SunAmbientColor.rgb*ao, 1.0);\n" + " gl_FragColor = vec4(tcolor*fg_SunAmbientColor.rgb, 1.0);\n" "}\n"; const char *sunlight_vert_src = "" @@ -768,7 +913,9 @@ const char *sunlight_vert_src = "" "}\n"; const char *sunlight_frag_src = "" +#if 0 "#version 130\n" +#endif "#line " TOSTRING(__LINE__) " 1\n" "uniform mat4 fg_ViewMatrix;\n" "uniform sampler2D depth_tex;\n" @@ -829,9 +976,9 @@ const char *sunlight_frag_src = "" " vec4 tint;\n" #if 0 - " float shadow = shadow2DProj( shadow_tex, DynamicShadow( vec4( pos, 1.0 ), tint ) ).r;\n" -#elif 1 " float shadow = 1.0;\n" +#elif 1 + " float shadow = shadow2DProj( shadow_tex, DynamicShadow( vec4( pos, 1.0 ), tint ) ).r;\n" #else " float kernel[9] = float[]( 36/256.0, 24/256.0, 6/256.0,\n" " 24/256.0, 16/256.0, 4/256.0,\n" @@ -960,12 +1107,12 @@ osg::Camera* FGRenderer::buildDeferredLightingCamera( flightgear::CameraInfo* in ss->setTextureAttributeAndModes( 1, info->getBuffer( flightgear::RenderBufferInfo::NORMAL_BUFFER ) ); ss->setTextureAttributeAndModes( 2, info->getBuffer( flightgear::RenderBufferInfo::DIFFUSE_BUFFER ) ); ss->setTextureAttributeAndModes( 3, info->getBuffer( flightgear::RenderBufferInfo::SPEC_EMIS_BUFFER ) ); - //ss->setTextureAttributeAndModes( 5, info->gBuffer->aoBuffer[2] ); + //ss->setTextureAttributeAndModes( 4, info->gBuffer->aoBuffer[2] ); ss->addUniform( new osg::Uniform( "depth_tex", 0 ) ); ss->addUniform( new osg::Uniform( "normal_tex", 1 ) ); ss->addUniform( new osg::Uniform( "color_tex", 2 ) ); ss->addUniform( new osg::Uniform( "spec_emis_tex", 3 ) ); - //ss->addUniform( new osg::Uniform( "ao_tex", 5 ) ); + //ss->addUniform( new osg::Uniform( "ao_tex", 4 ) ); ss->setRenderBinDetails( 0, "RenderBin" ); osg::Program* program = new osg::Program; program->addShader( new osg::Shader( osg::Shader::VERTEX, ambient_vert_src ) ); @@ -991,16 +1138,16 @@ osg::Camera* FGRenderer::buildDeferredLightingCamera( flightgear::CameraInfo* in ss->setMode( GL_LIGHTING, osg::StateAttribute::OFF ); ss->setMode( GL_DEPTH_TEST, osg::StateAttribute::OFF ); ss->setAttributeAndModes( new osg::BlendFunc( osg::BlendFunc::ONE, osg::BlendFunc::ONE ) ); - ss->setTextureAttributeAndModes( 0, info->getBuffer( flightgear::RenderBufferInfo::DEPTH_BUFFER ) ); - ss->setTextureAttributeAndModes( 1, info->getBuffer( flightgear::RenderBufferInfo::NORMAL_BUFFER ) ); - ss->setTextureAttributeAndModes( 2, info->getBuffer( flightgear::RenderBufferInfo::DIFFUSE_BUFFER ) ); - ss->setTextureAttributeAndModes( 3, info->getBuffer( flightgear::RenderBufferInfo::SPEC_EMIS_BUFFER ) ); - //ss->setTextureAttribute( 4, info->mainShadowMap ); + ss->setTextureAttribute( 0, info->getBuffer( flightgear::RenderBufferInfo::DEPTH_BUFFER ) ); + ss->setTextureAttribute( 1, info->getBuffer( flightgear::RenderBufferInfo::NORMAL_BUFFER ) ); + ss->setTextureAttribute( 2, info->getBuffer( flightgear::RenderBufferInfo::DIFFUSE_BUFFER ) ); + ss->setTextureAttribute( 3, info->getBuffer( flightgear::RenderBufferInfo::SPEC_EMIS_BUFFER ) ); + ss->setTextureAttribute( 4, info->getBuffer( flightgear::RenderBufferInfo::SHADOW_BUFFER ) ); ss->addUniform( new osg::Uniform( "depth_tex", 0 ) ); ss->addUniform( new osg::Uniform( "normal_tex", 1 ) ); ss->addUniform( new osg::Uniform( "color_tex", 2 ) ); ss->addUniform( new osg::Uniform( "spec_emis_tex", 3 ) ); - //ss->addUniform( new osg::Uniform( "shadow_tex", 4 ) ); + ss->addUniform( new osg::Uniform( "shadow_tex", 4 ) ); ss->setRenderBinDetails( 1, "RenderBin" ); osg::Program* program = new osg::Program; program->addShader( new osg::Shader( osg::Shader::VERTEX, sunlight_vert_src ) ); @@ -1101,13 +1248,19 @@ FGRenderer::buildDeferredPipeline(flightgear::CameraGroup* cgroup, unsigned flag osg::GraphicsContext* gc) { CameraInfo* info = new CameraInfo(flags); - buildDeferredBuffers( info ); + buildDeferredBuffers( info, _shadowMapSize ); osg::Camera* geometryCamera = buildDeferredGeometryCamera( info, gc ); cgroup->getViewer()->addSlave(geometryCamera, false); installCullVisitor(geometryCamera); int slaveIndex = cgroup->getViewer()->getNumSlaves() - 1; info->getRenderStageInfo(GEOMETRY_CAMERA).slaveIndex = slaveIndex; + + osg::Camera* shadowCamera = buildDeferredShadowCamera( info, gc ); + cgroup->getViewer()->addSlave(shadowCamera, false); + installCullVisitor(shadowCamera); + slaveIndex = cgroup->getViewer()->getNumSlaves() - 1; + info->getRenderStageInfo(SHADOW_CAMERA).slaveIndex = slaveIndex; osg::Camera* lightingCamera = buildDeferredLightingCamera( info, gc ); cgroup->getViewer()->addSlave(lightingCamera, false); diff --git a/src/Main/renderer.hxx b/src/Main/renderer.hxx index 618055236..0db0fa5d7 100644 --- a/src/Main/renderer.hxx +++ b/src/Main/renderer.hxx @@ -8,6 +8,7 @@ #include <osg/ref_ptr> #include <osg/Matrix> +#include <osg/Vec3> namespace osg { @@ -103,6 +104,8 @@ public: flightgear::CameraInfo* buildDeferredPipeline(flightgear::CameraGroup* cgroup, unsigned flags, osg::Camera* camera, const osg::Matrix& view, const osg::Matrix& projection, osg::GraphicsContext* gc); + void updateShadowCamera(const flightgear::CameraInfo* info, const osg::Vec3d& position); + SGSky* getSky() const { return _sky; } void setPlanes( double zNear, double zFar ); @@ -125,9 +128,13 @@ protected: SGTimeStamp _splash_time; SGSky* _sky; bool _classicalRenderer; + int _shadowMapSize; osg::Camera* buildDeferredGeometryCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc ); + osg::Camera* buildDeferredShadowCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc ); osg::Camera* buildDeferredLightingCamera( flightgear::CameraInfo* info, osg::GraphicsContext* gc ); + void updateShadowCascade(const flightgear::CameraInfo* info, osg::Camera* camera, osg::Group* grp, int idx, double left, double right, double bottom, double top, double zNear, double f1, double f2); + osg::Vec3 getSunDirection() const; osg::ref_ptr<osg::Uniform> _ambientFactor; osg::ref_ptr<osg::Uniform> _sunDiffuse; osg::ref_ptr<osg::Uniform> _sunSpecular;