- Timestamp:
- 03/21/12 18:36:20 (14 months ago)
- Files:
-
- 1 modified
Legend:
- Unmodified
- Added
- Removed
-
OpenSceneGraph/trunk/src/osgShadow/StandardShadowMap.cpp
r12737 r13041 1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 1 /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 2 2 * 3 * This library is open source and may be redistributed and/or modified under 4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 3 * This library is open source and may be redistributed and/or modified under 4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 5 5 * (at your option) any later version. The full license is in LICENSE file 6 6 * included with this distribution, and on the openscenegraph.org website. 7 * 7 * 8 8 * This library is distributed in the hope that it will be useful, 9 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 11 * OpenSceneGraph Public License for more details. 12 12 * … … 34 34 35 35 StandardShadowMap::StandardShadowMap(): 36 BaseClass(), 36 BaseClass(), 37 37 _polygonOffsetFactor( 1.1f ), 38 38 _polygonOffsetUnits( 4.0f ), … … 43 43 _shadowTextureCoordIndex( 1 ) 44 44 45 { 45 { 46 46 #if FRAGMENT_SHADERS_ONLY 47 47 _mainFragmentShader = new osg::Shader( osg::Shader::FRAGMENT, … … 70 70 // " color.rgb = mix( gl_Fog.color.rgb, color.rgb, fog ); \n" 71 71 " gl_FragColor = color; \n" 72 "} \n" ); 72 "} \n" ); 73 73 74 74 _shadowFragmentShader = new osg::Shader( osg::Shader::FRAGMENT, … … 82 82 " return shadow2DProj( shadowTexture, gl_TexCoord[1] ).r; \n" 83 83 "} \n" ); 84 85 84 85 86 86 _shadowVertexShader = NULL; 87 87 _mainVertexShader = NULL; … … 112 112 // " color.rgb = mix( gl_Fog.color.rgb, color.rgb, fog ); \n" 113 113 " gl_FragColor = color; \n" 114 "} \n" ); 115 116 114 "} \n" ); 115 116 117 117 _shadowFragmentShader = new osg::Shader( osg::Shader::FRAGMENT, 118 118 " // following expressions are auto modified - do not change them: \n" … … 126 126 "} \n" ); 127 127 128 129 128 129 130 130 _shadowVertexShader = new osg::Shader( osg::Shader::VERTEX, 131 131 " // following expressions are auto modified - do not change them: \n" … … 144 144 " gl_TexCoord[1].q = dot( ecPosition, gl_EyePlaneQ[1] ); \n" 145 145 "} \n" ); 146 146 147 147 _mainVertexShader = new osg::Shader( osg::Shader::VERTEX, 148 148 " // following expressions are auto modified - do not change them: \n" … … 237 237 " d = length(VP); \n" 238 238 " \n" 239 " // Normalize the vector from surface to light position \n" 239 " // Normalize the vector from surface to light position \n" 240 240 " VP = normalize(VP); \n" 241 241 " \n" … … 361 361 } 362 362 363 StandardShadowMap::~StandardShadowMap(void) 364 { 365 366 } 363 StandardShadowMap::~StandardShadowMap(void) 364 { 365 366 } 367 367 368 368 void StandardShadowMap::updateTextureCoordIndices( unsigned int fromTextureCoordIndex, unsigned int toTextureCoordIndex ) … … 387 387 char acFrom[ 32 ], acTo[32]; 388 388 389 // its not elegant to mix stdio & stl strings 389 // its not elegant to mix stdio & stl strings 390 390 // but in this context I do an exception for cleaner code 391 391 … … 413 413 414 414 std::string::size_type fromLength = fromString.length(); 415 std::string::size_type srceLength = srceString.length(); 415 std::string::size_type srceLength = srceString.length(); 416 416 417 417 for( std::string::size_type pos = 0; pos < srceLength; ) … … 423 423 424 424 destString.append( srceString, pos, end - pos ); 425 425 426 426 if( end == srceLength ) 427 427 break; … … 436 436 void StandardShadowMap::ViewData::cull() 437 437 { 438 // step 1: 439 // cull shadowed scene ie put into render bins and states into stage graphs 438 // step 1: 439 // cull shadowed scene ie put into render bins and states into stage graphs 440 440 cullShadowReceivingScene( ); 441 441 442 442 // step 2: 443 // find the light casting our shadows 443 // find the light casting our shadows 444 444 osg::Vec4 lightPos; 445 445 osg::Vec3 lightDir; … … 455 455 456 456 // step 4: 457 // cull scene casting shadow and generate render 457 // cull scene casting shadow and generate render 458 458 cullShadowCastingScene( ); 459 459 460 460 // step 5: 461 // setup texgen generating shadow map coords for the shadow receiving scene 461 // setup texgen generating shadow map coords for the shadow receiving scene 462 462 addShadowReceivingTexGen( ); 463 463 … … 488 488 _texture = texture; 489 489 } 490 490 491 491 _camera = new osg::Camera; 492 { // Setup shadow map camera 492 { // Setup shadow map camera 493 493 _camera->setName( "ShadowCamera" ); 494 494 #if 0 // Absolute reference frame INHERIT_VIEWPOINT works better than this 495 495 _camera->setCullingMode 496 ( _camera->getCullingMode() & ~osg::CullSettings::SMALL_FEATURE_CULLING ); 496 ( _camera->getCullingMode() & ~osg::CullSettings::SMALL_FEATURE_CULLING ); 497 497 #endif 498 498 _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF_INHERIT_VIEWPOINT); … … 504 504 _camera->setClearColor( osg::Vec4(1.0f,1.0f,1.0f,1.0f) ); 505 505 #endif 506 _camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); 506 _camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); 507 507 _camera->setViewport(0,0, st->_textureSize.x(), st->_textureSize.y() ); 508 _camera->setRenderOrder(osg::Camera::PRE_RENDER); 509 _camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); 508 _camera->setRenderOrder(osg::Camera::PRE_RENDER); 509 _camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT); 510 510 _camera->attach(osg::Camera::DEPTH_BUFFER, _texture.get()); 511 511 } … … 518 518 image->allocateImage( 1, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE ); 519 519 *(osg::Vec4ub*)image->data() = osg::Vec4ub( 0xFF, 0xFF, 0xFF, 0xFF ); 520 520 521 521 osg::Texture2D* fakeTex = new osg::Texture2D( image ); 522 522 fakeTex->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::REPEAT); … … 524 524 fakeTex->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::NEAREST); 525 525 fakeTex->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::NEAREST); 526 526 527 527 _stateset->setTextureAttribute(st->_baseTextureUnit,fakeTex,osg::StateAttribute::ON); 528 528 _stateset->setTextureMode(st->_baseTextureUnit,GL_TEXTURE_2D,osg::StateAttribute::ON); … … 533 533 } 534 534 535 { // Add shadow texture 535 { // Add shadow texture 536 536 _stateset->setTextureAttributeAndModes(st->_shadowTextureUnit,_texture.get(),osg::StateAttribute::ON); 537 537 _stateset->setTextureMode(st->_shadowTextureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); … … 541 541 } 542 542 543 { // Setup shaders used in shadow casting 543 { // Setup shaders used in shadow casting 544 544 osg::Program * program = new osg::Program(); 545 545 _stateset->setAttribute( program ); … … 565 565 { // Setup states used for shadow map generation 566 566 osg::StateSet * stateset = _camera->getOrCreateStateSet(); 567 568 stateset->setAttribute( 567 568 stateset->setAttribute( 569 569 new osg::PolygonOffset( st->_polygonOffsetFactor, st->_polygonOffsetUnits ), 570 570 osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE ); … … 574 574 575 575 // agressive optimization 576 stateset->setRenderBinDetails( 0, "RenderBin", 576 stateset->setRenderBinDetails( 0, "RenderBin", 577 577 osg::StateSet::OVERRIDE_RENDERBIN_DETAILS ); 578 578 … … 589 589 590 590 // note soft (attribute only no mode override) setting. When this works ? 591 // 1. for objects prepared for backface culling 591 // 1. for objects prepared for backface culling 592 592 // because they usually also set CullFace and CullMode on in their state 593 593 // For them we override CullFace but CullMode remains set by them 594 // 2. For one faced, trees, and similar objects which cannot use 594 // 2. For one faced, trees, and similar objects which cannot use 595 595 // backface nor front face so they usually use CullMode off set here. 596 596 // In this case we will draw them in their entirety. … … 599 599 osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE ); 600 600 601 // make sure GL_CULL_FACE is off by default 602 // we assume that if object has cull face attribute set to back 601 // make sure GL_CULL_FACE is off by default 602 // we assume that if object has cull face attribute set to back 603 603 // it will also set cull face mode ON so no need for override 604 604 stateset->setMode( GL_CULL_FACE, osg::StateAttribute::OFF ); 605 605 606 // optimization attributes 606 // optimization attributes 607 607 osg::Program* program = new osg::Program; 608 608 stateset->setAttribute( program, osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON ); … … 649 649 osgUtil::RenderStage * rs = _cv->getRenderStage(); 650 650 651 osgUtil::PositionalStateContainer::AttrMatrixList& aml = 651 osgUtil::PositionalStateContainer::AttrMatrixList& aml = 652 652 rs->getPositionalStateContainer()->getAttrMatrixList(); 653 653 … … 678 678 if( lightPos[3] == 0 ) 679 679 lightDir.set( -lightPos[0], -lightPos[1], -lightPos[2] ); 680 else 681 lightDir = light->getDirection(); 680 else 681 lightDir = light->getDirection(); 682 682 683 683 lightPos = lightPos * localToWorld; … … 691 691 void StandardShadowMap::ViewData::aimShadowCastingCamera( const osg::Light *light, 692 692 const osg::Vec4 &lightPos, 693 const osg::Vec3 &lightDir, 693 const osg::Vec3 &lightDir, 694 694 const osg::Vec3 &lightUp 695 695 /* by default = osg::Vec3( 0, 1 0 )*/ ) 696 696 { 697 #if 0 // less precise but faster 697 #if 0 // less precise but faster 698 698 osg::BoundingSphere bs =_st->getShadowedScene()->getBound(); 699 699 #else … … 709 709 } 710 710 711 void StandardShadowMap::ViewData::aimShadowCastingCamera( 711 void StandardShadowMap::ViewData::aimShadowCastingCamera( 712 712 const osg::BoundingSphere &bs, 713 713 const osg::Light *light, 714 714 const osg::Vec4 &lightPos, 715 const osg::Vec3 &lightDir, 716 const osg::Vec3 &lightUpVector 715 const osg::Vec3 &lightDir, 716 const osg::Vec3 &lightUpVector 717 717 /* by default = osg::Vec3( 0, 1 0 )*/ ) 718 718 { … … 730 730 position = bs.center() - lightDir * bs.radius() * 2; 731 731 } 732 732 733 733 float centerDistance = (position-bs.center()).length(); 734 734 float znear = centerDistance-bs.radius(); 735 735 float zfar = centerDistance+bs.radius(); 736 736 float zNearRatio = 0.001f; 737 if (znear<zfar*zNearRatio) 737 if (znear<zfar*zNearRatio) 738 738 znear = zfar*zNearRatio; 739 739 … … 765 765 _cv->pushStateSet( _stateset.get() ); 766 766 767 _st->getShadowedScene()->osg::Group::traverse( *_cv ); 767 _st->getShadowedScene()->osg::Group::traverse( *_cv ); 768 768 769 769 _cv->popStateSet(); … … 771 771 772 772 void StandardShadowMap::ViewData::cullShadowCastingScene( ) 773 { 773 { 774 774 // record the traversal mask on entry so we can reapply it later. 775 775 unsigned int traversalMask = _cv->getTraversalMask(); 776 776 777 _cv->setTraversalMask( traversalMask & 777 _cv->setTraversalMask( traversalMask & 778 778 _st->getShadowedScene()->getCastsShadowTraversalMask() ); 779 779 … … 786 786 787 787 void StandardShadowMap::ViewData::addShadowReceivingTexGen( ) 788 { 788 { 789 789 _texgen->setMode(osg::TexGen::EYE_LINEAR); 790 790
