bool Convex::getCollisionInfo(const MatrixF& mat, const Point3F& scale, CollisionList* cList,F32 tol) { PROFILE_SCOPE( Convex_GetCollisionInfo ); // Making these static prevents needless Vector resizing that occurs // in the ConvexFeature constructor. static ConvexFeature fa; static ConvexFeature fb; for ( CollisionStateList* itr = mList.mNext; itr != &mList; itr = itr->mNext) { CollisionState* state = itr->mState; if (state->mLista != itr) state->swap(); if (state->dist <= tol) { fa.reset(); fb.reset(); VectorF v; // The idea is that we need to scale the matrix, so we need to // make a copy of it, before we can pass it in to getFeatures. // This is used to scale us for comparison against the other // convex, which is correctly scaled. MatrixF omat = mat; omat.scale(scale); MatrixF imat = omat; imat.inverse(); imat.mulV(-state->v,&v); getFeatures(omat,v,&fa); imat = state->b->getTransform(); imat.scale(state->b->getScale()); MatrixF bxform = imat; imat.inverse(); imat.mulV(state->v,&v); state->b->getFeatures(bxform,v,&fb); fa.collide(fb,cList,tol); } } return (cList->getCount() != 0); }
void BtBody::applyImpulse( const Point3F &origin, const Point3F &force ) { AssertFatal( mActor, "BtBody::applyImpulse - The actor is null!" ); AssertFatal( isDynamic(), "BtBody::applyImpulse - This call is only for dynamics!" ); // Convert the world position to local MatrixF trans = btCast<MatrixF>( mActor->getCenterOfMassTransform() ); trans.inverse(); Point3F localOrigin( origin ); trans.mulP( localOrigin ); if ( mCenterOfMass ) { Point3F relOrigin( localOrigin ); mCenterOfMass->mulP( relOrigin ); Point3F relForce( force ); mCenterOfMass->mulV( relForce ); mActor->applyImpulse( btCast<btVector3>( relForce ), btCast<btVector3>( relOrigin ) ); } else mActor->applyImpulse( btCast<btVector3>( force ), btCast<btVector3>( localOrigin ) ); if ( !mActor->isActive() ) mActor->activate(); }
MatrixF TSShapeLoader::getLocalNodeMatrix(AppNode* node, F32 t) { MatrixF m1 = node->getNodeTransform(t); // multiply by inverse scale at t=0 MatrixF m10 = node->getNodeTransform(DefaultTime); m1.scale(Point3F(1.0f/m10.getScale().x, 1.0f/m10.getScale().y, 1.0f/m10.getScale().z)); if (node->mParentIndex >= 0) { AppNode *parent = appNodes[node->mParentIndex]; MatrixF m2 = parent->getNodeTransform(t); // multiply by inverse scale at t=0 MatrixF m20 = parent->getNodeTransform(DefaultTime); m2.scale(Point3F(1.0f/m20.getScale().x, 1.0f/m20.getScale().y, 1.0f/m20.getScale().z)); // get local transform by pre-multiplying by inverted parent transform m1 = m2.inverse() * m1; } else if (boundsNode && node != boundsNode) { // make transform relative to bounds node transform at time=t MatrixF mb = boundsNode->getNodeTransform(t); zapScale(mb); m1 = mb.inverse() * m1; } return m1; }
void TSShapeLoader::generateGroundAnimation(TSShape::Sequence& seq, const AppSequence* appSeq) { seq.firstGroundFrame = shape->groundTranslations.size(); seq.numGroundFrames = 0; if (!boundsNode) return; // Check if the bounds node is animated by this sequence seq.numGroundFrames = (S32)((seq.duration + 0.25f/AppGroundFrameRate) * AppGroundFrameRate); seq.flags |= TSShape::MakePath; // Get ground transform at the start of the sequence MatrixF invStartMat = boundsNode->getNodeTransform(appSeq->getStart()); zapScale(invStartMat); invStartMat.inverse(); for (int iFrame = 0; iFrame < seq.numGroundFrames; iFrame++) { F32 time = appSeq->getStart() + seq.duration * iFrame / getMax(1, seq.numGroundFrames - 1); // Determine delta bounds node transform at 't' MatrixF mat = boundsNode->getNodeTransform(time); zapScale(mat); mat = invStartMat * mat; // Add ground transform Quat16 rotation; rotation.set(QuatF(mat)); shape->groundTranslations.push_back(mat.getPosition()); shape->groundRotations.push_back(rotation); } }
void Sun::_renderCorona( ObjectRenderInst *ri, SceneState *state, BaseMatInstance *overrideMat ) { Point3F sunlightPosition = state->getCameraPosition() - mLight->getDirection() * state->getFarPlane() * 0.9f; // Calculate Billboard Radius (in world units) to be constant, independent of distance. // Takes into account distance, viewport size, and specified size in editor F32 BBRadius = (((sunlightPosition - state->getCameraPosition()).len()) / (GFX->getViewport().extent.x / 640.0)) / 2; BBRadius *= mCoronaScale; GFXTransformSaver saver; if ( state->isReflectPass() ) GFX->setProjectionMatrix( gClientSceneGraph->getNonClipProjection() ); GFX->setStateBlock(mCoronaSB); // Initialize points with basic info Point3F points[4]; points[0] = Point3F(-BBRadius, 0.0, -BBRadius); points[1] = Point3F( BBRadius, 0.0, -BBRadius); points[2] = Point3F( BBRadius, 0.0, BBRadius); points[3] = Point3F(-BBRadius, 0.0, BBRadius); // Get info we need to adjust points MatrixF camView = GFX->getWorldMatrix(); camView.inverse(); // Finalize points for(int i = 0; i < 4; i++) { // align with camera camView.mulV(points[i]); // offset points[i] += sunlightPosition; } // Draw it if ( mCoronaUseLightColor ) PrimBuild::color(mLightColor); else PrimBuild::color(mCoronaTint); GFX->setTexture(0, mCoronaTexture); PrimBuild::begin( GFXTriangleFan, 4 ); PrimBuild::texCoord2f(0, 0); PrimBuild::vertex3fv(points[0]); PrimBuild::texCoord2f(1, 0); PrimBuild::vertex3fv(points[1]); PrimBuild::texCoord2f(1, 1); PrimBuild::vertex3fv(points[2]); PrimBuild::texCoord2f(0, 1); PrimBuild::vertex3fv(points[3]); PrimBuild::end(); }
void PlaneReflector::setGFXMatrices( const MatrixF &camTrans ) { if ( objectSpace ) { // set up camera transform relative to object MatrixF invObjTrans = mObject->getRenderTransform(); invObjTrans.inverse(); MatrixF relCamTrans = invObjTrans * camTrans; MatrixF camReflectTrans = getCameraReflection( relCamTrans ); MatrixF camTrans = mObject->getRenderTransform() * camReflectTrans; camTrans.inverse(); GFX->setWorldMatrix( camTrans ); // use relative reflect transform for modelview since clip plane is in object space camTrans = camReflectTrans; camTrans.inverse(); // set new projection matrix gClientSceneGraph->setNonClipProjection( (MatrixF&) GFX->getProjectionMatrix() ); MatrixF clipProj = getFrustumClipProj( camTrans ); GFX->setProjectionMatrix( clipProj ); } else { // set world mat from new camera view MatrixF camReflectTrans = getCameraReflection( camTrans ); camReflectTrans.inverse(); GFX->setWorldMatrix( camReflectTrans ); // set new projection matrix gClientSceneGraph->setNonClipProjection( (MatrixF&) GFX->getProjectionMatrix() ); MatrixF clipProj = getFrustumClipProj( camReflectTrans ); GFX->setProjectionMatrix( clipProj ); } }
SceneCameraState SceneCameraState::fromGFXWithViewport( const RectI& viewport ) { const MatrixF& world = GFX->getWorldMatrix(); MatrixF camera = world; camera.inverse(); Frustum frustum = GFX->getFrustum(); frustum.setTransform( camera ); return SceneCameraState( viewport, frustum, world, GFX->getProjectionMatrix() ); }
GLint gluUnProject( GLdouble winx, GLdouble winy, GLdouble winz, const F64 *model, const F64 * proj, const GLint * vp, F64 * x, F64 * y, F64 * z ) { Vector4F v = Vector4F( 2.0f*(winx-vp[0])/vp[2] - 1.0f, 2.0f*(winy-vp[1])/vp[2] - 1.0f, 2.0f*vp[2] - 1.0f, 1.0f ); MatrixF pmat = MatrixF( false ); for (int i=0; i<16; i++) { ((F32*)pmat)[i] = (float)proj[i]; } MatrixF mmat = MatrixF( false ); for (int i=0; i<16; i++) { ((F32*)mmat)[i] = (float)model[i]; } mmat = pmat.mul(mmat); mmat = mmat.inverse(); mmat.mul( v ); *x = v.x; *y = v.y; *z = v.z; int glError; glError = TEST_FOR_OPENGL_ERRORS return GL_TRUE; }
void TSShapeInstance::addPath(TSThread *gt, F32 start, F32 end, MatrixF *mat) { // never get here while in transition... AssertFatal(!gt->transitionData.inTransition,"TSShapeInstance::addPath"); if (!mat) mat = &mGroundTransform; MatrixF startInvM; gt->getGround(start,&startInvM); startInvM.inverse(); MatrixF endM; gt->getGround(end,&endM); MatrixF addM; addM.mul(startInvM,endM); endM.mul(*mat,addM); *mat = endM; }
//---------------------------------------------------------------------------- AwTextureTarget *AwShape::processAwesomiumHit (const Point3F &start, const Point3F &end) { if (!mTextureTarget) { return NULL; } Point3F localStart, localEnd; MatrixF mat = getTransform(); mat.scale (Point3F (getScale ())); mat.inverse (); mat.mulP (start, &localStart); mat.mulP (end, &localEnd); RayInfo info; info.generateTexCoord = true; if (!mShapeInstance || !mShapeInstance->castRayOpcode (0, localStart, localEnd, &info)) { return NULL; } if (info.texCoord.x != -1 && info.texCoord.y != -1 && info.material == mMatInstance) { Point2I pnt (info.texCoord.x * mTextureTarget->getResolution ().x, info.texCoord.y * mTextureTarget->getResolution ().y); AwManager::sCursor->setPosition (pnt); if (mIsMouseDown) { mTextureTarget->injectMouseDown (); } else { mTextureTarget->injectMouseUp (); } return mTextureTarget; } return NULL; }
void ProcessedFFMaterial::_setSecondaryLightInfo(const MatrixF &_objTrans, LightInfo* light) { // set object transform MatrixF objTrans = _objTrans; objTrans.inverse(); // fill in secondary light //------------------------- GFXLightInfo xlatedLight; light->setGFXLight(&xlatedLight); Point3F lightPos = light->getPosition(); Point3F lightDir = light->getDirection(); objTrans.mulP(lightPos); objTrans.mulV(lightDir); xlatedLight.mPos = lightPos; xlatedLight.mDirection = lightDir; GFX->setLight(1, &xlatedLight); }
void ProcessedFFMaterial::_setPrimaryLightInfo(const MatrixF &_objTrans, LightInfo* light, U32 pass) { // Just in case GFX->setGlobalAmbientColor(ColorF(0.0f, 0.0f, 0.0f, 1.0f)); if ( light->getType() == LightInfo::Ambient ) { // Ambient light GFX->setGlobalAmbientColor( light->getAmbient() ); return; } GFX->setLight(0, NULL); GFX->setLight(1, NULL); // This is a quick hack that lets us use FF lights GFXLightMaterial lightMat; lightMat.ambient = ColorF(1.0f, 1.0f, 1.0f, 1.0f); lightMat.diffuse = ColorF(1.0f, 1.0f, 1.0f, 1.0f); lightMat.emissive = ColorF(0.0f, 0.0f, 0.0f, 0.0f); lightMat.specular = ColorF(0.0f, 0.0f, 0.0f, 0.0f); lightMat.shininess = 128.0f; GFX->setLightMaterial(lightMat); // set object transform MatrixF objTrans = _objTrans; objTrans.inverse(); // fill in primary light //------------------------- GFXLightInfo xlatedLight; light->setGFXLight(&xlatedLight); Point3F lightPos = light->getPosition(); Point3F lightDir = light->getDirection(); objTrans.mulP(lightPos); objTrans.mulV(lightDir); xlatedLight.mPos = lightPos; xlatedLight.mDirection = lightDir; GFX->setLight(0, &xlatedLight); }
bool ForestItem::castRay( const Point3F &start, const Point3F &end, RayInfo *outInfo, bool rendered ) const { if ( !mWorldBox.collideLine( start, end ) ) return false; Point3F s, e; MatrixF mat = getTransform(); mat.scale( Point3F(mScale) ); mat.inverse(); mat.mulP( start, &s ); mat.mulP( end, &e ); TSForestItemData *data = (TSForestItemData*)mDataBlock; TSShapeInstance *si = data->getShapeInstance(); if ( !si ) return false; if ( rendered ) { // Always raycast against detail level zero // because it makes lots of things easier. if ( !si->castRayRendered( s, e, outInfo, 0 ) ) return false; if ( outInfo->userData != NULL ) *(ForestItem*)(outInfo->userData) = *this; return true; } RayInfo shortest; shortest.t = 1e8; bool gotMatch = false; S32 detail; const Vector<S32> &details = data->getLOSDetails(); for (U32 i = 0; i < details.size(); i++) { detail = details[i]; if (detail != -1) { //si->animate(data->mLOSDetails[i]); if ( si->castRayOpcode( detail, s, e, outInfo ) ) { if (outInfo->t < shortest.t) { gotMatch = true; shortest = *outInfo; } } } } if ( !gotMatch ) return false; // Copy out the shortest time... *outInfo = shortest; if ( outInfo->userData != NULL ) *(ForestItem*)(outInfo->userData) = *this; return true; }
void EditTSCtrl::renderCameraAxis() { GFXDEBUGEVENT_SCOPE( Editor_renderCameraAxis, ColorI::WHITE ); static MatrixF sRotMat(EulerF( (M_PI_F / -2.0f), 0.0f, 0.0f)); MatrixF camMat = mLastCameraQuery.cameraMatrix; camMat.mul(sRotMat); camMat.inverse(); MatrixF axis; axis.setColumn(0, Point3F(1, 0, 0)); axis.setColumn(1, Point3F(0, 0, 1)); axis.setColumn(2, Point3F(0, -1, 0)); axis.mul(camMat); Point3F forwardVec, upVec, rightVec; axis.getColumn( 2, &forwardVec ); axis.getColumn( 1, &upVec ); axis.getColumn( 0, &rightVec ); Point2I pos = getPosition(); F32 offsetx = pos.x + 20.0; F32 offsety = pos.y + getExtent().y - 42.0; // Take the status bar into account F32 scale = 15.0; // Generate correct drawing order ColorI c1(255,0,0); ColorI c2(0,255,0); ColorI c3(0,0,255); ColorI tc; Point3F *p1, *p2, *p3, *tp; p1 = &rightVec; p2 = &upVec; p3 = &forwardVec; if(p3->y > p2->y) { tp = p2; tc = c2; p2 = p3; c2 = c3; p3 = tp; c3 = tc; } if(p2->y > p1->y) { tp = p1; tc = c1; p1 = p2; c1 = c2; p2 = tp; c2 = tc; } PrimBuild::begin( GFXLineList, 6 ); //*** Axis 1 PrimBuild::color(c1); PrimBuild::vertex3f(offsetx, offsety, 0); PrimBuild::vertex3f(offsetx+p1->x*scale, offsety-p1->z*scale, 0); //*** Axis 2 PrimBuild::color(c2); PrimBuild::vertex3f(offsetx, offsety, 0); PrimBuild::vertex3f(offsetx+p2->x*scale, offsety-p2->z*scale, 0); //*** Axis 3 PrimBuild::color(c3); PrimBuild::vertex3f(offsetx, offsety, 0); PrimBuild::vertex3f(offsetx+p3->x*scale, offsety-p3->z*scale, 0); PrimBuild::end(); }
void SingleLightShadowMap::_render( RenderPassManager* renderPass, const SceneRenderState *diffuseState ) { PROFILE_SCOPE(SingleLightShadowMap_render); const LightMapParams *lmParams = mLight->getExtended<LightMapParams>(); const bool bUseLightmappedGeometry = lmParams ? !lmParams->representedInLightmap || lmParams->includeLightmappedGeometryInShadow : true; const U32 texSize = getBestTexSize(); if ( mShadowMapTex.isNull() || mTexSize != texSize ) { mTexSize = texSize; mShadowMapTex.set( mTexSize, mTexSize, ShadowMapFormat, &ShadowMapProfile, "SingleLightShadowMap" ); } GFXFrustumSaver frustSaver; GFXTransformSaver saver; MatrixF lightMatrix; calcLightMatrices( lightMatrix, diffuseState->getCameraFrustum() ); lightMatrix.inverse(); GFX->setWorldMatrix(lightMatrix); const MatrixF& lightProj = GFX->getProjectionMatrix(); mWorldToLightProj = lightProj * lightMatrix; // Render the shadowmap! GFX->pushActiveRenderTarget(); mTarget->attachTexture( GFXTextureTarget::Color0, mShadowMapTex ); mTarget->attachTexture( GFXTextureTarget::DepthStencil, _getDepthTarget( mShadowMapTex->getWidth(), mShadowMapTex->getHeight() ) ); GFX->setActiveRenderTarget(mTarget); GFX->clear(GFXClearStencil | GFXClearZBuffer | GFXClearTarget, ColorI(255,255,255), 1.0f, 0); SceneManager* sceneManager = diffuseState->getSceneManager(); SceneRenderState shadowRenderState ( sceneManager, SPT_Shadow, SceneCameraState::fromGFXWithViewport( diffuseState->getViewport() ), renderPass ); shadowRenderState.getMaterialDelegate().bind( this, &LightShadowMap::getShadowMaterial ); shadowRenderState.renderNonLightmappedMeshes( true ); shadowRenderState.renderLightmappedMeshes( bUseLightmappedGeometry ); shadowRenderState.setDiffuseCameraTransform( diffuseState->getCameraTransform() ); shadowRenderState.setWorldToScreenScale( diffuseState->getWorldToScreenScale() ); sceneManager->renderSceneNoLights( &shadowRenderState, SHADOW_TYPEMASK ); _debugRender( &shadowRenderState ); mTarget->resolve(); GFX->popActiveRenderTarget(); }
void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect) { // Save the current transforms so we can restore // it for child control rendering below. GFXTransformSaver saver; if(!processCameraQuery(&mLastCameraQuery)) { // We have no camera, but render the GUI children // anyway. This makes editing GuiTSCtrl derived // controls easier in the GuiEditor. renderChildControls( offset, updateRect ); return; } // Set up the appropriate render style U32 prevRenderStyle = GFX->getCurrentRenderStyle(); Point2F prevProjectionOffset = GFX->getCurrentProjectionOffset(); Point3F prevEyeOffset = GFX->getStereoEyeOffset(); if(mRenderStyle == RenderStyleStereoSideBySide) { GFX->setCurrentRenderStyle(GFXDevice::RS_StereoSideBySide); GFX->setCurrentProjectionOffset(mLastCameraQuery.projectionOffset); GFX->setStereoEyeOffset(mLastCameraQuery.eyeOffset); } else { GFX->setCurrentRenderStyle(GFXDevice::RS_Standard); } if ( mReflectPriority > 0 ) { // Get the total reflection priority. F32 totalPriority = 0; for ( U32 i=0; i < smAwakeTSCtrls.size(); i++ ) if ( smAwakeTSCtrls[i]->isVisible() ) totalPriority += smAwakeTSCtrls[i]->mReflectPriority; REFLECTMGR->update( mReflectPriority / totalPriority, getExtent(), mLastCameraQuery ); } if(mForceFOV != 0) mLastCameraQuery.fov = mDegToRad(mForceFOV); if(mCameraZRot) { MatrixF rotMat(EulerF(0, 0, mDegToRad(mCameraZRot))); mLastCameraQuery.cameraMatrix.mul(rotMat); } // set up the camera and viewport stuff: F32 wwidth; F32 wheight; F32 renderWidth = (mRenderStyle == RenderStyleStereoSideBySide) ? F32(getWidth())*0.5f : F32(getWidth()); F32 renderHeight = F32(getHeight()); F32 aspectRatio = renderWidth / renderHeight; // Use the FOV to calculate the viewport height scale // then generate the width scale from the aspect ratio. if(!mLastCameraQuery.ortho) { wheight = mLastCameraQuery.nearPlane * mTan(mLastCameraQuery.fov / 2.0f); wwidth = aspectRatio * wheight; } else { wheight = mLastCameraQuery.fov; wwidth = aspectRatio * wheight; } F32 hscale = wwidth * 2.0f / renderWidth; F32 vscale = wheight * 2.0f / renderHeight; Frustum frustum; if(mRenderStyle == RenderStyleStereoSideBySide) { F32 left = 0.0f * hscale - wwidth; F32 right = renderWidth * hscale - wwidth; F32 top = wheight - vscale * 0.0f; F32 bottom = wheight - vscale * renderHeight; frustum.set( mLastCameraQuery.ortho, left, right, top, bottom, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane ); } else { F32 left = (updateRect.point.x - offset.x) * hscale - wwidth; F32 right = (updateRect.point.x + updateRect.extent.x - offset.x) * hscale - wwidth; F32 top = wheight - vscale * (updateRect.point.y - offset.y); F32 bottom = wheight - vscale * (updateRect.point.y + updateRect.extent.y - offset.y); frustum.set( mLastCameraQuery.ortho, left, right, top, bottom, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane ); } // Manipulate the frustum for tiled screenshots const bool screenShotMode = gScreenShot && gScreenShot->isPending(); if ( screenShotMode ) { gScreenShot->tileFrustum( frustum ); GFX->setViewMatrix(MatrixF::Identity); } RectI tempRect = updateRect; #ifdef TORQUE_OS_MAC Point2I screensize = getRoot()->getWindowSize(); tempRect.point.y = screensize.y - (tempRect.point.y + tempRect.extent.y); #endif GFX->setViewport( tempRect ); // Clear the zBuffer so GUI doesn't hose object rendering accidentally GFX->clear( GFXClearZBuffer , ColorI(20,20,20), 1.0f, 0 ); GFX->setFrustum( frustum ); if(mLastCameraQuery.ortho) { mOrthoWidth = frustum.getWidth(); mOrthoHeight = frustum.getHeight(); } // We're going to be displaying this render at size of this control in // pixels - let the scene know so that it can calculate e.g. reflections // correctly for that final display result. gClientSceneGraph->setDisplayTargetResolution(getExtent()); // Set the GFX world matrix to the world-to-camera transform, but don't // change the cameraMatrix in mLastCameraQuery. This is because // mLastCameraQuery.cameraMatrix is supposed to contain the camera-to-world // transform. In-place invert would save a copy but mess up any GUIs that // depend on that value. MatrixF worldToCamera = mLastCameraQuery.cameraMatrix; worldToCamera.inverse(); GFX->setWorldMatrix( worldToCamera ); mSaveProjection = GFX->getProjectionMatrix(); mSaveModelview = GFX->getWorldMatrix(); mSaveViewport = updateRect; mSaveWorldToScreenScale = GFX->getWorldToScreenScale(); mSaveFrustum = GFX->getFrustum(); mSaveFrustum.setTransform( mLastCameraQuery.cameraMatrix ); // Set the default non-clip projection as some // objects depend on this even in non-reflect cases. gClientSceneGraph->setNonClipProjection( mSaveProjection ); // Give the post effect manager the worldToCamera, and cameraToScreen matrices PFXMGR->setFrameMatrices( mSaveModelview, mSaveProjection ); renderWorld(updateRect); DebugDrawer::get()->render(); // Restore the previous matrix state before // we begin rendering the child controls. saver.restore(); // Restore the render style and any stereo parameters GFX->setCurrentRenderStyle(prevRenderStyle); GFX->setCurrentProjectionOffset(prevProjectionOffset); GFX->setStereoEyeOffset(prevEyeOffset); // Allow subclasses to render 2D elements. GFX->setClipRect(updateRect); renderGui( offset, updateRect ); renderChildControls(offset, updateRect); smFrameCount++; }
void GuiTSCtrl::onRender(Point2I offset, const RectI &updateRect) { // Save the current transforms so we can restore // it for child control rendering below. GFXTransformSaver saver; bool renderingToTarget = false; if(!processCameraQuery(&mLastCameraQuery)) { // We have no camera, but render the GUI children // anyway. This makes editing GuiTSCtrl derived // controls easier in the GuiEditor. renderChildControls( offset, updateRect ); return; } GFXTargetRef origTarget = GFX->getActiveRenderTarget(); // Set up the appropriate render style U32 prevRenderStyle = GFX->getCurrentRenderStyle(); Point2F prevProjectionOffset = GFX->getCurrentProjectionOffset(); Point2I renderSize = getExtent(); if(mRenderStyle == RenderStyleStereoSideBySide) { GFX->setCurrentRenderStyle(GFXDevice::RS_StereoSideBySide); GFX->setCurrentProjectionOffset(mLastCameraQuery.projectionOffset); GFX->setStereoEyeOffsets(mLastCameraQuery.eyeOffset); if (!mLastCameraQuery.hasStereoTargets) { // Need to calculate our current viewport here mLastCameraQuery.stereoViewports[0] = updateRect; mLastCameraQuery.stereoViewports[0].extent.x /= 2; mLastCameraQuery.stereoViewports[1] = mLastCameraQuery.stereoViewports[0]; mLastCameraQuery.stereoViewports[1].point.x += mLastCameraQuery.stereoViewports[1].extent.x; } if (!mLastCameraQuery.hasFovPort) { // Need to make our own fovPort mLastCameraQuery.fovPort[0] = CalculateFovPortForCanvas(mLastCameraQuery.stereoViewports[0], mLastCameraQuery); mLastCameraQuery.fovPort[1] = CalculateFovPortForCanvas(mLastCameraQuery.stereoViewports[1], mLastCameraQuery); } GFX->setStereoFovPort(mLastCameraQuery.fovPort); // NOTE: this specifies fov for BOTH eyes GFX->setSteroViewports(mLastCameraQuery.stereoViewports); GFX->setStereoTargets(mLastCameraQuery.stereoTargets); MatrixF myTransforms[2]; if (smUseLatestDisplayTransform) { // Use the view matrix determined from the display device myTransforms[0] = mLastCameraQuery.eyeTransforms[0]; myTransforms[1] = mLastCameraQuery.eyeTransforms[1]; } else { // Use the view matrix determined from the control object myTransforms[0] = mLastCameraQuery.cameraMatrix; myTransforms[1] = mLastCameraQuery.cameraMatrix; QuatF qrot = mLastCameraQuery.cameraMatrix; Point3F pos = mLastCameraQuery.cameraMatrix.getPosition(); Point3F rotEyePos; myTransforms[0].setPosition(pos + qrot.mulP(mLastCameraQuery.eyeOffset[0], &rotEyePos)); myTransforms[1].setPosition(pos + qrot.mulP(mLastCameraQuery.eyeOffset[1], &rotEyePos)); } GFX->setStereoEyeTransforms(myTransforms); // Allow render size to originate from the render target if (mLastCameraQuery.stereoTargets[0]) { renderSize = mLastCameraQuery.stereoViewports[0].extent; renderingToTarget = true; } } else { GFX->setCurrentRenderStyle(GFXDevice::RS_Standard); } if ( mReflectPriority > 0 ) { // Get the total reflection priority. F32 totalPriority = 0; for ( U32 i=0; i < smAwakeTSCtrls.size(); i++ ) if ( smAwakeTSCtrls[i]->isVisible() ) totalPriority += smAwakeTSCtrls[i]->mReflectPriority; REFLECTMGR->update( mReflectPriority / totalPriority, getExtent(), mLastCameraQuery ); } if(mForceFOV != 0) mLastCameraQuery.fov = mDegToRad(mForceFOV); if(mCameraZRot) { MatrixF rotMat(EulerF(0, 0, mDegToRad(mCameraZRot))); mLastCameraQuery.cameraMatrix.mul(rotMat); } Frustum frustum; if(mRenderStyle == RenderStyleStereoSideBySide) { // NOTE: these calculations are essentially overridden later by the fov port settings when rendering each eye. MathUtils::makeFovPortFrustum(&frustum, mLastCameraQuery.ortho, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane, mLastCameraQuery.fovPort[0]); } else { // set up the camera and viewport stuff: F32 wwidth; F32 wheight; F32 renderWidth = F32(renderSize.x); F32 renderHeight = F32(renderSize.y); F32 aspectRatio = renderWidth / renderHeight; // Use the FOV to calculate the viewport height scale // then generate the width scale from the aspect ratio. if(!mLastCameraQuery.ortho) { wheight = mLastCameraQuery.nearPlane * mTan(mLastCameraQuery.fov / 2.0f); wwidth = aspectRatio * wheight; } else { wheight = mLastCameraQuery.fov; wwidth = aspectRatio * wheight; } F32 hscale = wwidth * 2.0f / renderWidth; F32 vscale = wheight * 2.0f / renderHeight; F32 left = (updateRect.point.x - offset.x) * hscale - wwidth; F32 right = (updateRect.point.x + updateRect.extent.x - offset.x) * hscale - wwidth; F32 top = wheight - vscale * (updateRect.point.y - offset.y); F32 bottom = wheight - vscale * (updateRect.point.y + updateRect.extent.y - offset.y); frustum.set( mLastCameraQuery.ortho, left, right, top, bottom, mLastCameraQuery.nearPlane, mLastCameraQuery.farPlane ); } // Manipulate the frustum for tiled screenshots const bool screenShotMode = gScreenShot && gScreenShot->isPending(); if ( screenShotMode ) { gScreenShot->tileFrustum( frustum ); GFX->setViewMatrix(MatrixF::Identity); } RectI tempRect = updateRect; if (!renderingToTarget) { #ifdef TORQUE_OS_MAC Point2I screensize = getRoot()->getWindowSize(); tempRect.point.y = screensize.y - (tempRect.point.y + tempRect.extent.y); #endif GFX->setViewport( tempRect ); } else { // Activate stereo RT GFX->activateStereoTarget(-1); } // Clear the zBuffer so GUI doesn't hose object rendering accidentally GFX->clear( GFXClearZBuffer , ColorI(20,20,20), 1.0f, 0 ); //GFX->clear( GFXClearTarget, ColorI(255,0,0), 1.0f, 0); GFX->setFrustum( frustum ); if(mLastCameraQuery.ortho) { mOrthoWidth = frustum.getWidth(); mOrthoHeight = frustum.getHeight(); } // We're going to be displaying this render at size of this control in // pixels - let the scene know so that it can calculate e.g. reflections // correctly for that final display result. gClientSceneGraph->setDisplayTargetResolution(renderSize); // Set the GFX world matrix to the world-to-camera transform, but don't // change the cameraMatrix in mLastCameraQuery. This is because // mLastCameraQuery.cameraMatrix is supposed to contain the camera-to-world // transform. In-place invert would save a copy but mess up any GUIs that // depend on that value. MatrixF worldToCamera = mLastCameraQuery.cameraMatrix; worldToCamera.inverse(); GFX->setWorldMatrix( worldToCamera ); mSaveProjection = GFX->getProjectionMatrix(); mSaveModelview = GFX->getWorldMatrix(); mSaveViewport = updateRect; mSaveWorldToScreenScale = GFX->getWorldToScreenScale(); mSaveFrustum = GFX->getFrustum(); mSaveFrustum.setTransform( mLastCameraQuery.cameraMatrix ); // Set the default non-clip projection as some // objects depend on this even in non-reflect cases. gClientSceneGraph->setNonClipProjection( mSaveProjection ); // Give the post effect manager the worldToCamera, and cameraToScreen matrices PFXMGR->setFrameMatrices( mSaveModelview, mSaveProjection ); renderWorld(updateRect); DebugDrawer::get()->render(); // Render the canvas overlay if its available if (mRenderStyle == RenderStyleStereoSideBySide && mStereoGuiTarget.getPointer()) { GFXDEBUGEVENT_SCOPE( StereoGui_Render, ColorI( 255, 0, 0 ) ); MatrixF proj(1); Frustum originalFrustum = GFX->getFrustum(); GFXTextureObject *texObject = mStereoGuiTarget->getTexture(0); const FovPort *currentFovPort = GFX->getStereoFovPort(); const MatrixF *eyeTransforms = GFX->getStereoEyeTransforms(); const Point3F *eyeOffset = GFX->getStereoEyeOffsets(); Frustum gfxFrustum = originalFrustum; for (U32 i=0; i<2; i++) { GFX->activateStereoTarget(i); MathUtils::makeFovPortFrustum(&gfxFrustum, true, gfxFrustum.getNearDist(), gfxFrustum.getFarDist(), currentFovPort[i], eyeTransforms[i]); GFX->setFrustum(gfxFrustum); MatrixF eyeWorldTrans(1); eyeWorldTrans.setPosition(Point3F(eyeOffset[i].x,eyeOffset[i].y,eyeOffset[i].z)); MatrixF eyeWorld(1); eyeWorld.mul(eyeWorldTrans); eyeWorld.inverse(); GFX->setWorldMatrix(eyeWorld); GFX->setViewMatrix(MatrixF::Identity); if (!mStereoOverlayVB.getPointer()) { mStereoOverlayVB.set(GFX, 4, GFXBufferTypeStatic); GFXVertexPCT *verts = mStereoOverlayVB.lock(0, 4); F32 texLeft = 0.0f; F32 texRight = 1.0f; F32 texTop = 1.0f; F32 texBottom = 0.0f; F32 rectRatio = gfxFrustum.getWidth() / gfxFrustum.getHeight(); F32 rectWidth = gfxFrustum.getWidth() * TS_OVERLAY_SCREEN_WIDTH; F32 rectHeight = rectWidth * rectRatio; F32 screenLeft = -rectWidth * 0.5; F32 screenRight = rectWidth * 0.5; F32 screenTop = -rectHeight * 0.5; F32 screenBottom = rectHeight * 0.5; const F32 fillConv = 0.0f; const F32 frustumDepthAdjusted = gfxFrustum.getNearDist() + 0.012; verts[0].point.set( screenLeft - fillConv, frustumDepthAdjusted, screenTop - fillConv ); verts[1].point.set( screenRight - fillConv, frustumDepthAdjusted, screenTop - fillConv ); verts[2].point.set( screenLeft - fillConv, frustumDepthAdjusted, screenBottom - fillConv ); verts[3].point.set( screenRight - fillConv, frustumDepthAdjusted, screenBottom - fillConv ); verts[0].color = verts[1].color = verts[2].color = verts[3].color = ColorI(255,255,255,255); verts[0].texCoord.set( texLeft, texTop ); verts[1].texCoord.set( texRight, texTop ); verts[2].texCoord.set( texLeft, texBottom ); verts[3].texCoord.set( texRight, texBottom ); mStereoOverlayVB.unlock(); } if (!mStereoGuiSB.getPointer()) { // DrawBitmapStretchSR GFXStateBlockDesc bitmapStretchSR; bitmapStretchSR.setCullMode(GFXCullNone); bitmapStretchSR.setZReadWrite(false, false); bitmapStretchSR.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha); bitmapStretchSR.samplersDefined = true; bitmapStretchSR.samplers[0] = GFXSamplerStateDesc::getClampLinear(); bitmapStretchSR.samplers[0].minFilter = GFXTextureFilterPoint; bitmapStretchSR.samplers[0].mipFilter = GFXTextureFilterPoint; bitmapStretchSR.samplers[0].magFilter = GFXTextureFilterPoint; mStereoGuiSB = GFX->createStateBlock(bitmapStretchSR); } GFX->setVertexBuffer(mStereoOverlayVB); GFX->setStateBlock(mStereoGuiSB); GFX->setTexture( 0, texObject ); GFX->setupGenericShaders( GFXDevice::GSModColorTexture ); GFX->drawPrimitive( GFXTriangleStrip, 0, 2 ); } } // Restore the previous matrix state before // we begin rendering the child controls. saver.restore(); // Restore the render style and any stereo parameters GFX->setActiveRenderTarget(origTarget); GFX->setCurrentRenderStyle(prevRenderStyle); GFX->setCurrentProjectionOffset(prevProjectionOffset); if(mRenderStyle == RenderStyleStereoSideBySide && gLastStereoTexture) { GFX->setClipRect(updateRect); GFX->getDrawUtil()->drawBitmapStretch(gLastStereoTexture, updateRect); } // Allow subclasses to render 2D elements. GFX->setClipRect(updateRect); renderGui( offset, updateRect ); if (shouldRenderChildControls()) { renderChildControls(offset, updateRect); } smFrameCount++; }
void PSSMLightShadowMap::_render( RenderPassManager* renderPass, const SceneRenderState *diffuseState ) { PROFILE_SCOPE(PSSMLightShadowMap_render); const ShadowMapParams *params = mLight->getExtended<ShadowMapParams>(); const LightMapParams *lmParams = mLight->getExtended<LightMapParams>(); const bool bUseLightmappedGeometry = lmParams ? !lmParams->representedInLightmap || lmParams->includeLightmappedGeometryInShadow : true; const U32 texSize = getBestTexSize( params->numSplits < 4 ? params->numSplits : 2 ); if ( mShadowMapTex.isNull() || mNumSplits != params->numSplits || mTexSize != texSize ) { _setNumSplits( params->numSplits, texSize ); mShadowMapDepth = _getDepthTarget( mShadowMapTex->getWidth(), mShadowMapTex->getHeight() ); } mLogWeight = params->logWeight; Frustum fullFrustum( diffuseState->getCameraFrustum() ); fullFrustum.cropNearFar(fullFrustum.getNearDist(), params->shadowDistance); GFXFrustumSaver frustSaver; GFXTransformSaver saver; // Set our render target GFX->pushActiveRenderTarget(); mTarget->attachTexture( GFXTextureTarget::Color0, mShadowMapTex ); mTarget->attachTexture( GFXTextureTarget::DepthStencil, mShadowMapDepth ); GFX->setActiveRenderTarget( mTarget ); GFX->clear( GFXClearStencil | GFXClearZBuffer | GFXClearTarget, ColorI(255,255,255), 1.0f, 0 ); // Calculate our standard light matrices MatrixF lightMatrix; calcLightMatrices( lightMatrix, diffuseState->getCameraFrustum() ); lightMatrix.inverse(); MatrixF lightViewProj = GFX->getProjectionMatrix() * lightMatrix; // TODO: This is just retrieving the near and far calculated // in calcLightMatrices... we should make that clear. F32 pnear, pfar; GFX->getFrustum( NULL, NULL, NULL, NULL, &pnear, &pfar, NULL ); // Set our view up GFX->setWorldMatrix(lightMatrix); MatrixF toLightSpace = lightMatrix; // * invCurrentView; _calcSplitPos(fullFrustum); mWorldToLightProj = GFX->getProjectionMatrix() * toLightSpace; // Apply the PSSM const F32 savedSmallestVisible = TSShapeInstance::smSmallestVisiblePixelSize; const F32 savedDetailAdjust = TSShapeInstance::smDetailAdjust; TSShapeInstance::smDetailAdjust *= smDetailAdjustScale; TSShapeInstance::smSmallestVisiblePixelSize = smSmallestVisiblePixelSize; for (U32 i = 0; i < mNumSplits; i++) { GFXTransformSaver saver; // Calculate a sub-frustum Frustum subFrustum(fullFrustum); subFrustum.cropNearFar(mSplitDist[i], mSplitDist[i+1]); // Calculate our AABB in the light's clip space. Box3F clipAABB = _calcClipSpaceAABB(subFrustum, lightViewProj, fullFrustum.getFarDist()); // Calculate our crop matrix Point3F scale(2.0f / (clipAABB.maxExtents.x - clipAABB.minExtents.x), 2.0f / (clipAABB.maxExtents.y - clipAABB.minExtents.y), 1.0f); // TODO: This seems to produce less "pops" of the // shadow resolution as the camera spins around and // it should produce pixels that are closer to being // square. // // Still is it the right thing to do? // scale.y = scale.x = ( getMin( scale.x, scale.y ) ); //scale.x = mFloor(scale.x); //scale.y = mFloor(scale.y); Point3F offset( -0.5f * (clipAABB.maxExtents.x + clipAABB.minExtents.x) * scale.x, -0.5f * (clipAABB.maxExtents.y + clipAABB.minExtents.y) * scale.y, 0.0f ); MatrixF cropMatrix(true); cropMatrix.scale(scale); cropMatrix.setPosition(offset); _roundProjection(lightMatrix, cropMatrix, offset, i); cropMatrix.setPosition(offset); // Save scale/offset for shader computations mScaleProj[i].set(scale); mOffsetProj[i].set(offset); // Adjust the far plane to the max z we got (maybe add a little to deal with split overlap) bool isOrtho; { F32 left, right, bottom, top, nearDist, farDist; GFX->getFrustum(&left, &right, &bottom, &top, &nearDist, &farDist,&isOrtho); // BTRTODO: Fix me! farDist = clipAABB.maxExtents.z; if (!isOrtho) GFX->setFrustum(left, right, bottom, top, nearDist, farDist); else { // Calculate a new far plane, add a fudge factor to avoid bringing // the far plane in too close. F32 newFar = pfar * clipAABB.maxExtents.z + 1.0f; mFarPlaneScalePSSM[i] = (pfar - pnear) / (newFar - pnear); GFX->setOrtho(left, right, bottom, top, pnear, newFar, true); } } // Crop matrix multiply needs to be post-projection. MatrixF alightProj = GFX->getProjectionMatrix(); alightProj = cropMatrix * alightProj; // Set our new projection GFX->setProjectionMatrix(alightProj); // Render into the quad of the shadow map we are using. GFX->setViewport(mViewports[i]); SceneManager* sceneManager = diffuseState->getSceneManager(); // The frustum is currently the full size and has not had // cropping applied. // // We make that adjustment here. const Frustum& uncroppedFrustum = GFX->getFrustum(); Frustum croppedFrustum; scale *= 0.5f; croppedFrustum.set( isOrtho, uncroppedFrustum.getNearLeft() / scale.x, uncroppedFrustum.getNearRight() / scale.x, uncroppedFrustum.getNearTop() / scale.y, uncroppedFrustum.getNearBottom() / scale.y, uncroppedFrustum.getNearDist(), uncroppedFrustum.getFarDist(), uncroppedFrustum.getTransform() ); MatrixF camera = GFX->getWorldMatrix(); camera.inverse(); croppedFrustum.setTransform( camera ); // Setup the scene state and use the diffuse state // camera position and screen metrics values so that // lod is done the same as in the diffuse pass. SceneRenderState shadowRenderState ( sceneManager, SPT_Shadow, SceneCameraState( diffuseState->getViewport(), croppedFrustum, GFX->getWorldMatrix(), GFX->getProjectionMatrix() ), renderPass ); shadowRenderState.getMaterialDelegate().bind( this, &LightShadowMap::getShadowMaterial ); shadowRenderState.renderNonLightmappedMeshes( true ); shadowRenderState.renderLightmappedMeshes( bUseLightmappedGeometry ); shadowRenderState.setDiffuseCameraTransform( diffuseState->getCameraTransform() ); shadowRenderState.setWorldToScreenScale( diffuseState->getWorldToScreenScale() ); U32 objectMask = SHADOW_TYPEMASK; if ( i == mNumSplits-1 && params->lastSplitTerrainOnly ) objectMask = TerrainObjectType; sceneManager->renderSceneNoLights( &shadowRenderState, objectMask ); _debugRender( &shadowRenderState ); } // Restore the original TS lod settings. TSShapeInstance::smSmallestVisiblePixelSize = savedSmallestVisible; TSShapeInstance::smDetailAdjust = savedDetailAdjust; // Release our render target mTarget->resolve(); GFX->popActiveRenderTarget(); }
void GuiObjectView::renderWorld( const RectI& updateRect ) { if( !mModel ) return; GFXTransformSaver _saveTransforms; // Determine the camera position, and store off render state. MatrixF modelview; MatrixF mv; Point3F cp; modelview = GFX->getWorldMatrix(); mv = modelview; mv.inverse(); mv.getColumn( 3, &cp ); RenderPassManager* renderPass = gClientSceneGraph->getDefaultRenderPass(); S32 time = Platform::getVirtualMilliseconds(); S32 dt = time - mLastRenderTime; mLastRenderTime = time; LIGHTMGR->unregisterAllLights(); LIGHTMGR->setSpecialLight( LightManager::slSunLightType, mLight ); GFX->setStateBlock( mDefaultGuiSB ); F32 left, right, top, bottom, nearPlane, farPlane; bool isOrtho; GFX->getFrustum( &left, &right, &bottom, &top, &nearPlane, &farPlane, &isOrtho ); Frustum frust( false, left, right, top, bottom, nearPlane, farPlane, MatrixF::Identity ); SceneRenderState state ( gClientSceneGraph, SPT_Diffuse, SceneCameraState( GFX->getViewport(), frust, GFX->getWorldMatrix(), GFX->getProjectionMatrix() ), renderPass, false ); // Set up our TS render state here. TSRenderState rdata; rdata.setSceneState( &state ); // We might have some forward lit materials // so pass down a query to gather lights. LightQuery query; query.init( SphereF( Point3F::Zero, 1.0f ) ); rdata.setLightQuery( &query ); // Render primary model. if( mModel ) { if( mRunThread ) { mModel->advanceTime( dt / 1000.f, mRunThread ); mModel->animate(); } mModel->render( rdata ); } // Render mounted model. if( mMountedModel && mMountNode != -1 ) { GFX->pushWorldMatrix(); GFX->multWorld( mModel->mNodeTransforms[ mMountNode ] ); GFX->multWorld( mMountTransform ); mMountedModel->render( rdata ); GFX->popWorldMatrix(); } renderPass->renderPass( &state ); // Make sure to remove our fake sun. LIGHTMGR->unregisterAllLights(); }
void DualParaboloidLightShadowMap::_render( RenderPassManager* renderPass, const SceneRenderState *diffuseState ) { PROFILE_SCOPE(DualParaboloidLightShadowMap_render); const ShadowMapParams *p = mLight->getExtended<ShadowMapParams>(); const LightMapParams *lmParams = mLight->getExtended<LightMapParams>(); const bool bUseLightmappedGeometry = lmParams ? !lmParams->representedInLightmap || lmParams->includeLightmappedGeometryInShadow : true; const U32 texSize = getBestTexSize( 2 ); if ( mShadowMapTex.isNull() || mTexSize != texSize ) { mTexSize = texSize; mShadowMapTex.set( mTexSize * 2, mTexSize, ShadowMapFormat, &ShadowMapProfile, "DualParaboloidLightShadowMap" ); mShadowMapDepth = _getDepthTarget( mShadowMapTex->getWidth(), mShadowMapTex->getHeight() ); } GFXFrustumSaver frustSaver; GFXTransformSaver saver; // Set and Clear target GFX->pushActiveRenderTarget(); mTarget->attachTexture(GFXTextureTarget::Color0, mShadowMapTex); mTarget->attachTexture( GFXTextureTarget::DepthStencil, mShadowMapDepth ); GFX->setActiveRenderTarget(mTarget); GFX->clear(GFXClearTarget | GFXClearStencil | GFXClearZBuffer, ColorI::WHITE, 1.0f, 0); const bool bUseSinglePassDPM = (p->shadowType == ShadowType_DualParaboloidSinglePass); // Set up matrix and visible distance mWorldToLightProj = mLight->getTransform(); mWorldToLightProj.inverse(); const F32 &lightRadius = mLight->getRange().x; const F32 paraboloidNearPlane = 0.01f; const F32 renderPosOffset = 0.01f; // Alter for creation of scene state if this is a single pass map if(bUseSinglePassDPM) { VectorF camDir; MatrixF temp = mLight->getTransform(); temp.getColumn(1, &camDir); temp.setPosition(mLight->getPosition() - camDir * (lightRadius + renderPosOffset)); temp.inverse(); GFX->setWorldMatrix(temp); GFX->setOrtho(-lightRadius, lightRadius, -lightRadius, lightRadius, paraboloidNearPlane, 2.0f * lightRadius, true); } else { VectorF camDir; MatrixF temp = mLight->getTransform(); temp.getColumn(1, &camDir); temp.setPosition(mLight->getPosition() - camDir * renderPosOffset); temp.inverse(); GFX->setWorldMatrix(temp); GFX->setOrtho(-lightRadius, lightRadius, -lightRadius, lightRadius, paraboloidNearPlane, lightRadius, true); } SceneManager* sceneManager = diffuseState->getSceneManager(); // Front map render { SceneRenderState frontMapRenderState ( sceneManager, SPT_Shadow, SceneCameraState::fromGFXWithViewport( diffuseState->getViewport() ), renderPass ); frontMapRenderState.getMaterialDelegate().bind( this, &LightShadowMap::getShadowMaterial ); frontMapRenderState.renderNonLightmappedMeshes( true ); frontMapRenderState.renderLightmappedMeshes( bUseLightmappedGeometry ); frontMapRenderState.setDiffuseCameraTransform( diffuseState->getCameraTransform() ); frontMapRenderState.setWorldToScreenScale( diffuseState->getWorldToScreenScale() ); if(bUseSinglePassDPM) { GFX->setWorldMatrix(mWorldToLightProj); frontMapRenderState.getRenderPass()->getMatrixSet().setSceneView(mWorldToLightProj); GFX->setOrtho(-lightRadius, lightRadius, -lightRadius, lightRadius, paraboloidNearPlane, lightRadius, true); } GFXDEBUGEVENT_SCOPE( DualParaboloidLightShadowMap_Render_FrontFacingParaboloid, ColorI::RED ); mShadowMapScale.set(0.5f, 1.0f); mShadowMapOffset.set(-0.5f, 0.0f); sceneManager->renderSceneNoLights( &frontMapRenderState, SHADOW_TYPEMASK ); _debugRender( &frontMapRenderState ); } // Back map render if(!bUseSinglePassDPM) { GFXDEBUGEVENT_SCOPE( DualParaboloidLightShadowMap_Render_BackFacingParaboloid, ColorI::RED ); mShadowMapScale.set(0.5f, 1.0f); mShadowMapOffset.set(0.5f, 0.0f); // Invert direction on camera matrix VectorF right, forward; MatrixF temp = mLight->getTransform(); temp.getColumn( 1, &forward ); temp.getColumn( 0, &right ); forward *= -1.0f; right *= -1.0f; temp.setColumn( 1, forward ); temp.setColumn( 0, right ); temp.setPosition(mLight->getPosition() - forward * -renderPosOffset); temp.inverse(); GFX->setWorldMatrix(temp); // Create an inverted scene state for the back-map SceneRenderState backMapRenderState ( sceneManager, SPT_Shadow, SceneCameraState::fromGFXWithViewport( diffuseState->getViewport() ), renderPass ); backMapRenderState.getMaterialDelegate().bind( this, &LightShadowMap::getShadowMaterial ); backMapRenderState.renderNonLightmappedMeshes( true ); backMapRenderState.renderLightmappedMeshes( bUseLightmappedGeometry ); backMapRenderState.setDiffuseCameraTransform( diffuseState->getCameraTransform() ); backMapRenderState.setWorldToScreenScale( diffuseState->getWorldToScreenScale() ); backMapRenderState.getRenderPass()->getMatrixSet().setSceneView(temp); // Draw scene sceneManager->renderSceneNoLights( &backMapRenderState ); _debugRender( &backMapRenderState ); } mTarget->resolve(); GFX->popActiveRenderTarget(); }