void PlaneReflector::updateReflection( const ReflectParams ¶ms ) { PROFILE_SCOPE(PlaneReflector_updateReflection); GFXDEBUGEVENT_SCOPE( PlaneReflector_updateReflection, ColorI::WHITE ); mIsRendering = true; S32 texDim = mDesc->texSize; texDim = getMax( texDim, 32 ); // Protect against the reflection texture being bigger // than the current game back buffer. texDim = getMin( texDim, params.viewportExtent.x ); texDim = getMin( texDim, params.viewportExtent.y ); bool texResize = ( texDim != mLastTexSize ); mLastTexSize = texDim; const Point2I texSize( texDim, texDim ); if ( texResize || reflectTex.isNull() || reflectTex->getFormat() != REFLECTMGR->getReflectFormat() ) reflectTex = REFLECTMGR->allocRenderTarget( texSize ); GFXTexHandle depthBuff = LightShadowMap::_getDepthTarget( texSize.x, texSize.y ); // store current matrices GFXTransformSaver saver; Point2I viewport(params.viewportExtent); if(GFX->getCurrentRenderStyle() == GFXDevice::RS_StereoSideBySide) { viewport.x *= 0.5f; } F32 aspectRatio = F32( viewport.x ) / F32( viewport.y ); Frustum frustum; frustum.set(false, params.query->fov, aspectRatio, params.query->nearPlane, params.query->farPlane); // Manipulate the frustum for tiled screenshots const bool screenShotMode = gScreenShot && gScreenShot->isPending(); if ( screenShotMode ) gScreenShot->tileFrustum( frustum ); GFX->setFrustum( frustum ); // Store the last view info for scoring. mLastDir = params.query->cameraMatrix.getForwardVector(); mLastPos = params.query->cameraMatrix.getPosition(); setGFXMatrices( params.query->cameraMatrix ); // Adjust the detail amount F32 detailAdjustBackup = TSShapeInstance::smDetailAdjust; TSShapeInstance::smDetailAdjust *= mDesc->detailAdjust; if(reflectTarget.isNull()) reflectTarget = GFX->allocRenderToTextureTarget(); reflectTarget->attachTexture( GFXTextureTarget::Color0, reflectTex ); reflectTarget->attachTexture( GFXTextureTarget::DepthStencil, depthBuff ); GFX->pushActiveRenderTarget(); GFX->setActiveRenderTarget( reflectTarget ); U32 objTypeFlag = -1; SceneCameraState reflectCameraState = SceneCameraState::fromGFX(); LIGHTMGR->registerGlobalLights( &reflectCameraState.getFrustum(), false ); // Since we can sometime be rendering a reflection for 1 or 2 frames before // it gets updated do to the lag associated with getting the results from // a HOQ we can sometimes see into parts of the reflection texture that // have nothing but clear color ( eg. under the water ). // To make this look less crappy use the ambient color of the sun. // // In the future we may want to fix this instead by having the scatterSky // render a skirt or something in its lower half. // ColorF clearColor = gClientSceneGraph->getAmbientLightColor(); GFX->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, clearColor, 1.0f, 0 ); if(GFX->getCurrentRenderStyle() == GFXDevice::RS_StereoSideBySide) { // Store previous values RectI originalVP = GFX->getViewport(); Point2F projOffset = GFX->getCurrentProjectionOffset(); Point3F eyeOffset = GFX->getStereoEyeOffset(); // Render left half of display RectI leftVP = originalVP; leftVP.extent.x *= 0.5; GFX->setViewport(leftVP); MatrixF leftWorldTrans(true); leftWorldTrans.setPosition(Point3F(eyeOffset.x, eyeOffset.y, eyeOffset.z)); MatrixF leftWorld(params.query->cameraMatrix); leftWorld.mulL(leftWorldTrans); Frustum gfxFrustum = GFX->getFrustum(); gfxFrustum.setProjectionOffset(Point2F(projOffset.x, projOffset.y)); GFX->setFrustum(gfxFrustum); setGFXMatrices( leftWorld ); SceneCameraState cameraStateLeft = SceneCameraState::fromGFX(); SceneRenderState renderStateLeft( gClientSceneGraph, SPT_Reflect, cameraStateLeft ); renderStateLeft.setSceneRenderStyle(SRS_SideBySide); renderStateLeft.setSceneRenderField(0); renderStateLeft.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial ); renderStateLeft.setDiffuseCameraTransform( params.query->cameraMatrix ); renderStateLeft.disableAdvancedLightingBins(true); gClientSceneGraph->renderSceneNoLights( &renderStateLeft, objTypeFlag ); // Render right half of display RectI rightVP = originalVP; rightVP.extent.x *= 0.5; rightVP.point.x += rightVP.extent.x; GFX->setViewport(rightVP); MatrixF rightWorldTrans(true); rightWorldTrans.setPosition(Point3F(-eyeOffset.x, eyeOffset.y, eyeOffset.z)); MatrixF rightWorld(params.query->cameraMatrix); rightWorld.mulL(rightWorldTrans); gfxFrustum = GFX->getFrustum(); gfxFrustum.setProjectionOffset(Point2F(-projOffset.x, projOffset.y)); GFX->setFrustum(gfxFrustum); setGFXMatrices( rightWorld ); SceneCameraState cameraStateRight = SceneCameraState::fromGFX(); SceneRenderState renderStateRight( gClientSceneGraph, SPT_Reflect, cameraStateRight ); renderStateRight.setSceneRenderStyle(SRS_SideBySide); renderStateRight.setSceneRenderField(1); renderStateRight.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial ); renderStateRight.setDiffuseCameraTransform( params.query->cameraMatrix ); renderStateRight.disableAdvancedLightingBins(true); gClientSceneGraph->renderSceneNoLights( &renderStateRight, objTypeFlag ); // Restore previous values gfxFrustum.clearProjectionOffset(); GFX->setFrustum(gfxFrustum); GFX->setViewport(originalVP); } else { SceneRenderState reflectRenderState ( gClientSceneGraph, SPT_Reflect, SceneCameraState::fromGFX() ); reflectRenderState.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial ); reflectRenderState.setDiffuseCameraTransform( params.query->cameraMatrix ); reflectRenderState.disableAdvancedLightingBins(true); gClientSceneGraph->renderSceneNoLights( &reflectRenderState, objTypeFlag ); } LIGHTMGR->unregisterAllLights(); // Clean up. reflectTarget->resolve(); GFX->popActiveRenderTarget(); // Restore detail adjust amount. TSShapeInstance::smDetailAdjust = detailAdjustBackup; mIsRendering = false; }
void CubeReflector::updateFace( const ReflectParams ¶ms, U32 faceidx ) { GFXDEBUGEVENT_SCOPE( CubeReflector_UpdateFace, ColorI::WHITE ); // store current matrices GFXTransformSaver saver; // set projection to 90 degrees vertical and horizontal F32 left, right, top, bottom; MathUtils::makeFrustum( &left, &right, &top, &bottom, M_HALFPI_F, 1.0f, mDesc->nearDist ); GFX->setFrustum( left, right, bottom, top, mDesc->nearDist, mDesc->farDist ); // We don't use a special clipping projection, but still need to initialize // this for objects like SkyBox which will use it during a reflect pass. gClientSceneGraph->setNonClipProjection( GFX->getProjectionMatrix() ); // Standard view that will be overridden below. VectorF vLookatPt(0.0f, 0.0f, 0.0f), vUpVec(0.0f, 0.0f, 0.0f), vRight(0.0f, 0.0f, 0.0f); switch( faceidx ) { case 0 : // D3DCUBEMAP_FACE_POSITIVE_X: vLookatPt = VectorF( 1.0f, 0.0f, 0.0f ); vUpVec = VectorF( 0.0f, 1.0f, 0.0f ); break; case 1 : // D3DCUBEMAP_FACE_NEGATIVE_X: vLookatPt = VectorF( -1.0f, 0.0f, 0.0f ); vUpVec = VectorF( 0.0f, 1.0f, 0.0f ); break; case 2 : // D3DCUBEMAP_FACE_POSITIVE_Y: vLookatPt = VectorF( 0.0f, 1.0f, 0.0f ); vUpVec = VectorF( 0.0f, 0.0f,-1.0f ); break; case 3 : // D3DCUBEMAP_FACE_NEGATIVE_Y: vLookatPt = VectorF( 0.0f, -1.0f, 0.0f ); vUpVec = VectorF( 0.0f, 0.0f, 1.0f ); break; case 4 : // D3DCUBEMAP_FACE_POSITIVE_Z: vLookatPt = VectorF( 0.0f, 0.0f, 1.0f ); vUpVec = VectorF( 0.0f, 1.0f, 0.0f ); break; case 5: // D3DCUBEMAP_FACE_NEGATIVE_Z: vLookatPt = VectorF( 0.0f, 0.0f, -1.0f ); vUpVec = VectorF( 0.0f, 1.0f, 0.0f ); break; } // create camera matrix VectorF cross = mCross( vUpVec, vLookatPt ); cross.normalizeSafe(); MatrixF matView(true); matView.setColumn( 0, cross ); matView.setColumn( 1, vLookatPt ); matView.setColumn( 2, vUpVec ); matView.setPosition( mObject->getPosition() ); matView.inverse(); GFX->setWorldMatrix(matView); renderTarget->attachTexture( GFXTextureTarget::Color0, cubemap, faceidx ); GFX->setActiveRenderTarget( renderTarget ); GFX->clear( GFXClearStencil | GFXClearTarget | GFXClearZBuffer, gCanvasClearColor, 1.0f, 0 ); SceneRenderState reflectRenderState ( gClientSceneGraph, SPT_Reflect, SceneCameraState::fromGFX() ); reflectRenderState.getMaterialDelegate().bind( REFLECTMGR, &ReflectionManager::getReflectionMaterial ); reflectRenderState.setDiffuseCameraTransform( params.query->cameraMatrix ); reflectRenderState.disableAdvancedLightingBins(true); // render scene LIGHTMGR->registerGlobalLights( &reflectRenderState.getCullingFrustum(), false ); gClientSceneGraph->renderSceneNoLights( &reflectRenderState, mDesc->objectTypeMask ); LIGHTMGR->unregisterAllLights(); // Clean up. renderTarget->resolve(); }