00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043 #include <cstdlib>
00044 #include <cstdio>
00045
00046 #include "OSGConfig.h"
00047
00048 #include "OSGShaderShadowMapEngine.h"
00049
00050 #include "OSGMatrixUtility.h"
00051 #include "OSGSolidBackground.h"
00052 #include "OSGColorMaskChunk.h"
00053 #include "OSGMaterialChunk.h"
00054 #include "OSGPolygonChunk.h"
00055 #include "OSGShaderProgram.h"
00056
00057 #include "OSGBlendChunk.h"
00058 #include "OSGDepthChunk.h"
00059
00060 #include "OSGGL.h"
00061
00062 #include <boost/cast.hpp>
00063
00064 #include <strstream>
00065
00066 OSG_BEGIN_NAMESPACE
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 const Matrixr ShaderShadowMapEngine::_matCubeFaceInv[6] =
00078 {
00079 Matrixr( 1, 0, 0, 0,
00080 0, -1, 0, 0,
00081 0, 0, -1, 0,
00082 0, 0, 0, 1),
00083
00084 Matrixr(-1, 0, 0, 0,
00085 0, -1, 0, 0,
00086 0, 0, 1, 0,
00087 0, 0, 0, 1),
00088
00089 Matrixr( 1, 0, 0, 0,
00090 0, 0, 1, 0,
00091 0, -1, 0, 0,
00092 0, 0, 0, 1),
00093
00094 Matrixr( 1, 0, 0, 0,
00095 0, 0, -1, 0,
00096 0, 1, 0, 0,
00097 0, 0, 0, 1),
00098
00099 Matrixr( 0, 0, -1, 0,
00100 0, -1, 0, 0,
00101 -1, 0, 0, 0,
00102 0, 0, 0, 1),
00103
00104 Matrixr( 0, 0, 1, 0,
00105 0, -1, 0, 0,
00106 1, 0, 0, 0,
00107 0, 0, 0, 1),
00108 };
00109
00110 const GLenum ShaderShadowMapEngine::_cubeFaceTargets[6] =
00111 {
00112 GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
00113 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
00114 GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
00115 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
00116 GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
00117 GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
00118 };
00119
00120 const std::string ShaderShadowMapEngine::_pointFPCode(
00121 "#version 120\n"
00122 "\n"
00123 "#extension GL_EXT_gpu_shader4 : require\n"
00124 "#extension GL_EXT_gpu_shader4 : enable\n"
00125 "\n"
00126 "uniform samplerCubeShadow SSME_texShadow;\n"
00127 "\n"
00128 "uniform mat4 SSME_matEyeToLight;\n"
00129 "uniform mat4 SSME_matLightProj;\n"
00130 "\n"
00131 "vec4 OSG_SSME_FP_calcShadow(in vec4 ecFragPos)\n"
00132 "{\n"
00133 " vec4 shadow = vec4(0., 0., 0., 0.);\n"
00134 " vec4 lcPos = SSME_matEyeToLight * ecFragPos;\n"
00135 " vec4 lcAbsPos = abs(lcPos);\n"
00136 " vec4 plcPos;\n"
00137 "\n"
00138 " if(lcAbsPos.x > lcAbsPos.y && lcAbsPos.x > lcAbsPos.z)\n"
00139 " {\n"
00140 " if(lcPos.x >= 0.)\n"
00141 " plcPos = vec4(-1, -1, -1, 1) * lcPos.zyxw;\n"
00142 " else\n"
00143 " plcPos = vec4( 1, -1, 1, 1) * lcPos.zyxw;\n"
00144 " }\n"
00145 " else if(lcAbsPos.y > lcAbsPos.x && lcAbsPos.y > lcAbsPos.z)\n"
00146 " {\n"
00147 " if(lcPos.y >= 0.)\n"
00148 " plcPos = vec4( 1, 1, -1, 1) * lcPos.xzyw;\n"
00149 " else\n"
00150 " plcPos = vec4( 1, -1, 1, 1) * lcPos.xzyw;\n"
00151 " }\n"
00152 " else\n"
00153 " {\n"
00154 " if(lcPos.z >= 0.)\n"
00155 " plcPos = vec4( 1, -1, -1, 1) * lcPos;\n"
00156 " else\n"
00157 " plcPos = vec4(-1, -1, 1, 1) * lcPos;\n"
00158 " }\n"
00159 "\n"
00160 " plcPos = SSME_matLightProj * plcPos;\n"
00161 " plcPos = plcPos / plcPos.w;\n"
00162 " plcPos = 0.5 + 0.5 * plcPos;\n"
00163 "\n"
00164 " shadow = shadowCube(SSME_texShadow, vec4(lcPos.xyz, plcPos.z));\n"
00165 "\n"
00166 " return shadow;\n"
00167 "}\n");
00168
00169 const std::string ShaderShadowMapEngine::_dirFPCode(
00170 "#version 120\n"
00171 "\n"
00172 "uniform sampler2DShadow SSME_texShadow;\n"
00173 "\n"
00174 "uniform mat4 SSME_matEyeToLight;\n"
00175 "uniform mat4 SSME_matLightProj;\n"
00176 "\n"
00177 "vec4 OSG_SSME_FP_calcShadow(in vec4 ecFragPos)\n"
00178 "{\n"
00179 " vec4 lcPos = SSME_matEyeToLight * ecFragPos;\n"
00180 " vec4 plcPos = SSME_matLightProj * lcPos;\n"
00181 "\n"
00182 " plcPos = plcPos / plcPos.w;\n"
00183 " plcPos = 0.5 + 0.5 * plcPos;\n"
00184 "\n"
00185 " return shadow2D(SSME_texShadow, plcPos.xyz);\n"
00186 "}\n");
00187
00188 const std::string ShaderShadowMapEngine::_spotFPCode(
00189 "#version 120\n"
00190 "\n"
00191 "uniform sampler2DShadow SSME_texShadow;\n"
00192 "\n"
00193 "uniform mat4 SSME_matEyeToLight;\n"
00194 "uniform mat4 SSME_matLightProj;\n"
00195 "\n"
00196 "vec4 OSG_SSME_FP_calcShadow(in vec4 ecFragPos)\n"
00197 "{\n"
00198 " vec4 lcPos = SSME_matEyeToLight * ecFragPos;\n"
00199 " vec4 plcPos = SSME_matLightProj * lcPos;\n"
00200 "\n"
00201 " plcPos = plcPos / plcPos.w;\n"
00202 " plcPos = 0.5 + 0.5 * plcPos;\n"
00203 "\n"
00204 " return shadow2D(SSME_texShadow, plcPos.xyz);\n"
00205 "}\n");
00206
00207
00208
00209
00210
00211 void ShaderShadowMapEngine::initMethod(InitPhase ePhase)
00212 {
00213 Inherited::initMethod(ePhase);
00214 }
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227 ShaderShadowMapEngine::ShaderShadowMapEngine(void) :
00228 Inherited()
00229 {
00230 }
00231
00232 ShaderShadowMapEngine::ShaderShadowMapEngine(const ShaderShadowMapEngine &source) :
00233 Inherited(source)
00234 {
00235 }
00236
00237 ShaderShadowMapEngine::~ShaderShadowMapEngine(void)
00238 {
00239 }
00240
00241
00242
00243 ActionBase::ResultE ShaderShadowMapEngine::runOnEnter(
00244 Light *light, LightTypeE eType, RenderAction *ract)
00245 {
00246 BitVector bvMask = ract->getPassMask ( );
00247 SSMEngineData *data = ract->getData<SSMEngineData *>(_iDataSlotId);
00248
00249 if(data == NULL)
00250 {
00251 SSMEngineDataUnrecPtr newData = SSMEngineData::createLocal();
00252 this->setData(newData, _iDataSlotId, ract);
00253
00254 data = newData;
00255 }
00256
00257 if(0x0000 != bvMask)
00258 {
00259
00260 if(0x0000 != (bvMask & bvLightPassMask))
00261 {
00262 this->recurseFrom(ract, light);
00263
00264 handleEnter(light, eType, ract, data);
00265 }
00266 }
00267 else
00268 {
00269
00270 ract->addPassMask(bvLightPassMask);
00271 handleEnter(light, eType, ract, data);
00272 ract->subPassMask(bvLightPassMask);
00273 }
00274
00275
00276 return Action::Continue;
00277 }
00278
00279 ActionBase::ResultE ShaderShadowMapEngine::runOnLeave(
00280 Light *light, LightTypeE eType, RenderAction *ract)
00281 {
00282 return Action::Continue;
00283 }
00284
00285 void ShaderShadowMapEngine::changed(ConstFieldMaskArg whichField,
00286 UInt32 origin,
00287 BitVector details)
00288 {
00289 Inherited::changed(whichField, origin, details);
00290 }
00291
00292 void ShaderShadowMapEngine::dump( UInt32 ,
00293 const BitVector ) const
00294 {
00295 SLOG << "Dump ShaderShadowMapEngine NI" << std::endl;
00296 }
00297
00298 void ShaderShadowMapEngine::handleEnter(
00299 Light *light, LightTypeE eType, RenderAction *ract, SSMEngineData *data)
00300 {
00301 updateShadowTexChunk (data);
00302 updateLightPassMaterial(data);
00303 updateBackground (data);
00304
00305 UInt32 parentTravMask = ract->getTravMask();
00306 ract->setTravMask(_sfShadowTravMask.getValue());
00307
00308
00309 switch(eType)
00310 {
00311 case Point:
00312 {
00313 PointLight *pointL =
00314 boost::polymorphic_downcast<PointLight *>(light);
00315
00316 handlePointLightEnter(pointL, ract, data);
00317 }
00318 break;
00319
00320 case Directional:
00321 {
00322 DirectionalLight *dirL =
00323 boost::polymorphic_downcast<DirectionalLight *>(light);
00324
00325 handleDirectionalLightEnter(dirL, ract, data);
00326 }
00327 break;
00328
00329 case Spot:
00330 {
00331 SpotLight *spotL =
00332 boost::polymorphic_downcast<SpotLight *>(light);
00333
00334 handleSpotLightEnter(spotL, ract, data);
00335 }
00336 break;
00337
00338 default:
00339 {
00340 FWARNING(("ShaderShadowMapEngine::handleEnter: Unknown "
00341 "light type [%u]\n", eType));
00342 }
00343 break;
00344 }
00345
00346 ract->setTravMask(parentTravMask);
00347 }
00348
00349 void ShaderShadowMapEngine::handlePointLightEnter(
00350 PointLight *pointL, RenderAction *ract, SSMEngineData *data)
00351 {
00352 RenderPartition *parentPart = ract->getActivePartition();
00353
00354 Matrixr matEyeToWorld(parentPart->getCameraToWorld());
00355 Matrixr matLightProj;
00356
00357 Real lightNear;
00358 Real lightFar;
00359
00360 calcPointLightRange(pointL, 0.001f,
00361 parentPart->getNear(), parentPart->getFar(),
00362 lightNear, lightFar );
00363
00364 MatrixPerspective(matLightProj, Pi / 4.f, 1.f,
00365 lightNear, lightFar );
00366
00367 Matrixr matWorldToLight;
00368 Matrixr matEyeToLight;
00369
00370 calcPointLightMatrices(matWorldToLight, matEyeToLight,
00371 pointL, matEyeToWorld );
00372
00373 updatePointLightShadowTexImage (data);
00374 updatePointLightShadowTexBuffers(data);
00375 updatePointLightRenderTargets (data);
00376
00377 Int32 shadowTexUnit = (this->getForceTextureUnit() > 0) ?
00378 this->getForceTextureUnit() : 7;
00379
00380 ShaderProgram *shadowFP = this->getShadowFragmentProgram();
00381
00382 if(shadowFP == NULL)
00383 {
00384 ShaderProgramUnrecPtr newShadowFP = ShaderProgram::createLocal();
00385 newShadowFP->setShaderType(GL_FRAGMENT_SHADER);
00386 newShadowFP->setProgram (_pointFPCode );
00387
00388 newShadowFP->addUniformVariable("SSME_matEyeToLight", matEyeToLight);
00389 newShadowFP->addUniformVariable("SSME_matLightProj", matLightProj );
00390 newShadowFP->addUniformVariable("SSME_texShadow", shadowTexUnit);
00391
00392 this->setShadowFragmentProgram(newShadowFP);
00393 shadowFP = newShadowFP;
00394 }
00395 else
00396 {
00397 shadowFP->updateUniformVariable("SSME_matEyeToLight", matEyeToLight);
00398 shadowFP->updateUniformVariable("SSME_matLightProj", matLightProj );
00399 }
00400
00401 commitChanges();
00402
00403
00404 for(UInt16 i = 0; i < 6; ++i)
00405 {
00406 Matrixr matWorldToLightFace(matWorldToLight);
00407 matWorldToLightFace.multLeft(_matCubeFaceInv[i]);
00408
00409 ract->pushPartition();
00410 {
00411 RenderPartition *part = ract->getActivePartition( );
00412 Window *win = ract->getWindow ( );
00413 FrameBufferObject *target = data->getRenderTargets (i);
00414 Background *back = data->getBackground ( );
00415
00416 part->setRenderTarget(target);
00417 part->setWindow (win );
00418
00419 part->calcViewportDimension(0.f, 0.f, 1.f, 1.f,
00420 target->getWidth (),
00421 target->getHeight() );
00422
00423 part->setupProjection(matLightProj, Matrixr::identity());
00424 part->setupViewing (matWorldToLightFace );
00425
00426 part->setNear (parentPart->getNear());
00427 part->setFar (parentPart->getFar ());
00428
00429 part->calcFrustum ( );
00430
00431 part->setBackground (back );
00432
00433
00434 part->overrideMaterial(data->getLightPassMaterials(0),
00435 ract->getActNode ( ) );
00436
00437 this->recurseFrom(ract, pointL);
00438 ract->useNodeList(false );
00439
00440
00441 part->overrideMaterial(NULL,
00442 ract->getActNode ( ) );
00443 }
00444 ract->popPartition();
00445 }
00446 }
00447
00448 void ShaderShadowMapEngine::handleDirectionalLightEnter(
00449 DirectionalLight *dirL, RenderAction *ract, SSMEngineData *data)
00450 {
00451 RenderPartition *parentPart = ract ->getActivePartition();
00452 FrustumVolume camFrust = parentPart->getFrustum ();
00453
00454 Matrixr matEyeToWorld (parentPart->getCameraToWorld());
00455 Matrixr matWorldToLight;
00456 Matrixr matEyeToLight;
00457
00458 calcDirectionalLightMatrices(matWorldToLight, matEyeToLight,
00459 dirL, matEyeToWorld );
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 Pnt3r camVerts [10];
00471 Pnt3r sceneVerts[10];
00472 const Matrix &matSceneToWorld = ract->topMatrix ();
00473 BoxVolume sceneBB = ract->getActNode()->getVolume();
00474
00475 camFrust.getCorners(camVerts [0], camVerts [1],
00476 camVerts [2], camVerts [3],
00477 camVerts [4], camVerts [5],
00478 camVerts [6], camVerts [7] );
00479 sceneBB .getCorners(sceneVerts[0], sceneVerts[1],
00480 sceneVerts[2], sceneVerts[3],
00481 sceneVerts[4], sceneVerts[5],
00482 sceneVerts[6], sceneVerts[7] );
00483
00484 camVerts [8].setValues(TypeTraits<Real>::getMax(),
00485 TypeTraits<Real>::getMax(),
00486 TypeTraits<Real>::getMax() );
00487 camVerts [9].setValues(TypeTraits<Real>::getMin(),
00488 TypeTraits<Real>::getMin(),
00489 TypeTraits<Real>::getMin() );
00490 sceneVerts[8].setValues(TypeTraits<Real>::getMax(),
00491 TypeTraits<Real>::getMax(),
00492 TypeTraits<Real>::getMax() );
00493 sceneVerts[9].setValues(TypeTraits<Real>::getMin(),
00494 TypeTraits<Real>::getMin(),
00495 TypeTraits<Real>::getMin() );
00496
00497 for(UInt32 i = 0; i < 8; ++i)
00498 {
00499 matWorldToLight.mult(camVerts [i], camVerts [i]);
00500
00501 matSceneToWorld.mult(sceneVerts[i], sceneVerts[i]);
00502 matWorldToLight.mult(sceneVerts[i], sceneVerts[i]);
00503
00504 camVerts [8][0] = osgMin(camVerts [8][0], camVerts [i][0]);
00505 camVerts [9][0] = osgMax(camVerts [9][0], camVerts [i][0]);
00506 camVerts [8][1] = osgMin(camVerts [8][1], camVerts [i][1]);
00507 camVerts [9][1] = osgMax(camVerts [9][1], camVerts [i][1]);
00508
00509 sceneVerts[8][0] = osgMin(sceneVerts[8][0], sceneVerts[i][0]);
00510 sceneVerts[9][0] = osgMax(sceneVerts[9][0], sceneVerts[i][0]);
00511 sceneVerts[8][1] = osgMin(sceneVerts[8][1], sceneVerts[i][1]);
00512 sceneVerts[9][1] = osgMax(sceneVerts[9][1], sceneVerts[i][1]);
00513 sceneVerts[8][2] = osgMin(sceneVerts[8][2], sceneVerts[i][2]);
00514 sceneVerts[9][2] = osgMax(sceneVerts[9][2], sceneVerts[i][2]);
00515 }
00516
00517
00518 Pnt3r lightMin(osgMax(camVerts[8][0], sceneVerts[8][0]),
00519 osgMax(camVerts[8][1], sceneVerts[8][1]),
00520 -sceneVerts[9][2]);
00521
00522 Pnt3r lightMax(osgMin(camVerts[9][0], sceneVerts[9][0]),
00523 osgMin(camVerts[9][1], sceneVerts[9][1]),
00524 -sceneVerts[8][2]);
00525
00526
00527 lightMin[0] -= (lightMax[0] - lightMin[0]) * 0.01f;
00528 lightMin[1] -= (lightMax[1] - lightMin[1]) * 0.01f;
00529 lightMin[2] -= (lightMax[2] - lightMin[2]) * 0.01f;
00530
00531 lightMax[0] += (lightMax[0] - lightMin[0]) * 0.01f;
00532 lightMax[1] += (lightMax[1] - lightMin[1]) * 0.01f;
00533 lightMax[2] += (lightMax[2] - lightMin[2]) * 0.01f;
00534
00535 Matrixr matLightProj;
00536 Matrixr matLightProjTrans;
00537
00538 MatrixOrthogonal(matLightProj,
00539 lightMin[0], lightMax[0],
00540 lightMin[1], lightMax[1],
00541 lightMin[2], lightMax[2] );
00542
00543 updateShadowTexImage (data);
00544 updateShadowTexBuffers(data);
00545 updateRenderTargets (data);
00546
00547 Int32 shadowTexUnit = (this->getForceTextureUnit() > 0) ?
00548 this->getForceTextureUnit() : 7;
00549
00550 ShaderProgram *shadowFP = this->getShadowFragmentProgram();
00551
00552 if(shadowFP == NULL)
00553 {
00554 ShaderProgramUnrecPtr newShadowFP = ShaderProgram::createLocal();
00555 newShadowFP->setShaderType(GL_FRAGMENT_SHADER);
00556 newShadowFP->setProgram (_dirFPCode );
00557
00558 newShadowFP->addUniformVariable("SSME_matEyeToLight", matEyeToLight);
00559 newShadowFP->addUniformVariable("SSME_matLightProj", matLightProj );
00560 newShadowFP->addUniformVariable("SSME_texShadow", shadowTexUnit);
00561
00562 this->setShadowFragmentProgram(newShadowFP);
00563 shadowFP = newShadowFP;
00564 }
00565 else
00566 {
00567 shadowFP->updateUniformVariable("SSME_matEyeToLight", matEyeToLight);
00568 shadowFP->updateUniformVariable("SSME_matLightProj", matLightProj );
00569 }
00570
00571 commitChanges();
00572
00573 ract->pushPartition();
00574 {
00575 RenderPartition *part = ract->getActivePartition( );
00576 Window *win = ract->getWindow ( );
00577 FrameBufferObject *target = data->getRenderTargets (0);
00578 Background *back = data->getBackground ( );
00579
00580 part->setRenderTarget(target);
00581 part->setWindow (win );
00582
00583 part->calcViewportDimension(0.f, 0.f, 1.f, 1.f,
00584 target->getWidth (),
00585 target->getHeight() );
00586
00587 part->setupProjection(matLightProj, matLightProjTrans);
00588 part->setupViewing (matWorldToLight );
00589
00590 part->setNear (parentPart->getNear());
00591 part->setFar (parentPart->getFar ());
00592
00593 part->calcFrustum ( );
00594
00595 part->setBackground (back );
00596
00597
00598 part->overrideMaterial(data->getLightPassMaterials(0),
00599 ract->getActNode ( ) );
00600
00601 this->recurseFrom(ract, dirL);
00602 ract->useNodeList(false );
00603
00604
00605 part->overrideMaterial(NULL,
00606 ract->getActNode ( ) );
00607 }
00608 ract->popPartition();
00609 }
00610
00611 void ShaderShadowMapEngine::handleSpotLightEnter(
00612 SpotLight *spotL, RenderAction *ract, SSMEngineData *data)
00613 {
00614 RenderPartition *parentPart = ract->getActivePartition();
00615
00616
00617 Matrixr matEyeToWorld (parentPart->getCameraToWorld());
00618 Matrixr matWorldToLight;
00619 Matrixr matEyeToLight;
00620
00621 calcSpotLightMatrices(matWorldToLight, matEyeToLight,
00622 spotL, matEyeToWorld );
00623
00624 Real lightNear;
00625 Real lightFar;
00626
00627 calcPointLightRange(spotL, 0.001f,
00628 parentPart->getNear(), parentPart->getFar(),
00629 lightNear, lightFar );
00630
00631 if(getShadowNear() != 0.f)
00632 {
00633 lightNear = getShadowNear();
00634 }
00635
00636 if(getShadowFar() != 0.f)
00637 {
00638 lightFar = getShadowFar();
00639 }
00640
00641 Matrixr matLightProj;
00642 Matrixr matLightProjTrans;
00643
00644 MatrixPerspective(matLightProj,
00645 spotL->getSpotCutOff(), 1.f,
00646 lightNear, lightFar );
00647
00648 updateShadowTexImage (data);
00649 updateShadowTexBuffers(data);
00650 updateRenderTargets (data);
00651
00652 Int32 shadowTexUnit = (this->getForceTextureUnit() > 0) ?
00653 this->getForceTextureUnit() : 7;
00654 ShaderProgram *shadowFP = this->getShadowFragmentProgram();
00655
00656 if(shadowFP == NULL)
00657 {
00658 ShaderProgramUnrecPtr newShadowFP = ShaderProgram::createLocal();
00659 newShadowFP->setShaderType(GL_FRAGMENT_SHADER);
00660 newShadowFP->setProgram (_spotFPCode );
00661
00662 newShadowFP->addUniformVariable("SSME_matEyeToLight", matEyeToLight);
00663 newShadowFP->addUniformVariable("SSME_matLightProj", matLightProj );
00664 newShadowFP->addUniformVariable("SSME_texShadow", shadowTexUnit);
00665
00666 this->setShadowFragmentProgram(newShadowFP);
00667 shadowFP = newShadowFP;
00668 }
00669 else
00670 {
00671 shadowFP->updateUniformVariable("SSME_matEyeToLight", matEyeToLight);
00672 shadowFP->updateUniformVariable("SSME_matLightProj", matLightProj );
00673 }
00674
00675 commitChanges();
00676
00677 ract->pushPartition();
00678 {
00679 RenderPartition *part = ract->getActivePartition( );
00680 Window *win = ract->getWindow ( );
00681 FrameBufferObject *target = data->getRenderTargets (0);
00682 Background *back = data->getBackground ( );
00683
00684 part->setRenderTarget(target);
00685 part->setWindow (win );
00686
00687 part->calcViewportDimension(0.f, 0.f, 1.f, 1.f,
00688 target->getWidth (),
00689 target->getHeight() );
00690
00691 part->setupProjection(matLightProj, matLightProjTrans);
00692 part->setupViewing (matWorldToLight );
00693
00694 part->setNear (parentPart->getNear());
00695 part->setFar (parentPart->getFar ());
00696
00697 part->calcFrustum ( );
00698
00699 part->setBackground (back );
00700
00701
00702 part->overrideMaterial(data->getLightPassMaterials(0),
00703 ract->getActNode ( ) );
00704
00705 this->recurseFrom(ract, spotL);
00706 ract->useNodeList(false );
00707
00708
00709 part->overrideMaterial(NULL,
00710 ract->getActNode ( ) );
00711 }
00712 ract->popPartition();
00713 }
00714
00718 void ShaderShadowMapEngine::calcDirectionalLightMatrices(
00719 Matrixr &matWorldToLight,
00720 Matrixr &matEyeToLight,
00721 const DirectionalLight *dirL,
00722 const Matrixr &matEyeToWorld)
00723 {
00724 if(dirL->getBeacon() != NULL)
00725 dirL->getBeacon()->getToWorld(matWorldToLight);
00726
00727 Quaternion rotLightDir (Vec3r(0.f, 0.f, 1.f), dirL->getDirection());
00728 Matrixr matLightDir;
00729 matLightDir.setRotate(rotLightDir);
00730
00731 matWorldToLight.mult (matLightDir);
00732 matWorldToLight.invert( );
00733
00734 matEyeToLight = matWorldToLight;
00735 matEyeToLight.mult(matEyeToWorld);
00736 }
00737
00738 void ShaderShadowMapEngine::calcPointLightMatrices(
00739 Matrixr &matWorldToLight,
00740 Matrixr &matEyeToLight,
00741 const PointLight *pointL,
00742 const Matrixr &matEyeToWorld)
00743 {
00744 if(pointL->getBeacon() != NULL)
00745 pointL->getBeacon()->getToWorld(matWorldToLight);
00746
00747 Matrixr matLightPos;
00748 matLightPos .setTranslate(pointL->getPosition());
00749 matWorldToLight.mult (matLightPos );
00750 matWorldToLight.invert ( );
00751
00752 matEyeToLight = matWorldToLight;
00753 matEyeToLight.mult(matEyeToWorld);
00754 }
00755
00759 void ShaderShadowMapEngine::calcSpotLightMatrices(
00760 Matrixr &matWorldToLight,
00761 Matrixr &matEyeToLight,
00762 const SpotLight *spotL,
00763 const Matrixr &matEyeToWorld)
00764 {
00765 if(spotL->getBeacon() != NULL)
00766 spotL->getBeacon()->getToWorld(matWorldToLight);
00767
00768 Matrixr matLightPos;
00769 matLightPos.setTranslate(spotL->getPosition());
00770
00771 Matrixr matLightDir;
00772 Quaternion rotLightDir(Vec3r(0.f, 0.f, 1.f), -spotL->getDirection());
00773 matLightDir.setRotate(rotLightDir);
00774
00775 matWorldToLight.mult (matLightPos);
00776 matWorldToLight.mult (matLightDir);
00777 matWorldToLight.invert( );
00778
00779 matEyeToLight = matWorldToLight;
00780 matEyeToLight.mult(matEyeToWorld);
00781 }
00782
00783 void ShaderShadowMapEngine::calcPointLightRange(
00784 const PointLight *pointL, Real lightThreshold,
00785 Real defaultNear, Real defaultFar,
00786 Real &outNear, Real &outFar )
00787 {
00788 outNear = defaultNear;
00789 outFar = defaultFar;
00790
00791 Real kQ = pointL->getQuadraticAttenuation();
00792 Real kL = pointL->getLinearAttenuation ();
00793 Real kC = pointL->getConstantAttenuation ();
00794
00795 if(osgAbs(kQ) > Eps)
00796 {
00797 Real det = kL * kL - 4.f * kQ * (kC - 1.f / lightThreshold);
00798
00799 if(det >= 0)
00800 {
00801 det = osgSqrt(det);
00802 Real r1 = - kL + det / (2.f * kQ);
00803 Real r2 = - kL - det / (2.f * kQ);
00804
00805 if(r1 > 0.f && r2 > 0.f)
00806 {
00807 outFar = osgMin(r1, r2);
00808 }
00809 else if(r1 > 0.f)
00810 {
00811 outFar = r1;
00812 }
00813 else if(r2 > 0.f)
00814 {
00815 outFar = r2;
00816 }
00817 }
00818 }
00819 else if(osgAbs(kL) > Eps)
00820 {
00821 Real r = (1.f / lightThreshold - kC) / kL;
00822
00823 if(r > 0.f)
00824 {
00825 outFar = r;
00826 }
00827 }
00828 }
00829
00830 void ShaderShadowMapEngine::updateShadowTexChunk(SSMEngineData *data)
00831 {
00832 TextureObjChunk *bufTex = data->getShadowTexChunk();
00833
00834 if(bufTex == NULL)
00835 {
00836 TextureObjChunkUnrecPtr newBufTex = TextureObjChunk::createLocal();
00837 newBufTex->setMinFilter (GL_LINEAR );
00838 newBufTex->setMagFilter (GL_LINEAR );
00839 newBufTex->setWrapS (GL_CLAMP_TO_EDGE );
00840 newBufTex->setWrapT (GL_CLAMP_TO_EDGE );
00841 newBufTex->setWrapR (GL_CLAMP_TO_EDGE );
00842 newBufTex->setScale (false );
00843 newBufTex->setInternalFormat(GL_DEPTH_COMPONENT24 );
00844 newBufTex->setExternalFormat(GL_DEPTH_COMPONENT );
00845 newBufTex->setCompareMode (GL_COMPARE_R_TO_TEXTURE);
00846 newBufTex->setCompareFunc (GL_LESS );
00847 newBufTex->setDepthMode (GL_LUMINANCE );
00848
00849 data->setShadowTexChunk(newBufTex);
00850 this->setShadowTexChunk(newBufTex);
00851 }
00852 }
00853
00854 void ShaderShadowMapEngine::updateLightPassMaterial(SSMEngineData *data)
00855 {
00856 if(data->getMFLightPassMaterials()->empty() == true)
00857 {
00858 MaterialChunkUnrecPtr newMatChunk = MaterialChunk::createLocal();
00859 newMatChunk->setLit (false );
00860 newMatChunk->setColorMaterial(GL_NONE);
00861
00862 ColorMaskChunkUnrecPtr newCMaskChunk = ColorMaskChunk::create();
00863 newCMaskChunk->setMaskR(false);
00864 newCMaskChunk->setMaskG(false);
00865 newCMaskChunk->setMaskB(false);
00866 newCMaskChunk->setMaskA(false);
00867
00868 PolygonChunkUnrecPtr newPolyChunk = PolygonChunk::createLocal();
00869 newPolyChunk->setOffsetFill (true );
00870 newPolyChunk->setOffsetFactor(this->getOffsetFactor());
00871 newPolyChunk->setOffsetBias (this->getOffsetBias ());
00872
00873 ChunkMaterialUnrecPtr newLightPassMat = ChunkMaterial::createLocal();
00874 newLightPassMat->addChunk(newMatChunk );
00875 newLightPassMat->addChunk(newCMaskChunk);
00876 newLightPassMat->addChunk(newPolyChunk );
00877
00878 data->editMFLightPassMaterials()->push_back(newLightPassMat);
00879 }
00880 }
00881
00882 void ShaderShadowMapEngine::updateBackground(SSMEngineData *data)
00883 {
00884 Background *back = data->getBackground();
00885
00886 if(back == NULL)
00887 {
00888 SolidBackgroundUnrecPtr newBack = SolidBackground::createLocal();
00889 newBack->setClearColor(false);
00890
00891 data->setBackground(newBack);
00892 }
00893 }
00894
00895 void ShaderShadowMapEngine::updatePointLightShadowTexImage(SSMEngineData *data)
00896 {
00897 Image *bufImg = data->getShadowTexImage();
00898 TextureObjChunk *bufTex = data->getShadowTexChunk();
00899
00900 FASSERT((bufTex != NULL), false)
00901
00902 if(bufImg == NULL)
00903 {
00904 ImageUnrecPtr newBufImg = Image::createLocal();
00905 newBufImg->set(Image::OSG_L_PF,
00906 this->getWidth (),
00907 this->getHeight(),
00908 1,
00909 1,
00910 1,
00911 0.,
00912 NULL,
00913 Image::OSG_UINT8_IMAGEDATA,
00914 false,
00915 6);
00916
00917 bufTex->setImage (newBufImg);
00918 data ->setShadowTexImage(newBufImg);
00919
00920 bufImg = newBufImg;
00921 }
00922
00923 if((bufImg->getWidth () != this->getWidth ()) ||
00924 (bufImg->getHeight() != this->getHeight()) )
00925 {
00926 bufImg->setWidth (this->getWidth ());
00927 bufImg->setHeight(this->getHeight());
00928 }
00929 }
00930
00931 void ShaderShadowMapEngine::updateShadowTexImage(SSMEngineData *data)
00932 {
00933 Image *bufImg = data->getShadowTexImage();
00934 TextureObjChunk *bufTex = data->getShadowTexChunk();
00935
00936 FASSERT((bufTex != NULL), false)
00937
00938 if(bufImg == NULL)
00939 {
00940 ImageUnrecPtr newBufImg = Image::createLocal();
00941 newBufImg->set(Image::OSG_L_PF,
00942 this->getWidth (),
00943 this->getHeight(),
00944 1,
00945 1,
00946 1,
00947 0.,
00948 NULL,
00949 Image::OSG_UINT8_IMAGEDATA,
00950 false,
00951 1);
00952
00953 bufTex->setImage (newBufImg);
00954 data ->setShadowTexImage(newBufImg);
00955
00956 bufImg = newBufImg;
00957 }
00958
00959 if((bufImg->getWidth () != this->getWidth ()) ||
00960 (bufImg->getHeight() != this->getHeight()) )
00961 {
00962 bufImg->setWidth (this->getWidth ());
00963 bufImg->setHeight(this->getHeight());
00964 }
00965 }
00966
00967 void ShaderShadowMapEngine::updatePointLightShadowTexBuffers(
00968 SSMEngineData *data)
00969 {
00970 TextureObjChunk *bufTex = data->getShadowTexChunk();
00971
00972 if(data->getMFShadowTexBuffers()->empty() == true)
00973 {
00974 for(UInt16 i = 0; i < 6; ++i)
00975 {
00976 TextureBufferUnrecPtr newBuf = TextureBuffer::createLocal();
00977 newBuf->setTexture (bufTex );
00978 newBuf->setTexTarget(_cubeFaceTargets[i]);
00979
00980 data->editMFShadowTexBuffers()->push_back(newBuf);
00981 }
00982 }
00983 }
00984
00985 void ShaderShadowMapEngine::updateShadowTexBuffers(SSMEngineData *data)
00986 {
00987 TextureObjChunk *bufTex = data->getShadowTexChunk();
00988
00989 if(data->getMFShadowTexBuffers()->empty() == true)
00990 {
00991 TextureBufferUnrecPtr newBuf = TextureBuffer::createLocal();
00992 newBuf->setTexture (bufTex );
00993 newBuf->setTexTarget(GL_TEXTURE_2D);
00994
00995 data->editMFShadowTexBuffers()->push_back(newBuf);
00996 }
00997 }
00998
00999 void ShaderShadowMapEngine::updatePointLightRenderTargets(SSMEngineData *data)
01000 {
01001 if(data->getMFRenderTargets()->empty() == true)
01002 {
01003 for(UInt16 i = 0; i < 6; ++i)
01004 {
01005 FrameBufferObjectUnrecPtr newTarget =
01006 FrameBufferObject::createLocal();
01007 newTarget->setWidth (this->getWidth ( ));
01008 newTarget->setHeight (this->getHeight ( ));
01009 newTarget->setDepthAttachment(data->getShadowTexBuffers(i));
01010
01011 data->editMFRenderTargets()->push_back(newTarget);
01012 }
01013 }
01014 else
01015 {
01016 for(UInt16 i = 0; i < 6; ++i)
01017 {
01018 FrameBufferObject *target = data->getRenderTargets(i);
01019
01020 if((target->getWidth () != this->getWidth ()) ||
01021 (target->getHeight() != this->getHeight()) )
01022 {
01023 target->setWidth (this->getWidth ());
01024 target->setHeight(this->getHeight());
01025 }
01026 }
01027 }
01028 }
01029
01030 void ShaderShadowMapEngine::updateRenderTargets(SSMEngineData *data)
01031 {
01032 if(data->getMFRenderTargets()->empty() == true)
01033 {
01034 FrameBufferObjectUnrecPtr newTarget =
01035 FrameBufferObject::createLocal();
01036 newTarget->setWidth (this->getWidth ( ));
01037 newTarget->setHeight (this->getHeight ( ));
01038 newTarget->setDepthAttachment(data->getShadowTexBuffers(0));
01039
01040 data->editMFRenderTargets()->push_back(newTarget);
01041 }
01042 else
01043 {
01044 FrameBufferObject *target = data->getRenderTargets(0);
01045
01046 if((target->getWidth () != this->getWidth ()) ||
01047 (target->getHeight() != this->getHeight()) )
01048 {
01049 target->setWidth (this->getWidth ());
01050 target->setHeight(this->getHeight());
01051 }
01052 }
01053 }
01054
01055 OSG_END_NAMESPACE