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() ); }
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(); }
"TODO\n\n" "@ingroup Rendering" ); } MODULE_SHUTDOWN { SAFE_DELETE( gClientSceneGraph ); SAFE_DELETE( gServerSceneGraph ); } MODULE_END; bool SceneManager::smRenderBoundingBoxes; bool SceneManager::smLockDiffuseFrustum = false; SceneCameraState SceneManager::smLockedDiffuseCamera = SceneCameraState( RectI(), Frustum(), MatrixF(), MatrixF() ); SceneManager* gClientSceneGraph = NULL; SceneManager* gServerSceneGraph = NULL; //----------------------------------------------------------------------------- SceneManager::SceneManager( bool isClient ) : mLightManager( NULL ), mCurrentRenderState( NULL ), mIsClient( isClient ), mUsePostEffectFog( true ), mDisplayTargetResolution( 0, 0 ), mDefaultRenderPass( NULL ), mVisibleDistance( 500.f ),
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 GuiMaterialCtrl::onRender( Point2I offset, const RectI &updateRect ) { Parent::onRender( offset, updateRect ); if ( !mMaterialInst ) return; // Draw a quad with the material assigned GFXVertexBufferHandle<GFXVertexPCT> verts( GFX, 4, GFXBufferTypeVolatile ); verts.lock(); F32 screenLeft = updateRect.point.x; F32 screenRight = (updateRect.point.x + updateRect.extent.x); F32 screenTop = updateRect.point.y; F32 screenBottom = (updateRect.point.y + updateRect.extent.y); const F32 fillConv = GFX->getFillConventionOffset(); verts[0].point.set( screenLeft - fillConv, screenTop - fillConv, 0.f ); verts[1].point.set( screenRight - fillConv, screenTop - fillConv, 0.f ); verts[2].point.set( screenLeft - fillConv, screenBottom - fillConv, 0.f ); verts[3].point.set( screenRight - fillConv, screenBottom - fillConv, 0.f ); verts[0].color = verts[1].color = verts[2].color = verts[3].color = ColorI( 255, 255, 255, 255 ); verts[0].texCoord.set( 0.0f, 0.0f ); verts[1].texCoord.set( 1.0f, 0.0f ); verts[2].texCoord.set( 0.0f, 1.0f ); verts[3].texCoord.set( 1.0f, 1.0f ); verts.unlock(); GFX->setVertexBuffer( verts ); MatrixSet matSet; matSet.setWorld(GFX->getWorldMatrix()); matSet.setView(GFX->getViewMatrix()); matSet.setProjection(GFX->getProjectionMatrix()); MatrixF cameraMatrix( true ); F32 left, right, top, bottom, nearPlane, farPlane; bool isOrtho; GFX->getFrustum( &left, &right, &bottom, &top, &nearPlane, &farPlane, &isOrtho ); Frustum frust( isOrtho, left, right, top, bottom, nearPlane, farPlane, cameraMatrix ); SceneRenderState state ( gClientSceneGraph, SPT_Diffuse, SceneCameraState( GFX->getViewport(), frust, GFX->getWorldMatrix(), GFX->getProjectionMatrix() ), gClientSceneGraph->getDefaultRenderPass(), false ); SceneData sgData; sgData.init( &state ); sgData.wireframe = false; // Don't wireframe this. while( mMaterialInst->setupPass( &state, sgData ) ) { mMaterialInst->setSceneInfo( &state, sgData ); mMaterialInst->setTransforms( matSet, &state ); GFX->setupGenericShaders(); GFX->drawPrimitive( GFXTriangleStrip, 0, 2 ); } // Clean up GFX->setShader( NULL ); GFX->setTexture( 0, NULL ); }
void ImposterCapture::begin( TSShapeInstance *shapeInst, S32 dl, S32 dim, F32 radius, const Point3F ¢er ) { mShapeInstance = shapeInst; mDl = dl; mDim = dim; mRadius = radius; mCenter = center; mBlackTex.set( mDim, mDim, GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ) ); mWhiteTex.set( mDim, mDim, GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ) ); mNormalTex.set( mDim, mDim, GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ) ); mDepthBuffer.set( mDim, mDim, GFXFormatD24S8, &GFXDefaultZTargetProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ) ); // copy the black render target data into a bitmap mBlackBmp = new GBitmap; mBlackBmp->allocateBitmap(mDim, mDim, false, GFXFormatR8G8B8); // copy the white target data into a bitmap mWhiteBmp = new GBitmap; mWhiteBmp->allocateBitmap(mDim, mDim, false, GFXFormatR8G8B8); // Setup viewport and frustrum to do orthographic projection. RectI viewport( 0, 0, mDim, mDim ); GFX->setViewport( viewport ); GFX->setOrtho( -mRadius, mRadius, -mRadius, mRadius, 1, 20.0f * mRadius ); // Position camera looking out the X axis. MatrixF cameraMatrix( true ); cameraMatrix.setColumn( 0, Point3F( 0, 0, 1 ) ); cameraMatrix.setColumn( 1, Point3F( 1, 0, 0 ) ); cameraMatrix.setColumn( 2, Point3F( 0, 1, 0 ) ); // setup scene state required for TS mesh render...this is messy and inefficient; // should have a mode where most of this is done just once (and then // only the camera matrix changes between snapshots). // note that we use getFrustum here, but we set up an ortho projection above. // it doesn't seem like the scene state object pays attention to whether the projection is // ortho or not. this could become a problem if some code downstream tries to // reconstruct the projection matrix using the dimensions and doesn't // realize it should be ortho. at the moment no code is doing that. F32 left, right, top, bottom, nearPlane, farPlane; bool isOrtho; GFX->getFrustum( &left, &right, &bottom, &top, &nearPlane, &farPlane, &isOrtho ); Frustum frust( isOrtho, left, right, top, bottom, nearPlane, farPlane, cameraMatrix ); // Set up render pass. mRenderPass = new RenderPassManager(); mRenderPass->assignName( "DiffuseRenderPass" ); mMeshRenderBin = new RenderMeshMgr(); mRenderPass->addManager( mMeshRenderBin ); // Set up scene state. mState = new SceneRenderState( gClientSceneGraph, SPT_Diffuse, SceneCameraState( viewport, frust, GFX->getWorldMatrix(),GFX->getProjectionMatrix() ), mRenderPass, false ); // Set up our TS render state. mRData.setSceneState( mState ); mRData.setCubemap( NULL ); mRData.setFadeOverride( 1.0f ); // set gfx up for render to texture GFX->pushActiveRenderTarget(); mRenderTarget = GFX->allocRenderToTextureTarget(); }
void GuiMaterialPreview::renderWorld(const RectI &updateRect) { // nothing to render, punt if ( !mModel && !mMountedModel ) return; S32 time = Platform::getVirtualMilliseconds(); //S32 dt = time - lastRenderTime; lastRenderTime = time; F32 left, right, top, bottom, nearPlane, farPlane; bool isOrtho; GFX->getFrustum( &left, &right, &bottom, &top, &nearPlane, &farPlane, &isOrtho); Frustum frust( isOrtho, left, right, bottom, top, nearPlane, farPlane, MatrixF::Identity ); FogData savedFogData = gClientSceneGraph->getFogData(); gClientSceneGraph->setFogData( FogData() ); // no fog in preview window RenderPassManager* renderPass = gClientSceneGraph->getDefaultRenderPass(); SceneRenderState state ( gClientSceneGraph, SPT_Diffuse, SceneCameraState( GFX->getViewport(), frust, GFX->getWorldMatrix(), GFX->getProjectionMatrix() ), renderPass, true ); // 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 ); // Set up pass transforms renderPass->assignSharedXform(RenderPassManager::View, MatrixF::Identity); renderPass->assignSharedXform(RenderPassManager::Projection, GFX->getProjectionMatrix()); LIGHTMGR->unregisterAllLights(); LIGHTMGR->setSpecialLight( LightManager::slSunLightType, mFakeSun ); if ( mModel ) mModel->render( rdata ); if ( mMountedModel ) { // render a weapon /* MatrixF mat; GFX->pushWorldMatrix(); GFX->multWorld( mat ); GFX->popWorldMatrix(); */ } renderPass->renderPass( &state ); gClientSceneGraph->setFogData( savedFogData ); // restore fog setting // Make sure to remove our fake sun LIGHTMGR->unregisterAllLights(); }