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 "OSGConfig.h"
00044
00045 #include "OSGTrapezoidalShadowMapEngine.h"
00046
00047 #include "OSGLine.h"
00048 #include "OSGMaterialChunk.h"
00049 #include "OSGMathMFields.h"
00050 #include "OSGMatrixUtility.h"
00051 #include "OSGColorMaskChunk.h"
00052 #include "OSGPolygonChunk.h"
00053
00054 #include <boost/cast.hpp>
00055
00056 #define OSG_TSME_LIGHTPASS_EXACT 1
00057
00058 OSG_BEGIN_NAMESPACE
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069 #ifdef OSG_TSME_LIGHTPASS_EXACT
00070
00071 const std::string TrapezoidalShadowMapEngine::_lightPassVPCode(
00072 "#version 120\n"
00073 "\n"
00074 "uniform mat4 TSME_matNT;\n"
00075 "\n"
00076 "varying vec4 TSME_plcPos;\n"
00077 "\n"
00078 "void main(void)\n"
00079 "{\n"
00080 " TSME_plcPos = ftransform();\n"
00081 " gl_Position = TSME_matNT * TSME_plcPos;\n"
00082 "}\n"
00083 );
00084
00085 const std::string TrapezoidalShadowMapEngine::_lightPassFPCode(
00086 "#version 120\n"
00087 "\n"
00088 "const float TSME_depthEps = 1e-7;\n"
00089 "\n"
00090 "uniform float TSME_offsetFactor;\n"
00091 "uniform float TSME_offsetBias;\n"
00092 "\n"
00093 "varying vec4 TSME_plcPos;\n"
00094 "\n"
00095 "void main(void)\n"
00096 "{\n"
00097 " float depth = 0.5 + 0.5 * (TSME_plcPos.z / TSME_plcPos.w);\n"
00098 " float depthSlope = max(abs(dFdx(depth)),\n"
00099 " abs(dFdy(depth)) );\n"
00100 " gl_FragDepth = depth + TSME_offsetFactor * depthSlope\n"
00101 " + TSME_offsetBias * TSME_depthEps;\n"
00102 "}\n"
00103 );
00104
00105 #else
00106
00107 const std::string TrapezoidalShadowMapEngine::_lightPassVPCode(
00108 "#version 120\n"
00109 "\n"
00110 "uniform mat4 TSME_matNT;\n"
00111 "\n"
00112 "void main(void)\n"
00113 "{\n"
00114 " vec4 plcPos = ftransform();\n"
00115 " vec4 tcPos = TSME_matNT * plcPos;\n"
00116 " gl_Position = vec4(tcPos.xy, (plcPos.z / plcPos.w) * tcPos.w, tcPos.w);\n"
00117 "}\n"
00118 );
00119
00120 const std::string TrapezoidalShadowMapEngine::_lightPassFPCode("");
00121
00122 #endif // OSG_TSME_LIGHTPASS_EXACT
00123
00124 const std::string TrapezoidalShadowMapEngine::_pointFPCode(
00125 "#version 120\n"
00126 "\n"
00127 "#define TSME_PCF 1\n"
00128 "\n"
00129 "#extension GL_EXT_gpu_shader4 : require\n"
00130 "#extension GL_EXT_gpu_shader4 : enable\n"
00131 "\n"
00132 "uniform samplerCubeShadow TSME_texShadow;\n"
00133 "uniform vec2 TSME_texShadowSizeInv;\n"
00134 "\n"
00135 "uniform mat4 TSME_matEyeToLight;\n"
00136 "uniform mat4 TSME_matLightProj;\n"
00137 "uniform mat4 TSME_matNT[6];\n"
00138 "\n"
00139 "vec2 TSME_offsetFactors[16] = vec2[](\n"
00140 " vec2(-1.5, -1.5),\n"
00141 " vec2( 1.5, -1.5),\n"
00142 " vec2(-1.5, 1.5),\n"
00143 " vec2( 1.5, 1.5),\n"
00144 "\n"
00145 " vec2(-0.5, 1.5),\n"
00146 " vec2( 0.5, 1.5),\n"
00147 " vec2(-1.0, 1.0),\n"
00148 " vec2( 1.0, 1.0),\n"
00149 " vec2(-1.5, 0.5),\n"
00150 " vec2( 1.5, 0.5),\n"
00151 "\n"
00152 " vec2(-1.5, -0.5),\n"
00153 " vec2( 1.5, -0.5),\n"
00154 " vec2(-1.0, -1.0),\n"
00155 " vec2( 1.0, -1.0),\n"
00156 " vec2(-0.5, -1.5),\n"
00157 " vec2( 0.5, -1.5) \n"
00158 " );\n"
00159 "\n"
00160 "vec4 OSG_SSME_FP_calcShadow(in vec4 fragPos)\n"
00161 "{\n"
00162 " vec4 shadow = vec4(0., 0., 0., 0.);\n"
00163 " vec4 lcPos = TSME_matEyeToLight * fragPos;\n"
00164 " vec4 lcAbsPos = abs(lcPos);\n"
00165 " vec4 plcPos;\n"
00166 " vec4 tcPos;\n"
00167 " vec4 pcfOffset0;\n"
00168 " vec4 pcfOffset1;\n"
00169 "\n"
00170 " if(lcAbsPos.x > lcAbsPos.y && lcAbsPos.x > lcAbsPos.z)\n"
00171 " {\n"
00172 " pcfOffset0 = vec4(0., 0., TSME_texShadowSizeInv.x, 0.);\n"
00173 " pcfOffset1 = vec4(0., TSME_texShadowSizeInv.y, 0. , 0.);\n"
00174 "\n"
00175 " if(lcPos.x >= 0.)\n"
00176 " {\n"
00177 " plcPos = vec4(-1, -1, -1, 1) * lcPos.zyxw;\n"
00178 " plcPos = TSME_matLightProj * plcPos;\n"
00179 " tcPos = TSME_matNT[4] * plcPos;\n"
00180 " tcPos = tcPos / tcPos.w;\n"
00181 " tcPos = vec4(-1, -1, -1, 1) * tcPos.zyxw;\n"
00182 " tcPos.x = 1.;\n"
00183 " }\n"
00184 " else\n"
00185 " {\n"
00186 " plcPos = vec4( 1, -1, 1, 1) * lcPos.zyxw;\n"
00187 " plcPos = TSME_matLightProj * plcPos;\n"
00188 " tcPos = TSME_matNT[5] * plcPos;\n"
00189 " tcPos = tcPos / tcPos.w;\n"
00190 " tcPos = vec4( 1, -1, 1, 1) * tcPos.zyxw;\n"
00191 " tcPos.x = -1.;\n"
00192 " }\n"
00193 " }\n"
00194 " else if(lcAbsPos.y > lcAbsPos.x && lcAbsPos.y > lcAbsPos.z)\n"
00195 " {\n"
00196 " pcfOffset0 = vec4(TSME_texShadowSizeInv.x, 0., 0., 0.);\n"
00197 " pcfOffset1 = vec4(0., 0., TSME_texShadowSizeInv.y, 0.);\n"
00198 "\n"
00199 " if(lcPos.y >= 0.)\n"
00200 " {\n"
00201 " plcPos = vec4( 1, 1, -1, 1) * lcPos.xzyw;\n"
00202 " plcPos = TSME_matLightProj * plcPos;\n"
00203 " tcPos = TSME_matNT[2] * plcPos;\n"
00204 " tcPos = tcPos / tcPos.w;\n"
00205 " tcPos = vec4( 1, -1, 1, 1) * tcPos.xzyw;\n"
00206 " tcPos.y = 1.;\n"
00207 " }\n"
00208 " else\n"
00209 " {\n"
00210 " plcPos = vec4( 1, -1, 1, 1) * lcPos.xzyw;\n"
00211 " plcPos = TSME_matLightProj * plcPos;\n"
00212 " tcPos = TSME_matNT[3] * plcPos;\n"
00213 " tcPos = tcPos / tcPos.w;\n"
00214 " tcPos = vec4( 1, 1, -1, 1) * tcPos.xzyw;\n"
00215 " tcPos.y = -1.;\n"
00216 " }\n"
00217 " }\n"
00218 " else\n"
00219 " {\n"
00220 " pcfOffset0 = vec4(TSME_texShadowSizeInv.x, 0., 0., 0.);\n"
00221 " pcfOffset1 = vec4(0., TSME_texShadowSizeInv.y, 0., 0.);\n"
00222 "\n"
00223 " if(lcPos.z >= 0.)\n"
00224 " {\n"
00225 " plcPos = vec4( 1, -1, -1, 1) * lcPos;\n"
00226 " plcPos = TSME_matLightProj * plcPos;\n"
00227 " tcPos = TSME_matNT[0] * plcPos;\n"
00228 " tcPos = tcPos / tcPos.w;\n"
00229 " tcPos = vec4( 1, -1, -1, 1) * tcPos;\n"
00230 " tcPos.z = 1.;\n"
00231 " }\n"
00232 " else\n"
00233 " {\n"
00234 " plcPos = vec4(-1, -1, 1, 1) * lcPos;\n"
00235 " plcPos = TSME_matLightProj * plcPos;\n"
00236 " tcPos = TSME_matNT[1] * plcPos;\n"
00237 " tcPos = tcPos / tcPos.w;\n"
00238 " tcPos = vec4(-1, -1, 1, 1) * tcPos;\n"
00239 " tcPos.z = -1.;\n"
00240 " }\n"
00241 " }\n"
00242 "\n"
00243 " plcPos = plcPos / plcPos.w;\n"
00244 " plcPos = 0.5 + 0.5 * plcPos;\n"
00245 "\n"
00246 "#ifndef TSME_PCF\n"
00247 " shadow = shadowCube(TSME_texShadow, vec4(tcPos.xyz, plcPos.z));\n"
00248 "#else\n"
00249 " vec4 lookupBase = vec4(tcPos.xyz, plcPos.z);\n"
00250 " vec4 lookup;\n"
00251 "\n"
00252 " for(int i = 0; i < 4; ++i)\n"
00253 " {\n"
00254 " lookup = TSME_offsetFactors[i].x * pcfOffset0 +\n"
00255 " TSME_offsetFactors[i].y * pcfOffset1 + lookupBase;\n"
00256 " shadow += shadowCube(TSME_texShadow, lookup);\n"
00257 " }\n"
00258 "\n"
00259 " if((shadow.x - 4.0) * shadow.x == 0.0)\n"
00260 " {\n"
00261 " shadow *= 0.25;\n"
00262 " }\n"
00263 " else\n"
00264 " {\n"
00265 " for(int i = 4; i < 16; ++i)\n"
00266 " {\n"
00267 " lookup = TSME_offsetFactors[i].x * pcfOffset0 +\n"
00268 " TSME_offsetFactors[i].y * pcfOffset1 + lookupBase;\n"
00269 " shadow += shadowCube(TSME_texShadow, lookup);\n"
00270 " }\n"
00271 "\n"
00272 " shadow *= 1.0 / 16.0;\n"
00273 " }\n"
00274 "#endif // TSME_PCF\n"
00275 "\n"
00276 " return shadow;\n"
00277 "}\n"
00278 );
00279
00280 const std::string TrapezoidalShadowMapEngine::_spotFPCode(
00281 "#version 120\n"
00282 "\n"
00283 "#define TSME_PCF 1\n"
00284 "\n"
00285 "uniform sampler2DShadow TSME_texShadow;\n"
00286 "uniform vec2 TSME_texShadowSizeInv;\n"
00287 "\n"
00288 "uniform mat4 TSME_matEyeToLight;\n"
00289 "uniform mat4 TSME_matLightProj;\n"
00290 "uniform mat4 TSME_matNT;\n"
00291 "\n"
00292 "vec2 TSME_offsetFactors[16] = vec2[](\n"
00293 " vec2(-1.5, -1.5),\n"
00294 " vec2( 1.5, -1.5),\n"
00295 " vec2(-1.5, 1.5),\n"
00296 " vec2( 1.5, 1.5),\n"
00297 "\n"
00298 " vec2(-0.5, 1.5),\n"
00299 " vec2( 0.5, 1.5),\n"
00300 " vec2(-1.0, 1.0),\n"
00301 " vec2( 1.0, 1.0),\n"
00302 " vec2(-1.5, 0.5),\n"
00303 " vec2( 1.5, 0.5),\n"
00304 "\n"
00305 " vec2(-1.5, -0.5),\n"
00306 " vec2( 1.5, -0.5),\n"
00307 " vec2(-1.0, -1.0),\n"
00308 " vec2( 1.0, -1.0),\n"
00309 " vec2(-0.5, -1.5),\n"
00310 " vec2( 0.5, -1.5) \n"
00311 " );\n"
00312 "\n"
00313 "vec4 OSG_SSME_FP_calcShadow(in vec4 ecFragPos)\n"
00314 "{\n"
00315 " vec4 shadow = vec4(0., 0., 0., 0.);\n"
00316 " vec4 plcPos = TSME_matLightProj * TSME_matEyeToLight * ecFragPos;\n"
00317 " vec4 tcPos = TSME_matNT * plcPos;\n"
00318 "\n"
00319 " plcPos = plcPos / plcPos.w;\n"
00320 " plcPos = 0.5 + 0.5 * plcPos;\n"
00321 " tcPos = tcPos / tcPos.w;\n"
00322 " tcPos = 0.5 + 0.5 * tcPos;\n"
00323 "\n"
00324 " vec3 lookupBase = vec3(tcPos.xy, plcPos.z);\n"
00325 " vec3 lookup;\n"
00326 "\n"
00327 "#ifndef TSME_PCF\n"
00328 " shadow = shadow2D(TSME_texShadow, lookupBase);\n"
00329 "#else\n"
00330 " for(int i = 0; i < 4; ++i)\n"
00331 " {\n"
00332 " lookup = vec3(TSME_offsetFactors[i].x * TSME_texShadowSizeInv.x,\n"
00333 " TSME_offsetFactors[i].y * TSME_texShadowSizeInv.y,\n"
00334 " 0.0) + lookupBase;\n"
00335 " shadow += shadow2D(TSME_texShadow, lookup);\n"
00336 " }\n"
00337 "\n"
00338 " if((shadow.x - 4.) * shadow.x == 0)\n"
00339 " {\n"
00340 " shadow *= 0.25;\n"
00341 " }\n"
00342 " else\n"
00343 " {\n"
00344 " for(int i = 4; i < 16; ++i)\n"
00345 " {\n"
00346 " lookup = vec3(TSME_offsetFactors[i].x * TSME_texShadowSizeInv.x,\n"
00347 " TSME_offsetFactors[i].y * TSME_texShadowSizeInv.y,\n"
00348 " 0.0) + lookupBase;\n"
00349 " shadow += shadow2D(TSME_texShadow, lookup);\n"
00350 " }\n"
00351 "\n"
00352 " shadow *= 1.0 / 16.0;\n"
00353 " }\n"
00354 "#endif\n"
00355 "\n"
00356 " return shadow;\n"
00357 "}\n"
00358 );
00359
00360
00361
00362
00363
00364 void TrapezoidalShadowMapEngine::initMethod(InitPhase ePhase)
00365 {
00366 Inherited::initMethod(ePhase);
00367 }
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380 TrapezoidalShadowMapEngine::TrapezoidalShadowMapEngine(void) :
00381 Inherited()
00382 {
00383 }
00384
00385 TrapezoidalShadowMapEngine::TrapezoidalShadowMapEngine(const TrapezoidalShadowMapEngine &source) :
00386 Inherited(source)
00387 {
00388 }
00389
00390 TrapezoidalShadowMapEngine::~TrapezoidalShadowMapEngine(void)
00391 {
00392 }
00393
00394
00395
00396 ActionBase::ResultE TrapezoidalShadowMapEngine::runOnEnter(
00397 Light *light, LightTypeE eType, RenderAction *ract)
00398 {
00399 BitVector passMask = ract->getPassMask ( );
00400 TSMEngineData *data = ract->getData<TSMEngineData *>(_iDataSlotId);
00401
00402 if(data == NULL)
00403 {
00404 TSMEngineDataUnrecPtr newData = TSMEngineData::createLocal();
00405 this->setData(newData, _iDataSlotId, ract);
00406
00407 data = newData;
00408 }
00409
00410 if(passMask != 0x0000)
00411 {
00412
00413 if((passMask & bvLightPassMask) != 0x0000)
00414 {
00415 this->recurseFrom(ract, light);
00416
00417 handleEnter(light, eType, ract, data);
00418 }
00419 }
00420 else
00421 {
00422 ract->addPassMask(bvLightPassMask);
00423 handleEnter(light, eType, ract, data);
00424 ract->subPassMask(bvLightPassMask);
00425 }
00426
00427 return Action::Continue;
00428 }
00429
00430 ActionBase::ResultE TrapezoidalShadowMapEngine::runOnLeave(
00431 Light *light, LightTypeE eType, RenderAction *ract)
00432 {
00433 return Action::Continue;
00434 }
00435
00436 void TrapezoidalShadowMapEngine::changed(ConstFieldMaskArg whichField,
00437 UInt32 origin,
00438 BitVector details)
00439 {
00440 Inherited::changed(whichField, origin, details);
00441 }
00442
00443 void TrapezoidalShadowMapEngine::dump( UInt32 ,
00444 const BitVector ) const
00445 {
00446 SLOG << "Dump TrapezoidalShadowMapEngine NI" << std::endl;
00447 }
00448
00449 void TrapezoidalShadowMapEngine::handleEnter(
00450 Light *light, LightTypeE eType, RenderAction *ract, TSMEngineData *data)
00451 {
00452 Inherited::updateShadowTexChunk (data);
00453 Inherited::updateBackground (data);
00454
00455 UInt32 parentTravMask = ract->getTravMask();
00456 ract->setTravMask(_sfShadowTravMask.getValue());
00457
00458 switch(eType)
00459 {
00460 case Point:
00461 {
00462 PointLight *pointL =
00463 boost::polymorphic_downcast<PointLight *>(light);
00464
00465 handlePointLightEnter(pointL, ract, data);
00466 }
00467 break;
00468
00469 case Directional:
00470 {
00471 DirectionalLight *dirL =
00472 boost::polymorphic_downcast<DirectionalLight *>(light);
00473
00474 handleDirectionalLightEnter(dirL, ract, data);
00475 }
00476 break;
00477
00478 case Spot:
00479 {
00480 SpotLight *spotL =
00481 boost::polymorphic_downcast<SpotLight *>(light);
00482
00483 handleSpotLightEnter(spotL, ract, data);
00484 }
00485 break;
00486
00487 default:
00488 {
00489 FWARNING(("TrapezoidalShadowMapEngine::handleEnter: Unknown "
00490 "light type [%u]\n", eType));
00491 }
00492 break;
00493 }
00494
00495 ract->setTravMask(parentTravMask);
00496 }
00497
00498 void TrapezoidalShadowMapEngine::handlePointLightEnter(
00499 PointLight *pointL, RenderAction *ract, TSMEngineData *data)
00500 {
00501 RenderPartition *parentPart = ract->getActivePartition();
00502
00503 Matrixr matEyeToWorld(parentPart->getCameraToWorld());
00504 Matrixr matLightProj;
00505
00506 Real shadowNear = (getShadowNear() != 0.f ?
00507 getShadowNear() :
00508 parentPart->getNear() );
00509 Real shadowFar = (getShadowFar () != 0.f ?
00510 getShadowFar () :
00511 parentPart->getFar() );
00512
00513 Inherited::calcPointLightRange(
00514 pointL, 0.01f,
00515 shadowNear, shadowFar, shadowNear, shadowFar);
00516
00517 MatrixPerspective(matLightProj, Pi / 4.f, 1.f,
00518 shadowNear, shadowFar );
00519
00520 Matrixr matWorldToLight;
00521 Matrixr matEyeToLight;
00522 MFMatrixr mfMatNT;
00523
00524 mfMatNT.resize(6);
00525
00526 Inherited::calcPointLightMatrices(matWorldToLight, matEyeToLight,
00527 pointL, matEyeToWorld );
00528
00529 Inherited::updatePointLightShadowTexImage (data);
00530 Inherited::updatePointLightShadowTexBuffers(data);
00531 Inherited::updatePointLightRenderTargets (data);
00532
00533 Int32 shadowTexUnit = (this->getForceTextureUnit() >= 0) ?
00534 this->getForceTextureUnit() : 7;
00535 ShaderProgram *shadowFP = this->getShadowFragmentProgram();
00536
00537 if(shadowFP == NULL)
00538 {
00539 ShaderProgramUnrecPtr newShadowFP = ShaderProgram::createLocal();
00540 newShadowFP->setShaderType(GL_FRAGMENT_SHADER);
00541 newShadowFP->setProgram (_pointFPCode );
00542
00543 newShadowFP->addUniformVariable("TSME_matEyeToLight", matEyeToLight);
00544 newShadowFP->addUniformVariable("TSME_matLightProj", matLightProj );
00545 newShadowFP->addUniformVariable("TSME_matNT", mfMatNT );
00546 newShadowFP->addUniformVariable("TSME_texShadow", shadowTexUnit);
00547 newShadowFP->addUniformVariable("TSME_texShadowSizeInv",
00548 Vec2f(1.f / getWidth (),
00549 1.f / getHeight() ) );
00550
00551 this->setShadowFragmentProgram(newShadowFP);
00552 shadowFP = newShadowFP;
00553 }
00554 else
00555 {
00556 shadowFP->updateUniformVariable("TSME_matEyeToLight", matEyeToLight);
00557 shadowFP->updateUniformVariable("TSME_matLightProj", matLightProj );
00558 }
00559
00560 const FrustumVolume &eyeFrust = parentPart->getFrustum();
00561
00562 for(UInt16 faceIdx = 0; faceIdx < 6; ++faceIdx)
00563 {
00564 Matrixr matWorldToLightFace (matWorldToLight );
00565 matWorldToLightFace.multLeft(_matCubeFaceInv[faceIdx]);
00566
00567 Matrixr matLightFull(matWorldToLightFace);
00568 matLightFull.multLeft(matLightProj);
00569
00570 FrustumVolume lightFrust;
00571 Matrixr matNT;
00572
00573 lightFrust.setPlanes(matLightFull);
00574
00575 bool matNTValid =
00576 calcTrapezoidalTransform(mfMatNT[faceIdx],
00577 matEyeToWorld, matLightFull,
00578 eyeFrust, lightFrust );
00579
00580 if(matNTValid == false)
00581 {
00582
00583
00584 commitChanges();
00585
00586 ract->pushPartition(RenderPartition::CopyNothing,
00587 RenderPartition::SimpleCallback);
00588 {
00589 RenderPartition *part = ract->getActivePartition( );
00590 Window *win = ract->getWindow ( );
00591 FrameBufferObject *target = data->getRenderTargets (faceIdx);
00592 Background *back = data->getBackground ( );
00593
00594 part->setSetupMode(RenderPartition::ViewportSetup |
00595 RenderPartition::BackgroundSetup );
00596
00597 part->setRenderTarget(target);
00598 part->setWindow (win );
00599
00600 part->calcViewportDimension(0.f, 0.f, 1.f, 1.f,
00601 target->getWidth (),
00602 target->getHeight() );
00603
00604 part->setBackground(back);
00605
00606 RenderPartition::SimpleDrawCallback emptyCubeFaceDraw =
00607 boost::bind(
00608 &TrapezoidalShadowMapEngine::emptyCubeFaceDrawFunc,
00609 this, _1);
00610
00611 part->dropFunctor(emptyCubeFaceDraw);
00612 }
00613 ract->popPartition();
00614 }
00615 else
00616 {
00617 updateLightPassMaterial(data, faceIdx, mfMatNT[faceIdx]);
00618
00619 commitChanges();
00620
00621 ract->pushPartition();
00622 {
00623 RenderPartition *part = ract->getActivePartition( );
00624 Window *win = ract->getWindow ( );
00625 FrameBufferObject *target = data->getRenderTargets (faceIdx);
00626 Background *back = data->getBackground ( );
00627
00628 part->setRenderTarget(target);
00629 part->setWindow (win );
00630
00631 part->calcViewportDimension(0.f, 0.f, 1.f, 1.f,
00632 target->getWidth (),
00633 target->getHeight() );
00634
00635 part->setupProjection(matLightProj, Matrixr::identity());
00636 part->setupViewing (matWorldToLightFace );
00637
00638 part->setNear (parentPart->getNear());
00639 part->setFar (parentPart->getFar ());
00640
00641 part->setFrustum (lightFrust );
00642
00643 part->setBackground (back );
00644
00645 part->overrideMaterial(data->getLightPassMaterials(faceIdx),
00646 ract->getActNode ( ) );
00647
00648 this->recurseFrom(ract, pointL);
00649 ract->useNodeList(false );
00650
00651 part->overrideMaterial(NULL,
00652 ract->getActNode ( ) );
00653 }
00654 ract->popPartition();
00655 }
00656 }
00657
00658 shadowFP->updateUniformVariable("TSME_matNT", mfMatNT);
00659 }
00660
00661 void TrapezoidalShadowMapEngine::handleDirectionalLightEnter(
00662 DirectionalLight *dirL, RenderAction *ract, TSMEngineData *data)
00663 {
00664 FWARNING(("TrapezoidalShadowMapEngine::handleDirectionalLightEnter: NIY\n"));
00665 }
00666
00667 void TrapezoidalShadowMapEngine::handleSpotLightEnter(
00668 SpotLight *spotL, RenderAction *ract, TSMEngineData *data)
00669 {
00670 RenderPartition *parentPart = ract->getActivePartition();
00671
00672 Matrixr matEyeToWorld(parentPart->getCameraToWorld());
00673 Matrixr matWorldToLight;
00674 Matrixr matEyeToLight;
00675
00676 Inherited::calcSpotLightMatrices(matWorldToLight, matEyeToLight,
00677 spotL, matEyeToWorld );
00678
00679 Matrixr matLightProj;
00680 Matrixr matLightFull(matWorldToLight);
00681
00682 Real shadowNear = (getShadowNear() != 0.f ?
00683 getShadowNear() :
00684 parentPart->getNear() );
00685 Real shadowFar = (getShadowFar () != 0.f ?
00686 getShadowFar () :
00687 parentPart->getFar() );
00688
00689 Inherited::calcPointLightRange(
00690 spotL, 0.01f,
00691 shadowNear, shadowFar, shadowNear, shadowFar);
00692
00693 MatrixPerspective(matLightProj,
00694 spotL->getSpotCutOff(), 1.f,
00695 shadowNear, shadowFar );
00696
00697 matLightFull.multLeft(matLightProj);
00698
00699 Inherited::updateShadowTexImage (data);
00700 Inherited::updateShadowTexBuffers(data);
00701 Inherited::updateRenderTargets (data);
00702
00703 const FrustumVolume &eyeFrust = parentPart->getFrustum();
00704 FrustumVolume lightFrust;
00705 Matrixr matNT;
00706
00707 lightFrust.setPlanes(matLightFull);
00708
00709 bool matNTValid = calcTrapezoidalTransform(matNT,
00710 matEyeToWorld, matLightFull,
00711 eyeFrust, lightFrust );
00712
00713 if(matNTValid == false)
00714 return;
00715
00716
00717
00718 Int32 shadowTexUnit = (this->getForceTextureUnit() >= 0) ?
00719 this->getForceTextureUnit() : 7;
00720 ShaderProgram *shadowFP = this->getShadowFragmentProgram();
00721
00722 if(shadowFP == NULL)
00723 {
00724 ShaderProgramUnrecPtr newShadowFP = ShaderProgram::createLocal();
00725 newShadowFP->setShaderType(GL_FRAGMENT_SHADER);
00726 newShadowFP->setProgram (_spotFPCode );
00727
00728 newShadowFP->addUniformVariable("TSME_matEyeToLight", matEyeToLight);
00729 newShadowFP->addUniformVariable("TSME_matLightProj", matLightProj );
00730 newShadowFP->addUniformVariable("TSME_matNT", matNT );
00731 newShadowFP->addUniformVariable("TSME_texShadow", shadowTexUnit);
00732 newShadowFP->addUniformVariable("TSME_texShadowSizeInv",
00733 Vec2f(1.f / getWidth (),
00734 1.f / getHeight() ) );
00735
00736 this->setShadowFragmentProgram(newShadowFP);
00737 shadowFP = newShadowFP;
00738 }
00739 else
00740 {
00741 shadowFP->updateUniformVariable("TSME_matEyeToLight", matEyeToLight);
00742 shadowFP->updateUniformVariable("TSME_matLightProj", matLightProj );
00743 shadowFP->updateUniformVariable("TSME_matNT", matNT );
00744 }
00745
00746 updateLightPassMaterial(data, 0, matNT);
00747
00748 commitChanges();
00749
00750 ract->pushPartition();
00751 {
00752 RenderPartition *part = ract->getActivePartition( );
00753 Window *win = ract->getWindow ( );
00754 FrameBufferObject *target = data->getRenderTargets (0);
00755 Background *back = data->getBackground ( );
00756
00757 part->setRenderTarget(target);
00758 part->setWindow (win );
00759
00760 part->calcViewportDimension(0.f, 0.f, 1.f, 1.f,
00761 target->getWidth (),
00762 target->getHeight() );
00763
00764 part->setupProjection(matLightProj, Matrixr::identity());
00765 part->setupViewing (matWorldToLight );
00766
00767 part->setNear (parentPart->getNear());
00768 part->setFar (parentPart->getFar ());
00769
00770 part->setFrustum (lightFrust );
00771
00772 part->setBackground (back );
00773
00774 part->overrideMaterial(data->getLightPassMaterials(0),
00775 ract->getActNode ( ) );
00776
00777 this->recurseFrom(ract, spotL);
00778 ract->useNodeList(false );
00779
00780 part->overrideMaterial(NULL,
00781 ract->getActNode ( ) );
00782 }
00783 ract->popPartition();
00784 }
00785
00789 void TrapezoidalShadowMapEngine::intersectFrusta(
00790 const FrustumVolume &fA, const FrustumVolume &fB,
00791 std::vector<Pnt3r> &intVerts, Pnt3r &intCenter)
00792 {
00793 const Plane *planes[12];
00794
00795 intVerts.clear ( );
00796 intVerts.reserve(16);
00797
00798 for(UInt32 i = 0; i < 6; ++i)
00799 {
00800 planes[i ] = &(fA.getPlanes()[i]);
00801 planes[6 + i] = &(fB.getPlanes()[i]);
00802 }
00803
00804
00805
00806
00807
00808
00809 for(UInt32 i = 0; i < 12; ++i)
00810 {
00811
00812 for(UInt32 j = osgMax<UInt32>(2, i + 1); j < 12; ++j)
00813 {
00814
00815
00816
00817 if((i == 6 && j == 7) ||
00818 (i == 2 && j == 3) || (i == 8 && j == 9) ||
00819 (i == 4 && j == 5) || (i == 10 && j == 11) )
00820 continue;
00821
00822 Line intLine;
00823 if(planes[i]->intersect(*planes[j], intLine) == false)
00824 continue;
00825
00826 for(UInt32 k = j + 1; k < 12; ++k)
00827 {
00828
00829
00830
00831 if((j == 6 && k == 7) ||
00832 (j == 2 && k == 3) || (j == 8 && k == 9) ||
00833 (j == 4 && k == 5) || (j == 10 && k == 11) )
00834 continue;
00835
00836 Pnt3r intPoint;
00837 if(planes[k]->intersectInfinite(intLine, intPoint) == false)
00838 continue;
00839
00840 bool intPointValid = true;
00841
00842
00843
00844 for(UInt32 m = 0; m < 12; ++m)
00845 {
00846
00847
00848 if(m == i || m == j || m == k)
00849 continue;
00850
00851 if(planes[m]->isInHalfSpace(intPoint) == false)
00852 {
00853 intPointValid = false;
00854 break;
00855 }
00856 }
00857
00858 if(intPointValid == true)
00859 {
00860 intCenter += intPoint.subZero();
00861 intVerts.push_back(intPoint);
00862 }
00863 }
00864 }
00865 }
00866
00867 intCenter /= intVerts.size();
00868 }
00869
00870 void TrapezoidalShadowMapEngine::updateLightPassMaterial(
00871 TSMEngineData *data, UInt16 faceIdx, const Matrixr &matNT)
00872 {
00873 if(data->getMFLightPassMaterials()->size() < 6)
00874 data->editMFLightPassMaterials()->resize(6, NULL);
00875
00876 ChunkMaterial *lightPassMat = data->getLightPassMaterials(faceIdx);
00877
00878 if(lightPassMat == NULL)
00879 {
00880 ColorMaskChunkUnrecPtr newCMaskChunk = ColorMaskChunk::create();
00881 newCMaskChunk->setMaskR(false);
00882 newCMaskChunk->setMaskG(false);
00883 newCMaskChunk->setMaskB(false);
00884 newCMaskChunk->setMaskA(false);
00885
00886 #ifdef OSG_TSME_LIGHTPASS_EXACT
00887
00888 ShaderProgramUnrecPtr newLightPassVP = ShaderProgram::createLocal();
00889 newLightPassVP->setShaderType(GL_VERTEX_SHADER);
00890 newLightPassVP->setProgram (_lightPassVPCode);
00891 newLightPassVP->addUniformVariable("TSME_matNT", matNT);
00892
00893 ShaderProgramUnrecPtr newLightPassFP = ShaderProgram::createLocal();
00894 newLightPassFP->setShaderType(GL_FRAGMENT_SHADER);
00895 newLightPassFP->setProgram (_lightPassFPCode );
00896 newLightPassFP->addUniformVariable("TSME_offsetFactor", getOffsetFactor());
00897 newLightPassFP->addUniformVariable("TSME_offsetBias", getOffsetBias ());
00898
00899 ShaderProgramChunkUnrecPtr newLightPassSHChunk =
00900 ShaderProgramChunk::createLocal();
00901 newLightPassSHChunk->addVertexShader (newLightPassVP);
00902 newLightPassSHChunk->addFragmentShader(newLightPassFP);
00903
00904 ChunkMaterialUnrecPtr newLightPassMat = ChunkMaterial::createLocal();
00905 newLightPassMat->addChunk(newCMaskChunk );
00906 newLightPassMat->addChunk(newLightPassSHChunk);
00907
00908 lightPassMat = newLightPassMat;
00909 data->editMFLightPassMaterials()->replace(faceIdx, newLightPassMat);
00910
00911 #else
00912
00913 PolygonChunkUnrecPtr newPolyChunk = PolygonChunk::createLocal();
00914 newPolyChunk->setOffsetFill (true );
00915 newPolyChunk->setOffsetFactor(getOffsetFactor());
00916 newPolyChunk->setOffsetBias (getOffsetBias ());
00917
00918 ShaderProgramUnrecPtr newLightPassVP = ShaderProgram::createLocal();
00919 newLightPassVP->setShaderType (GL_VERTEX_SHADER );
00920 newLightPassVP->setProgram (_lightPassVPCode );
00921 newLightPassVP->addUniformVariable("TSME_matNT", matNT);
00922
00923 ShaderProgramChunkUnrecPtr newLightPassSHChunk =
00924 ShaderProgramChunk::createLocal();
00925 newLightPassSHChunk->addVertexShader(newLightPassVP);
00926
00927 ChunkMaterialUnrecPtr newLightPassMat = ChunkMaterial::createLocal();
00928 newLightPassMat->addChunk(newCMaskChunk );
00929 newLightPassMat->addChunk(newPolyChunk );
00930 newLightPassMat->addChunk(newLightPassSHChunk);
00931
00932 lightPassMat = newLightPassMat;
00933 (*data->editMFLightPassMaterials())[faceIdx] = newLightPassMat;
00934
00935 #endif
00936
00937
00938 }
00939 else
00940 {
00941 ShaderProgramChunk *lightPassSHChunk =
00942 dynamic_cast<ShaderProgramChunk *>(
00943 lightPassMat->find(ShaderProgramChunk::getClassType()));
00944
00945 if(lightPassSHChunk != NULL)
00946 {
00947 ShaderProgram *lightPassVP = lightPassSHChunk->getVertexShader(0);
00948 lightPassVP->updateUniformVariable("TSME_matNT", matNT);
00949 }
00950 }
00951 }
00952
00968 bool TrapezoidalShadowMapEngine::calcTrapezoidalTransform(
00969 Matrixr &matNT,
00970 const Matrixr &matEyeToWorld,
00971 const Matrixr &matLightFull,
00972 const FrustumVolume &eyeFrust,
00973 const FrustumVolume &lightFrust )
00974 {
00975
00976 Pnt3r eyePos;
00977 matEyeToWorld.mult (eyePos, eyePos);
00978 matLightFull .multFull(eyePos, eyePos);
00979
00980
00981 std::vector<Pnt3r> intVerts;
00982 Pnt3r intCenter;
00983 intersectFrusta(eyeFrust, lightFrust, intVerts, intCenter);
00984
00985 if(intVerts.empty() == true)
00986 return false;
00987
00988
00989 matLightFull.multFull(intCenter, intCenter);
00990
00991 std::vector<Pnt3r>::iterator ivIt = intVerts.begin();
00992 std::vector<Pnt3r>::iterator ivEnd = intVerts.end ();
00993
00994 for(; ivIt != ivEnd; ++ivIt)
00995 matLightFull.multFull(*ivIt, *ivIt);
00996
00997 Pnt2r eyePos2D (eyePos [0], eyePos [1]);
00998 Pnt2r intCenter2D(intCenter[0], intCenter[1]);
00999
01000
01001 Vec2r clDir (intCenter2D - eyePos2D);
01002 clDir.normalize();
01003 Vec2r clNorm(-clDir[1], clDir[0]);
01004
01005
01006 Real clDist = clNorm.dot(eyePos2D.subZero());
01007
01008
01009
01010
01011
01012
01013
01014
01015 Pnt2r tlBase;
01016 Pnt2r blBase;
01017 Real topDist = TypeTraits<Real>::getMax();
01018 Real baseDist = TypeTraits<Real>::getMin();
01019
01020 std::vector<Pnt3r>::const_iterator ivCIt = intVerts.begin();
01021 std::vector<Pnt3r>::const_iterator ivCEnd = intVerts.end ();
01022
01023 for(; ivCIt != ivCEnd; ++ivCIt)
01024 {
01025 Pnt2r ivPnt((*ivCIt)[0], (*ivCIt)[1]);
01026
01027 ivPnt = ivPnt - (clNorm.dot(ivPnt) - clDist) * clNorm;
01028
01029 Real dist = (ivPnt - eyePos2D).squareLength();
01030 dist *= osgSgn(clDir.dot(ivPnt - eyePos2D));
01031
01032 if(dist < topDist)
01033 {
01034 topDist = dist;
01035 tlBase = ivPnt;
01036 }
01037
01038 if(dist > baseDist)
01039 {
01040 baseDist = dist;
01041 blBase = ivPnt;
01042 }
01043 }
01044
01045 topDist = osgSgn(topDist ) * osgSqrt(osgAbs(topDist ));
01046 baseDist = osgSgn(baseDist) * osgSqrt(osgAbs(baseDist));
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056 ivCIt = intVerts.begin();
01057 ivCEnd = intVerts.end ();
01058
01059
01060
01061 Real lambda = baseDist - topDist;
01062 Real delta = 0.5f * lambda;
01063 Real xi = -0.6f;
01064 Real eta = ((lambda * delta) + (lambda * delta * xi)) /
01065 (lambda - 2.f * delta - lambda * xi );
01066 Pnt2r trapTip = tlBase - (eta * clDir);
01067 Pnt2r focusPnt = tlBase + (delta * clDir);
01068
01069
01070
01071
01072 Pnt2r posPnt;
01073 Real posCos = 1.f;
01074 Pnt2r negPnt;
01075 Real negCos = 1.f;
01076
01077 for(UInt32 i = 0; ivCIt != ivCEnd; ++ivCIt, ++i)
01078 {
01079 Pnt2r ivPnt((*ivCIt)[0], (*ivCIt)[1]);
01080
01081 Vec2r v = ivPnt - trapTip;
01082 v.normalize();
01083 Real currCos = osgAbs(clDir.dot(v));
01084
01085 if(clNorm.dot(v) >= 0.f)
01086 {
01087 if(currCos <= posCos)
01088 {
01089 posPnt = ivPnt;
01090 posCos = currCos;
01091 }
01092 }
01093 else
01094 {
01095 if(currCos <= negCos)
01096 {
01097 negPnt = ivPnt;
01098 negCos = currCos;
01099 }
01100 }
01101 }
01102
01103
01104 Pnt2r trapVerts [4];
01105 Pnt2r extraVerts[2];
01106 Real posTan = osgTan(osgACos(posCos));
01107 Real negTan = osgTan(osgACos(negCos));
01108
01109 trapVerts[0] = blBase - ((eta + lambda) * negTan * clNorm);
01110 trapVerts[1] = blBase + ((eta + lambda) * posTan * clNorm);
01111 trapVerts[2] = tlBase + ( eta * posTan * clNorm);
01112 trapVerts[3] = tlBase - ( eta * negTan * clNorm);
01113
01114 extraVerts[0] = focusPnt + ((eta + delta) * posTan * clNorm);
01115 extraVerts[1] = focusPnt - ((eta + delta) * negTan * clNorm);
01116
01117
01118
01119
01120 Vec2r u = 0.5f * (trapVerts[2].subZero() + trapVerts[3].subZero());
01121 Vec2r v = trapVerts[3] - trapVerts[2];
01122 v.normalize();
01123
01124 matNT.setValue( v[0], v[1], 0.f, -(u[0] * v[0] + u[1] * v[1]),
01125 -v[1], v[0], 0.f, (u[0] * v[1] - u[1] * v[0]),
01126 0.f, 0.f, 1.f, 0.f,
01127 0.f, 0.f, 0.f, 1.f);
01128
01129
01130 matNT[3][0] = - (matNT[0][0] * trapTip[0] + matNT[1][0] * trapTip[1]);
01131 matNT[3][1] = - (matNT[0][1] * trapTip[0] + matNT[1][1] * trapTip[1]);
01132
01133
01134
01135 v[0] = matNT[0][0] * u[0] + matNT[1][0] * u[1] + matNT[3][0];
01136 v[1] = matNT[0][1] * u[0] + matNT[1][1] * u[1] + matNT[3][1];
01137
01138 Real a = - v[0] / v[1];
01139
01140
01141 matNT[0][0] += a * matNT[0][1];
01142 matNT[1][0] += a * matNT[1][1];
01143 matNT[2][0] += a * matNT[2][1];
01144 matNT[3][0] += a * matNT[3][1];
01145
01146
01147
01148
01149 v[0] = 1.f / (matNT[0][0] * trapVerts[2][0] + matNT[1][0] * trapVerts[2][1] + matNT[3][0]);
01150 v[1] = 1.f / (matNT[0][1] * trapVerts[2][0] + matNT[1][1] * trapVerts[2][1] + matNT[3][1]);
01151
01152 matNT[0][0] *= v[0]; matNT[0][1] *= v[1];
01153 matNT[1][0] *= v[0]; matNT[1][1] *= v[1];
01154 matNT[2][0] *= v[0]; matNT[2][1] *= v[1];
01155 matNT[3][0] *= v[0]; matNT[3][1] *= v[1];
01156
01157
01158 matNT[0][3] = matNT[0][1];
01159 matNT[1][3] = matNT[1][1];
01160 matNT[2][3] = matNT[2][1];
01161 matNT[3][3] = matNT[3][1];
01162 matNT[3][1] += 1.f;
01163
01164
01165
01166
01167 u[0] = matNT[0][1] * trapVerts[0][0] + matNT[1][1] * trapVerts[0][1] + matNT[3][1];
01168 u[1] = matNT[0][3] * trapVerts[0][0] + matNT[1][3] * trapVerts[0][1] + matNT[3][3];
01169 v[0] = matNT[0][1] * trapVerts[2][0] + matNT[1][1] * trapVerts[2][1] + matNT[3][1];
01170 v[1] = matNT[0][3] * trapVerts[2][0] + matNT[1][3] * trapVerts[2][1] + matNT[3][3];
01171 a = - 0.5f * (u[0] / u[1] + v[0] / v[1]);
01172
01173 matNT[0][1] += matNT[0][3] * a;
01174 matNT[1][1] += matNT[1][3] * a;
01175 matNT[2][1] += matNT[2][3] * a;
01176 matNT[3][1] += matNT[3][3] * a;
01177
01178
01179
01180 u[0] = matNT[0][1] * trapVerts[0][0] + matNT[1][1] * trapVerts[0][1] + matNT[3][1];
01181 u[1] = matNT[0][3] * trapVerts[0][0] + matNT[1][3] * trapVerts[0][1] + matNT[3][3];
01182 a = -u[1] / u[0];
01183
01184 matNT[0][1] *= a;
01185 matNT[1][1] *= a;
01186 matNT[2][1] *= a;
01187 matNT[3][1] *= a;
01188
01189 return true;
01190 }
01191
01192
01193 void TrapezoidalShadowMapEngine::emptyCubeFaceDrawFunc(DrawEnv *drawEnv)
01194 {
01195 }
01196
01197 #if 0
01198 void TrapezoidalShadowMapEngine::calcJitterTexture(
01199 Image *img,
01200 UInt32 blockSizeX, UInt32 blockSizeY,
01201 UInt32 angleSectors, UInt32 distSectors)
01202 {
01203 UInt32 zSize = angleSector * distSectors / 2;
01204
01205 img->set(OSG_RGBA_PF,
01206 blockSizeX,
01207 blockSizeY,
01208 zSize,
01209 1,
01210 1,
01211 0.0,
01212 NULL,
01213 OSG_UINT8_IMAGEDATA,
01214 true,
01215 1);
01216
01217 Real32 sizeCellU = 1.f / angleSectors;
01218 Real32 sizeCellV = 1.f / distSectors;
01219
01220 UInt8 *pPixel = img->editData(0, 0, 0);
01221
01222 for(UInt32 zPos = 0; zPos < zSize; ++zPos)
01223 {
01224 Real32 cell0U = sizeCellU * (2 * zPos % angleSectors);
01225 Real32 cell0V = sizeCellV * (distSectors - 1 - (2 * zPos / angleSectors));
01226 Real32 cell1U = sizeCellU * (1 + (2 * zPos % angleSectors));
01227 Real32 cell1V = sizeCellV * (distSectors - 1 - (2 * zPos / angleSectors));
01228
01229 Real32 grid0U = sizeCellU * (2 * zPos % blockSizeX);
01230 Real32 grid0V = 1.f - sizeCellV * (2 * zPos / blockSizeY);
01231 Real32 grid1U = sizeCellU * ((2 * zPos % blockSizeX) + 1);
01232 Real32 grid1V = 1.f - sizeCellV * (2 * zPos / blockSizeY);
01233
01234 for(UInt32 xPos = 0; xPos < blockSizeX; ++xPos)
01235 {
01236 for(UInt32 yPos = 0; yPos < blockSizeY; ++yPos)
01237 {
01238
01239 }
01240 }
01241 }
01242 }
01243 #endif
01244
01245 OSG_END_NAMESPACE