OSGTrapezoidalShadowMapEngine.cpp

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002  *                                OpenSG                                     *
00003  *                                                                           *
00004  *                                                                           *
00005  *               Copyright (C) 2000-2006 by the OpenSG Forum                 *
00006  *                                                                           *
00007  *                            www.opensg.org                                 *
00008  *                                                                           *
00009  *   contact: dirk@opensg.org, gerrit.voss@vossg.org, jbehr@zgdv.de          *
00010  *                                                                           *
00011 \*---------------------------------------------------------------------------*/
00012 /*---------------------------------------------------------------------------*\
00013  *                                License                                    *
00014  *                                                                           *
00015  * This library is free software; you can redistribute it and/or modify it   *
00016  * under the terms of the GNU Library General Public License as published    *
00017  * by the Free Software Foundation, version 2.                               *
00018  *                                                                           *
00019  * This library is distributed in the hope that it will be useful, but       *
00020  * WITHOUT ANY WARRANTY; without even the implied warranty of                *
00021  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
00022  * Library General Public License for more details.                          *
00023  *                                                                           *
00024  * You should have received a copy of the GNU Library General Public         *
00025  * License along with this library; if not, write to the Free Software       *
00026  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.                 *
00027  *                                                                           *
00028 \*---------------------------------------------------------------------------*/
00029 /*---------------------------------------------------------------------------*\
00030  *                                Changes                                    *
00031  *                                                                           *
00032  *                                                                           *
00033  *                                                                           *
00034  *                                                                           *
00035  *                                                                           *
00036  *                                                                           *
00037 \*---------------------------------------------------------------------------*/
00038
00039 //---------------------------------------------------------------------------
00040 //  Includes
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 // Documentation for this class is emitted in the
00061 // OSGTrapezoidalShadowMapEngineBase.cpp file.
00062 // To modify it, please change the .fcd file (OSGTrapezoidalShadowMapEngine.fcd) and
00063 // regenerate the base file.
00064
00065 /***************************************************************************\
00066  *                           Class variables                               *
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  *                           Class methods                                 *
00362 \***************************************************************************/
00363
00364 void TrapezoidalShadowMapEngine::initMethod(InitPhase ePhase)
00365 {
00366     Inherited::initMethod(ePhase);
00367 }
00368
00369
00370 /***************************************************************************\
00371  *                           Instance methods                              *
00372 \***************************************************************************/
00373
00374 /*-------------------------------------------------------------------------*\
00375  -  private                                                                 -
00376 \*-------------------------------------------------------------------------*/
00377
00378 /*----------------------- constructors & destructors ----------------------*/
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 /*----------------------------- class specific ----------------------------*/
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         // already generating a shadow map for another light source?
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             // setup a minimal partition to clear the cube face
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 //    Real           cosSpotCutOff = osgCos(spotL->getSpotCutOff());
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     // take all combinations of 3 planes -- but avoid choosing planes
00805     // we know to be parallel (i.e. near and far of the same frustum), or
00806     // that are known to intersect outside the frustum (i.e top/bottom,
00807     // left/right).
00808
00809     for(UInt32 i = 0; i < 12; ++i)
00810     {
00811         // choose initial value of j such that it avoids near and far of fA
00812         for(UInt32 j = osgMax<UInt32>(2, i + 1); j < 12; ++j)
00813         {
00814             // near/far are parallel,
00815             // left/right always intersect outside the frustum,
00816             // top/bottom always intersect outside the frustum
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                 // near/far are parallel,
00829                 // left/right always intersect outside the frustum,
00830                 // top/bottom always intersect outside the frustum
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                 // check the intersection point against all planes to ensure
00843                 // it is in both frusta
00844                 for(UInt32 m = 0; m < 12; ++m)
00845                 {
00846                     // intPoint is the intersection of planes i, j, k, so
00847                     // we don't have to test against those
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     // obtain post proj. light space eye position
00976     Pnt3r eyePos;
00977     matEyeToWorld.mult    (eyePos, eyePos);
00978     matLightFull .multFull(eyePos, eyePos);
00979
00980     // intersect eye and light frusta, get vertices and center of intersection
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     // xform intCenter and intVerts to post proj. light space
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     // center line, normal, direction and distance from origin
01001     Vec2r clDir (intCenter2D - eyePos2D);
01002     clDir.normalize();
01003     Vec2r clNorm(-clDir[1], clDir[0]);
01004
01005     // distance of the center line from the origin
01006     Real clDist = clNorm.dot(eyePos2D.subZero());
01007
01008     // compute top and base lines:
01009     //  - project intVerts onto the center line.
01010     //  - top line is perpendicular to center line and goes through the
01011     //    projected point closest to eyePos
01012     //  - base line is perpendicular to center line and goes through the
01013     //    projected point farthest from eyePos
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     // compute side lines:
01049     //  - choose focusPnt (everything closer to the near plane is mapped to
01050     //    80% of the shadow map) - here we just take the point at 0.7 between
01051     //    tlBase and blBase
01052     //  - find a point (trapTip, q in the paper) on center line such that
01053     //    focusPnt is mapped the 80% line in the shadow map
01054     //  - choose lines through q that touch the convex hull of intVerts
01055
01056     ivCIt  = intVerts.begin();
01057     ivCEnd = intVerts.end  ();
01058
01059 //    Real  centerDist = (intCenter2D - eyePos2D).length();
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     // on both sides of the center line, find the point in intVerts that has
01070     // the smallest |cosine| (largest angle) between clDir and the vector
01071     // from trapTip to intVerts[i]
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     // compute corners of trapezoid:
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     // == xform trapezoid to unit square ==
01118
01119     // M1 = R * T1  -- translate center of top line to origin and rotate
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     // M2 = T2 * M1  -- translate tip to origin
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     // M3 = H * M2  -- shear to make it symmetric wrt to the y axis
01134     //    v = M2 * u
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     //    matNT[*][0] : = mat[*][0] + a * mat[*][1]
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     // M4 = S1 * M3  -- scale to make sidelines orthogonal and 
01147     //                  top line is at y == 1
01148     //    v = 1 / (M3 * t2)
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     // M5 = N * M4  -- turn trapezoid into rectangle
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     // M6 = T3 * M5  -- translate center to origin
01165     //    u = "M5 * t0"  - only y and w coordinates
01166     //    v = "M5 * t2"  - only y and w coordinates
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     // M7 = S2 * M6  -- scale to fill -1/+1 square
01179     //    u = "M6 * t0"  - only y and w coordinates
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 // Dummy draw function.
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