csplugincommon/rendermanager/autofx_reflrefr.h Source File (Crystal Space 2.0 Public API Reference)

| ## Public API Reference

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

csplugincommon/rendermanager/autofx_reflrefr.h
Go to the documentation of this file.

    00001 /*
    00002     Copyright (C) 2008 by Frank Richter
    00003
    00004     This library is free software; you can redistribute it and/or
    00005     modify it under the terms of the GNU Library General Public
    00006     License as published by the Free Software Foundation; either
    00007     version 2 of the License, or (at your option) any later version.
    00008
    00009     This library is distributed in the hope that it will be useful,
    00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
    00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    00012     Library General Public License for more details.
    00013
    00014     You should have received a copy of the GNU Library General Public
    00015     License along with this library; if not, write to the Free
    00016     Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    00017 */
    00018
    00019 #ifndef __CS_CSPLUGINCOMMON_RENDERMANAGER_AUTOFX_REFLREFR_H__
    00020 #define __CS_CSPLUGINCOMMON_RENDERMANAGER_AUTOFX_REFLREFR_H__
    00021
    00026 #include "iengine/mesh.h"
    00027 #include "imesh/object.h"
    00028 #include "imesh/objmodel.h"
    00029 #include "csgeom/polyclip.h"
    00030
    00031 #include "csplugincommon/rendermanager/posteffects.h"
    00032 #include "csplugincommon/rendermanager/rendertree.h"
    00033 #include "csplugincommon/rendermanager/texturecache.h"
    00034
    00035 namespace CS
    00036 {
    00037   namespace RenderManager
    00038   {
    00039     namespace AutoFX
    00040     {
    00046       class ReflectRefract_Base
    00047       {
    00048       public:
    00050         enum { svUserFlags = iShader::svuTextures };
    00051
    00057         struct CS_CRYSTALSPACE_EXPORT PersistentData
    00058         {
    00059           CS::ShaderVarStringID svTexPlaneRefl;
    00060           CS::ShaderVarStringID svTexPlaneRefr;
    00061           CS::ShaderVarStringID svTexPlaneReflDepth;
    00062           CS::ShaderVarStringID svTexPlaneRefrDepth;
    00063
    00064           CS::ShaderVarStringID svPlaneRefl;
    00065           CS::ShaderVarStringID svClipPlaneReflRefr;
    00066
    00067           CS::ShaderVarStringID svReflXform;
    00068           csRef<csShaderVariable> reflXformSV;
    00069           CS::ShaderVarStringID svRefrXform;
    00070           csRef<csShaderVariable> refrXformSV;
    00071           bool screenFlipped;
    00072           float mappingStretch;
    00073
    00074           uint currentFrame;
    00075           uint updatesThisFrame;
    00076
    00077           TextureCacheT<CS::Utility::ResourceCache::ReuseIfOnlyOneRef> texCache;
    00078           TextureCacheT<CS::Utility::ResourceCache::ReuseIfOnlyOneRef> texCacheDepth;
    00079           struct ReflectRefractSVs
    00080           {
    00081             csTicks lastUpdate;
    00082             uint lastUpdateFrame;
    00083             csTransform lastCamera;
    00084
    00085             csRef<csShaderVariable> reflectSV;
    00086             csRef<csShaderVariable> refractSV;
    00087             csRef<csShaderVariable> reflectDepthSV;
    00088             csRef<csShaderVariable> refractDepthSV;
    00089
    00090             csRef<iShaderVariableContext> clipPlaneReflContext;
    00091             csRef<csShaderVariable> clipPlaneReflSV;
    00092             csRef<iShaderVariableContext> clipPlaneRefrContext;
    00093             csRef<csShaderVariable> clipPlaneRefrSV;
    00094
    00095             ReflectRefractSVs() : lastUpdate (0), lastUpdateFrame (~0) {}
    00096           };
    00097           typedef csHash<ReflectRefractSVs, csPtrKey<iMeshWrapper> > ReflRefrCache;
    00098           ReflRefrCache reflRefrCache;
    00099
    00100           int resolutionReduceRefl;
    00101           int resolutionReduceRefr;
    00102           uint texUpdateInterval;
    00103           uint maxUpdatesPerFrame;
    00104           float cameraChangeThresh;
    00105
    00106           uint dbgReflRefrTex;
    00107
    00109           PersistentData();
    00110
    00118           void Initialize (iObjectRegistry* objReg,
    00119                           RenderTreeBase::DebugPersistent& dbgPersist,
    00120                           PostEffectManager* postEffects);
    00121
    00126           void UpdateNewFrame ();
    00127         };
    00128
    00129         ReflectRefract_Base (PersistentData& persist) : persist (persist)
    00130         {}
    00131       protected:
    00132         PersistentData& persist;
    00133       };
    00134
    00189       template<typename RenderTree,
    00190         typename ContextSetupReflect,
    00191         typename ContextSetupRefract = ContextSetupReflect>
    00192       class ReflectRefract : public ReflectRefract_Base
    00193       {
    00194       public:
    00195         ReflectRefract (PersistentData& persist,
    00196           ContextSetupReflect& contextFunction) :
    00197           ReflectRefract_Base (persist),
    00198           contextFunctionRefl (contextFunction),
    00199           contextFunctionRefr (contextFunction)
    00200         {}
    00201         ReflectRefract (PersistentData& persist,
    00202           ContextSetupReflect& contextFunctionRefl,
    00203           ContextSetupRefract& contextFunctionRefr) :
    00204           ReflectRefract_Base (persist),
    00205           contextFunctionRefl (contextFunctionRefl),
    00206           contextFunctionRefr (contextFunctionRefr)
    00207         {}
    00208
    00214         void operator() (typename RenderTree::MeshNode* node,
    00215                         size_t layer,
    00216                         typename RenderTree::MeshNode::SingleMesh& mesh,
    00217                         const csBitArray& names)
    00218         {
    00219           // Check if reflection or refraction is needed
    00220           if (!names.IsBitSetTolerant (persist.svTexPlaneRefl)
    00221               && !names.IsBitSetTolerant (persist.svTexPlaneRefr))
    00222             return;
    00223
    00224           /* @@@ NOTE:The same mesh, if rendered in multiple views, will get
    00225             the same reflection/refraction texture. This is wrong.
    00226             However, ignore for now, until someone complains */
    00227           typename PersistentData::ReflectRefractSVs& meshReflectRefract =
    00228             persist.reflRefrCache.GetOrCreate (mesh.meshWrapper);
    00229
    00230           typename RenderTree::ContextNode& context = node->GetOwner();
    00231           RenderTree& renderTree = context.owner;
    00232           RenderView* rview = context.renderView;
    00233
    00234           csShaderVariableStack localStack;
    00235           context.svArrays.SetupSVStack (localStack, layer, mesh.contextLocalId);
    00236
    00237           csTicks currentTicks = csGetTicks ();
    00238           bool forceUpdate = (persist.texUpdateInterval == 0)
    00239             || ((currentTicks - meshReflectRefract.lastUpdate) >
    00240               persist.texUpdateInterval);
    00241
    00242           forceUpdate &= (persist.maxUpdatesPerFrame == 0)
    00243             || (persist.currentFrame - meshReflectRefract.lastUpdateFrame >=
    00244               ((persist.reflRefrCache.GetSize()+persist.maxUpdatesPerFrame-1)
    00245                 / persist.maxUpdatesPerFrame));
    00246
    00247           forceUpdate &= (persist.maxUpdatesPerFrame == 0)
    00248             || (persist.updatesThisFrame < persist.maxUpdatesPerFrame);
    00249
    00250
    00251           iCamera* cam = rview->GetCamera();
    00252           /* Compute a difference for the camera between the last render;
    00253             if bigger than a certain threshold, rerender (whether it's the
    00254             reflections's turn or not) */
    00255           if (!forceUpdate && (persist.cameraChangeThresh > 0))
    00256           {
    00257             const csTransform& camTrans = cam->GetTransform();
    00258             float cameraDiff;
    00259
    00260             cameraDiff = fabsf (camTrans.GetO2T().m11
    00261               - meshReflectRefract.lastCamera.GetO2T().m11);
    00262             cameraDiff += fabsf (camTrans.GetO2T().m12
    00263               - meshReflectRefract.lastCamera.GetO2T().m12);
    00264             cameraDiff += fabsf (camTrans.GetO2T().m13
    00265               - meshReflectRefract.lastCamera.GetO2T().m13);
    00266
    00267             cameraDiff += fabsf (camTrans.GetO2T().m21
    00268               - meshReflectRefract.lastCamera.GetO2T().m21);
    00269             cameraDiff += fabsf (camTrans.GetO2T().m22
    00270               - meshReflectRefract.lastCamera.GetO2T().m22);
    00271             cameraDiff += fabsf (camTrans.GetO2T().m23
    00272               - meshReflectRefract.lastCamera.GetO2T().m23);
    00273
    00274             cameraDiff += fabsf (camTrans.GetO2T().m31
    00275               - meshReflectRefract.lastCamera.GetO2T().m31);
    00276             cameraDiff += fabsf (camTrans.GetO2T().m32
    00277               - meshReflectRefract.lastCamera.GetO2T().m32);
    00278             cameraDiff += fabsf (camTrans.GetO2T().m33
    00279               - meshReflectRefract.lastCamera.GetO2T().m33);
    00280
    00281             cameraDiff += fabsf (camTrans.GetO2TTranslation().x
    00282               - meshReflectRefract.lastCamera.GetO2TTranslation().x);
    00283             cameraDiff += fabsf (camTrans.GetO2TTranslation().y
    00284               - meshReflectRefract.lastCamera.GetO2TTranslation().y);
    00285             cameraDiff += fabsf (camTrans.GetO2TTranslation().z
    00286               - meshReflectRefract.lastCamera.GetO2TTranslation().z);
    00287
    00288             forceUpdate = cameraDiff >= persist.cameraChangeThresh;
    00289           }
    00290
    00291           // But never force an update if we already rendered in this frame
    00292           forceUpdate &= (persist.currentFrame != meshReflectRefract.lastUpdateFrame);
    00293
    00294           bool usesReflTex = names.IsBitSetTolerant (persist.svTexPlaneRefl);
    00295           bool usesReflDepthTex = names.IsBitSetTolerant (persist.svTexPlaneReflDepth);
    00296           bool needReflTex = (usesReflTex
    00297               && (!meshReflectRefract.reflectSV.IsValid() || forceUpdate))
    00298             || (usesReflDepthTex
    00299               && (!meshReflectRefract.reflectDepthSV.IsValid() || forceUpdate));
    00300
    00301           bool usesRefrTex = names.IsBitSetTolerant (persist.svTexPlaneRefr);
    00302           bool usesRefrDepthTex = names.IsBitSetTolerant (persist.svTexPlaneRefrDepth);
    00303           bool needRefrTex = (usesRefrTex
    00304               && (!meshReflectRefract.refractSV.IsValid() || forceUpdate))
    00305             || (usesRefrDepthTex
    00306               && (!meshReflectRefract.refractDepthSV.IsValid() || forceUpdate));
    00307
    00308           int renderW = 512, renderH = 512;
    00309           context.GetTargetDimensions (renderW, renderH);
    00310           int txt_w_refl = renderW >> persist.resolutionReduceRefl;
    00311           int txt_h_refl = renderH >> persist.resolutionReduceRefl;
    00312           int txt_w_refr = renderW >> persist.resolutionReduceRefr;
    00313           int txt_h_refr = renderH >> persist.resolutionReduceRefr;
    00314
    00315           // @@@ Kludge: don't render nested reflections
    00316           bool doRender = localStack[persist.svClipPlaneReflRefr] == 0;
    00317
    00318           csPlane3 reflRefrPlane, reflRefrPlane_cam;
    00319           csBox2 clipBoxRefl, clipBoxRefr;
    00320           if ((needReflTex || needRefrTex) && doRender)
    00321           {
    00322             // Compute reflect/refract plane
    00323             if ((localStack.GetSize() > persist.svPlaneRefl)
    00324                 && (localStack[persist.svPlaneRefl] != 0))
    00325             {
    00326               // Grab reflection plane from a SV
    00327               csShaderVariable* planeSV = localStack[persist.svPlaneRefl];
    00328               csVector4 v;
    00329               planeSV->GetValue (v);
    00330               reflRefrPlane.Set (v.x, v.y, v.z, v.w);
    00331             }
    00332             else
    00333             {
    00334               /* Guess reflection plane from mesh bbox:
    00335                 Take smallest dimension of object space bounding box, make that
    00336                 the direction of reflect plane */
    00337               const csBox3& objBB =
    00338                 mesh.meshWrapper->GetMeshObject()->GetObjectModel()->GetObjectBoundingBox();
    00339               const csVector3& bbSize = objBB.GetSize();
    00340
    00341               int axis;
    00342               if ((bbSize[0] < bbSize[1]) && (bbSize[0] < bbSize[2]))
    00343               {
    00344                 axis = 0;
    00345               }
    00346               else if (bbSize[1] < bbSize[2])
    00347               {
    00348                 axis = 1;
    00349               }
    00350               else
    00351               {
    00352                 axis = 2;
    00353               }
    00354
    00355               csVector3 planeNorm (0);
    00356               planeNorm[axis] = -1;
    00357               reflRefrPlane.Set (planeNorm, 0);
    00358               reflRefrPlane.SetOrigin (objBB.GetCenter());
    00359             }
    00360
    00361             reflRefrPlane =
    00362               mesh.meshWrapper->GetMovable()->GetFullTransform().This2Other (reflRefrPlane);
    00363
    00364             reflRefrPlane_cam =
    00365               cam->GetTransform().Other2This (reflRefrPlane);
    00366             doRender = reflRefrPlane.Classify (cam->GetTransform().GetOrigin()) <= 0;
    00367
    00368             meshReflectRefract.clipPlaneReflSV.AttachNew (new csShaderVariable (
    00369               persist.svClipPlaneReflRefr));
    00370             meshReflectRefract.clipPlaneReflSV->SetValue (csVector4 (
    00371               -reflRefrPlane.A(),
    00372               -reflRefrPlane.B(),
    00373               -reflRefrPlane.C(),
    00374               -reflRefrPlane.D()));
    00375             meshReflectRefract.clipPlaneReflContext.AttachNew (
    00376               new csShaderVariableContext);
    00377             meshReflectRefract.clipPlaneReflContext->AddVariable (
    00378               meshReflectRefract.clipPlaneReflSV);
    00379
    00380             meshReflectRefract.clipPlaneRefrSV.AttachNew (new csShaderVariable (
    00381               persist.svClipPlaneReflRefr));
    00382             meshReflectRefract.clipPlaneRefrSV->SetValue (csVector4 (
    00383               reflRefrPlane.A(),
    00384               reflRefrPlane.B(),
    00385               reflRefrPlane.C(),
    00386               reflRefrPlane.D()));
    00387             meshReflectRefract.clipPlaneRefrContext.AttachNew (
    00388               new csShaderVariableContext);
    00389             meshReflectRefract.clipPlaneRefrContext->AddVariable (
    00390               meshReflectRefract.clipPlaneRefrSV);
    00391
    00392             // Compute screen space bounding box
    00393             {
    00394               const csBox3& objBB_world =  mesh.meshWrapper->GetWorldBoundingBox();
    00395               float min_z, max_z;
    00396               objBB_world.ProjectBox (cam->GetTransform(),
    00397                 cam->GetProjectionMatrix(), clipBoxRefl, min_z, max_z,
    00398                 txt_w_refl, txt_h_refl);
    00399               objBB_world.ProjectBox (cam->GetTransform(),
    00400                 cam->GetProjectionMatrix(), clipBoxRefr, min_z, max_z,
    00401                 txt_w_refr, txt_h_refr);
    00402             }
    00403
    00404             /* To reduce bleeding from filtering, fuzz the reflection mapping to
    00405                 be actually stretched out a pixel at the corners */
    00406             if ((persist.mappingStretch > 0)
    00407                 && ((persist.resolutionReduceRefr > 0)
    00408                   || (persist.resolutionReduceRefl > 0)))
    00409             {
    00410               /* Since reflection + refraction share the same TC transform,
    00411                 compute the 'fuzz' from the smaller one. This can lead to
    00412                 distortions when the resolutions differ a lot ... but hopefully
    00413                 doesn't happen often */
    00414               csBox2 dstBox;
    00415               int txt_w, txt_h;
    00416               if (persist.resolutionReduceRefr > persist.resolutionReduceRefl)
    00417               {
    00418                 dstBox = clipBoxRefr;
    00419                 txt_w = txt_w_refr;
    00420                 txt_h = txt_h_refr;
    00421               }
    00422               else
    00423               {
    00424                 dstBox = clipBoxRefl;
    00425                 txt_w = txt_w_refl;
    00426                 txt_h = txt_h_refl;
    00427               }
    00428
    00429               float oldMinY = dstBox.MinY();
    00430               dstBox.SetMin (1, txt_h-dstBox.MaxY());
    00431               dstBox.SetMax (1, txt_h-oldMinY);
    00432               dstBox *= csBox2 (0, 0, txt_w, txt_h);
    00433               csBox2 useBox (dstBox.MinX() + persist.mappingStretch,
    00434                 dstBox.MinY() + persist.mappingStretch,
    00435                 dstBox.MaxX() - persist.mappingStretch,
    00436                 dstBox.MaxY() - persist.mappingStretch);
    00437               float dw = dstBox.MaxX() - dstBox.MinX();
    00438               float dh = dstBox.MaxY() - dstBox.MinY();
    00439               float sw = useBox.MaxX() - useBox.MinX();
    00440               float sh = useBox.MaxY() - useBox.MinY();
    00441               float scaleX = sw/dw;
    00442               float scaleY = sh/dh;
    00443               float cX1 = useBox.GetCenter().x/(float)txt_w;
    00444               float cY1 = useBox.GetCenter().y/(float)txt_h;
    00445               float cX2 = dstBox.GetCenter().x/(float)txt_w;
    00446               float cY2 = dstBox.GetCenter().y/(float)txt_h;
    00447               float dX = (0.5f-cX1)*scaleX + cX2;
    00448               float dY = (0.5f-cY1)*scaleY + cY2;
    00449
    00450               persist.reflXformSV->SetValue (csVector4 (0.5f * scaleX,
    00451                 (persist.screenFlipped ? 0.5f : -0.5f) * scaleY,
    00452                 dX, dY));
    00453             }
    00454             else
    00455             {
    00456               persist.reflXformSV->SetValue (csVector4 (0.5f,
    00457                 (persist.screenFlipped ? 0.5f : -0.5f),
    00458                 0.5f, 0.5f));
    00459             }
    00460             persist.refrXformSV->SetValue (csVector4 (0.5f,
    00461               (persist.screenFlipped ? 0.5f : -0.5f),
    00462               0.5f, 0.5f));
    00463           }
    00464
    00465           typename RenderTree::ContextNode* reflCtx = 0;
    00466           typename RenderTree::ContextNode* refrCtx = 0;
    00467
    00468           if (usesReflTex || usesReflDepthTex)
    00469           {
    00470             csRef<csShaderVariable> svReflection;
    00471             csRef<csShaderVariable> svReflectionDepth;
    00472
    00473             if (needReflTex && doRender)
    00474             {
    00475               // Compute reflection view
    00476               iCamera* cam = rview->GetCamera();
    00477               // Create a new view
    00478               csRef<CS::RenderManager::RenderView> reflView;
    00479               csRef<iCamera> newCam (cam->Clone());
    00480               iCamera* inewcam = newCam;
    00481         reflView = renderTree.GetPersistentData().renderViews.CreateRenderView (rview);
    00482               reflView->SetCamera (inewcam);
    00483               CS::Utility::MeshFilter meshFilter;
    00484               meshFilter.AddFilterMesh (mesh.meshWrapper);
    00485               reflView->SetMeshFilter(meshFilter);
    00486
    00487               // Change the camera transform to be a reflection across reflRefrPlane
    00488               csReversibleTransform reflection (csTransform::GetReflect (reflRefrPlane));
    00489               csTransform reflection_cam (csTransform::GetReflect (reflRefrPlane_cam));
    00490               const csTransform& world2cam (inewcam->GetTransform());
    00491               csTransform reflected;
    00492               reflected.SetO2T (reflection_cam.GetO2T() * world2cam.GetO2T());
    00493               reflected.SetOrigin (reflection.Other2This (world2cam.GetOrigin()));
    00494               inewcam->SetTransform (reflected);
    00495               inewcam->SetMirrored (true);
    00496
    00497               csPlane3 reflRefrPlane_newcam;
    00498               reflRefrPlane_newcam = reflected.Other2This (reflRefrPlane);
    00499               reflView->SetClipPlane (reflRefrPlane_newcam);
    00500
    00501               csRef<iTextureHandle> tex;
    00502               csRef<iTextureHandle> texDepth;
    00503               if (usesReflTex)
    00504               {
    00505                 tex =
    00506                   persist.texCache.QueryUnusedTexture (txt_w_refl, txt_h_refl);
    00507               }
    00508               if (usesReflDepthTex)
    00509               {
    00510                 texDepth =
    00511                   persist.texCacheDepth.QueryUnusedTexture (txt_w_refl, txt_h_refl);
    00512               }
    00513
    00514               // Set up context for reflection, clipped to plane
    00515               reflView->SetViewDimensions (txt_w_refl, txt_h_refl);
    00516               csRef<iClipper2D> newView;
    00517               newView.AttachNew (new csBoxClipper (clipBoxRefl));
    00518               reflView->SetClipper (newView);
    00519
    00520               reflCtx = renderTree.CreateContext (reflView);
    00521               reflCtx->renderTargets[rtaColor0].texHandle = tex;
    00522               reflCtx->renderTargets[rtaDepth].texHandle = texDepth;
    00523               reflCtx->drawFlags = CSDRAW_CLEARSCREEN | CSDRAW_CLEARZBUFFER
    00524                 | CSDRAW_NOCLIPCLEAR;
    00525               reflCtx->shadervars = meshReflectRefract.clipPlaneReflContext;
    00526
    00527               if (meshReflectRefract.reflectSV)
    00528               {
    00529                 svReflection = meshReflectRefract.reflectSV;
    00530               }
    00531               else
    00532               {
    00533                 svReflection.AttachNew (new csShaderVariable (
    00534                   persist.svTexPlaneRefl));
    00535                 meshReflectRefract.reflectSV = svReflection;
    00536               }
    00537               svReflection->SetValue (tex);
    00538
    00539               if (meshReflectRefract.reflectDepthSV)
    00540               {
    00541                 svReflectionDepth = meshReflectRefract.reflectDepthSV;
    00542               }
    00543               else
    00544               {
    00545                 svReflectionDepth.AttachNew (new csShaderVariable (
    00546                   persist.svTexPlaneReflDepth));
    00547                 meshReflectRefract.reflectDepthSV = svReflectionDepth;
    00548               }
    00549               svReflectionDepth->SetValue (texDepth);
    00550
    00551               if (renderTree.IsDebugFlagEnabled (persist.dbgReflRefrTex))
    00552               {
    00553                 float dbgAspect = (float)txt_w_refl/(float)txt_h_refl;
    00554                 renderTree.AddDebugTexture (tex, dbgAspect);
    00555                 renderTree.AddDebugTexture (texDepth, dbgAspect);
    00556               }
    00557             }
    00558             else
    00559             {
    00560               svReflection = meshReflectRefract.reflectSV;
    00561               svReflectionDepth = meshReflectRefract.reflectDepthSV;
    00562
    00563               if (renderTree.IsDebugFlagEnabled (persist.dbgReflRefrTex)
    00564                   && doRender)
    00565               {
    00566                 float dbgAspect = (float)txt_w_refl/(float)txt_h_refl;
    00567                 iTextureHandle* texh = 0;
    00568                 if (svReflection.IsValid()) svReflection->GetValue (texh);
    00569                 renderTree.AddDebugTexture (texh, dbgAspect);
    00570                 texh = 0;
    00571                 if (svReflectionDepth.IsValid()) svReflectionDepth->GetValue (texh);
    00572                 renderTree.AddDebugTexture (texh, dbgAspect);
    00573               }
    00574             }
    00575
    00576             // Attach reflection texture to mesh
    00577             localStack[persist.svTexPlaneRefl] = svReflection;
    00578             localStack[persist.svTexPlaneReflDepth] = svReflectionDepth;
    00579             localStack[persist.svReflXform] = persist.reflXformSV;
    00580           }
    00581
    00582           if (usesRefrTex || usesRefrDepthTex)
    00583           {
    00584             csRef<csShaderVariable> svRefraction;
    00585             csRef<csShaderVariable> svRefractionDepth;
    00586
    00587             if (needRefrTex && doRender)
    00588             {
    00589               // Set up context for refraction, clipped to plane
    00590
    00591               // Create a new view
    00592               csRef<CS::RenderManager::RenderView> refrView;
    00593               /* Keep old camera to allow shadow map caching  */
    00594               refrView = renderTree.GetPersistentData().renderViews.CreateRenderView (rview, true);
    00595
    00596               csRef<iTextureHandle> tex;
    00597               csRef<iTextureHandle> texDepth;
    00598               if (usesRefrTex)
    00599               {
    00600                 tex =
    00601                   persist.texCache.QueryUnusedTexture (txt_w_refr, txt_h_refr);
    00602               }
    00603               if (usesRefrDepthTex)
    00604               {
    00605                 texDepth =
    00606                   persist.texCacheDepth.QueryUnusedTexture (txt_w_refr, txt_h_refr);
    00607               }
    00608
    00609               // Set up context for reflection, clipped to plane
    00610               refrView->SetViewDimensions (txt_w_refr, txt_h_refr);
    00611               csRef<iClipper2D> newView;
    00612               newView.AttachNew (new csBoxClipper (clipBoxRefr));
    00613               refrView->SetClipper (newView);
    00614               CS::Utility::MeshFilter meshFilter;
    00615               meshFilter.AddFilterMesh (mesh.meshWrapper);
    00616               refrView->SetMeshFilter(meshFilter);
    00617               refrView->SetClipPlane (reflRefrPlane_cam.Inverse ());
    00618
    00619               refrCtx = renderTree.CreateContext (refrView);
    00620               refrCtx->renderTargets[rtaColor0].texHandle = tex;
    00621               refrCtx->renderTargets[rtaDepth].texHandle = texDepth;
    00622               refrCtx->drawFlags = CSDRAW_CLEARSCREEN | CSDRAW_CLEARZBUFFER
    00623                 | CSDRAW_NOCLIPCLEAR;
    00624               refrCtx->shadervars = meshReflectRefract.clipPlaneRefrContext;
    00625
    00626               // Attach refraction texture to mesh
    00627               if (meshReflectRefract.refractSV)
    00628               {
    00629                 svRefraction = meshReflectRefract.refractSV;
    00630               }
    00631               else
    00632               {
    00633                 svRefraction.AttachNew (new csShaderVariable (
    00634                   persist.svTexPlaneRefr));
    00635                 meshReflectRefract.refractSV = svRefraction;
    00636               }
    00637               svRefraction->SetValue (tex);
    00638
    00639               if (meshReflectRefract.refractDepthSV)
    00640               {
    00641                 svRefractionDepth = meshReflectRefract.refractDepthSV;
    00642               }
    00643               else
    00644               {
    00645                 svRefractionDepth.AttachNew (new csShaderVariable (
    00646                   persist.svTexPlaneRefrDepth));
    00647                 meshReflectRefract.refractDepthSV = svRefractionDepth;
    00648               }
    00649               svRefractionDepth->SetValue (texDepth);
    00650
    00651               if (renderTree.IsDebugFlagEnabled (persist.dbgReflRefrTex))
    00652               {
    00653                 float dbgAspect = (float)txt_w_refr/(float)txt_h_refr;
    00654                 renderTree.AddDebugTexture (tex, dbgAspect);
    00655                 renderTree.AddDebugTexture (texDepth, dbgAspect);
    00656               }
    00657             }
    00658             else
    00659             {
    00660               svRefraction = meshReflectRefract.refractSV;
    00661               svRefractionDepth = meshReflectRefract.refractDepthSV;
    00662
    00663               if (renderTree.IsDebugFlagEnabled (persist.dbgReflRefrTex)
    00664                   && doRender)
    00665               {
    00666                 float dbgAspect = (float)txt_w_refl/(float)txt_h_refl;
    00667                 iTextureHandle* texh = 0;
    00668                 if (svRefraction.IsValid()) svRefraction->GetValue (texh);
    00669                 renderTree.AddDebugTexture (texh, dbgAspect);
    00670                 texh = 0;
    00671                 if (svRefractionDepth.IsValid()) svRefractionDepth->GetValue (texh);
    00672                 renderTree.AddDebugTexture (texh, dbgAspect);
    00673               }
    00674             }
    00675
    00676             // Attach refraction texture to mesh
    00677             localStack[persist.svTexPlaneRefr] = svRefraction;
    00678             localStack[persist.svTexPlaneRefrDepth] = svRefractionDepth;
    00679             localStack[persist.svRefrXform] = persist.refrXformSV;
    00680           }
    00681           if ((needReflTex || needRefrTex) && doRender)
    00682           {
    00683             meshReflectRefract.lastUpdate = currentTicks;
    00684             meshReflectRefract.lastUpdateFrame = persist.currentFrame;
    00685             meshReflectRefract.lastCamera = cam->GetTransform();
    00686             persist.updatesThisFrame++;
    00687           }
    00688
    00689           // Setup the new contexts
    00690           if (reflCtx) contextFunctionRefl (*reflCtx);
    00691           if (refrCtx) contextFunctionRefr (*refrCtx);
    00692         }
    00693       protected:
    00694         ContextSetupReflect& contextFunctionRefl;
    00695         ContextSetupRefract& contextFunctionRefr;
    00696       };
    00697
    00698     } // namespace AutoFX
    00699   } // namespace RenderManager
    00700 } // namespace CS
    00701
    00702 #endif // __CS_CSPLUGINCOMMON_RENDERMANAGER_AUTOFX_REFLREFR_H__