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__
Generated for Crystal Space 2.0 by doxygen 1.6.1