void TSShapeInstance::render( const TSRenderState &rdata, S32 dl, F32 intraDL ) { AssertFatal( dl >= 0 && dl < mShape->details.size(),"TSShapeInstance::render" ); S32 i; const TSDetail * detail = &mShape->details[dl]; S32 ss = detail->subShapeNum; S32 od = detail->objectDetailNum; // if we're a billboard detail, draw it and exit if ( ss < 0 ) { PROFILE_SCOPE( TSShapeInstance_RenderBillboards ); if ( !rdata.isNoRenderTranslucent() && ( TSLastDetail::smCanShadow || !rdata.getSceneState()->isShadowPass() ) ) mShape->billboardDetails[ dl ]->render( rdata, mAlphaAlways ? mAlphaAlwaysValue : 1.0f ); return; } // run through the meshes S32 start = rdata.isNoRenderNonTranslucent() ? mShape->subShapeFirstTranslucentObject[ss] : mShape->subShapeFirstObject[ss]; S32 end = rdata.isNoRenderTranslucent() ? mShape->subShapeFirstTranslucentObject[ss] : mShape->subShapeFirstObject[ss] + mShape->subShapeNumObjects[ss]; for (i=start; i<end; i++) { // following line is handy for debugging, to see what part of the shape that it is rendering // const char *name = mShape->names[ mMeshObjects[i].object->nameIndex ]; mMeshObjects[i].render( od, mMaterialList, rdata, mAlphaAlways ? mAlphaAlwaysValue : 1.0f ); } }
void Projectile::prepBatchRender( SceneRenderState *state ) { if ( !mProjectileShape ) return; GFXTransformSaver saver; // Set up our TS render state. TSRenderState rdata; rdata.setSceneState( state ); // We might have some forward lit materials // so pass down a query to gather lights. LightQuery query; query.init( getWorldSphere() ); rdata.setLightQuery( &query ); MatrixF mat = getRenderTransform(); mat.scale( mObjScale ); mat.scale( mDataBlock->scale ); GFX->setWorldMatrix( mat ); mProjectileShape->setDetailFromPosAndScale( state, mat.getPosition(), mObjScale ); mProjectileShape->animate(); mProjectileShape->render( rdata ); }
void TSLastDetail::render( TSRenderState &rdata, F32 alpha ) { #if 0 // Early out if we have nothing to render. if ( alpha < 0.01f || !mMatInstance || mMaterial->mImposterUVs.size() == 0 ) return; const MatrixF &mat = GFX->getWorldMatrix(); // Post a render instance for this imposter... the special // imposter render manager will do the magic! RenderPassManager *renderPass = rdata.getSceneState()->getRenderPass(); ImposterRenderInst *ri = renderPass->allocInst<ImposterRenderInst>(); ri->mat = rdata.getSceneState()->getOverrideMaterial( mMatInstance ); ri->state.alpha = alpha; // Store the up and right vectors of the rotation // and we'll generate the up vector in the shader. // // This is faster than building a quat on the // CPU and then rebuilding the matrix on the GPU. // // NOTE: These vector include scale. // mat.getColumn( 2, &ri->state.upVec ); mat.getColumn( 0, &ri->state.rightVec ); // We send the unscaled size and the vertex shader // will use the orientation vectors above to scale it. ri->state.halfSize = mRadius; // We use the center of the object bounds for // the center of the billboard quad. mat.mulP( mCenter, &ri->state.center ); // We sort by the imposter type first so that RIT_Imposter and s // RIT_ImposterBatches do not get mixed together. // // We then sort by material. // ri->defaultKey = 1; ri->defaultKey2 = ri->mat->getStateHint(); renderPass->addInst( ri ); #endif }
void TSShapeInstance::MeshObjectInstance::render( S32 objectDetail, TSMaterialList *materials, const TSRenderState &rdata, F32 alpha ) { PROFILE_SCOPE( TSShapeInstance_MeshObjectInstance_render ); if ( forceHidden || ( ( visible * alpha ) <= 0.01f ) ) return; TSMesh *mesh = getMesh(objectDetail); if ( !mesh ) return; const MatrixF &transform = getTransform(); if ( rdata.getCuller() ) { Box3F box( mesh->getBounds() ); transform.mul( box ); if ( rdata.getCuller()->isCulled( box ) ) return; } GFX->pushWorldMatrix(); GFX->multWorld( transform ); mesh->setFade( visible * alpha ); // Pass a hint to the mesh that time has advanced and that the // skin is dirty and needs to be updated. This should result // in the skin only updating once per frame in most cases. const U32 currTime = Sim::getCurrentTime(); bool isSkinDirty = currTime != mLastTime; mesh->render( materials, rdata, isSkinDirty, *mTransforms, mVertexBuffer, mPrimitiveBuffer ); // Update the last render time. mLastTime = currTime; GFX->popWorldMatrix(); }
void PxSingleActor::renderObject(SceneState* state) { GFXTransformSaver saver; // Set up our TS render state here. TSRenderState rdata; rdata.setSceneState( state ); //rdata.setObjScale( &getScale() ); LightManager *lm = gClientSceneGraph->getLightManager(); if ( !state->isShadowPass() ) lm->setupLights( this, getWorldSphere() ); MatrixF mat = getTransform(); mat.scale( getScale() ); GFX->setWorldMatrix( mat ); mShapeInstance->animate(); mShapeInstance->render( rdata ); lm->resetLights(); }
void Projectile::prepBatchRender( SceneState *state ) { GFXTransformSaver saver; // Set up our TS render state. TSRenderState rdata; rdata.setSceneState( state ); MatrixF mat = getRenderTransform(); mat.scale( mObjScale ); mat.scale( mDataBlock->scale ); GFX->setWorldMatrix( mat ); if(mProjectileShape) { AssertFatal(mProjectileShape != NULL, "Projectile::renderObject: Error, projectile shape should always be present in renderObject"); mProjectileShape->setDetailFromPosAndScale( state, mat.getPosition(), mObjScale ); mProjectileShape->animate(); mProjectileShape->render( rdata ); } }
void TSStatic::prepRenderImage( SceneRenderState* state ) { if( !mShapeInstance ) return; Point3F cameraOffset; getRenderTransform().getColumn(3,&cameraOffset); cameraOffset -= state->getDiffuseCameraPosition(); F32 dist = cameraOffset.len(); if (dist < 0.01f) dist = 0.01f; F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z)); if ( mForceDetail == -1 ) mShapeInstance->setDetailFromDistance( state, dist * invScale ); else mShapeInstance->setCurrentDetail( mForceDetail ); if ( mShapeInstance->getCurrentDetail() < 0 ) return; GFXTransformSaver saver; // Set up our TS render state. TSRenderState rdata; rdata.setSceneState( state ); rdata.setFadeOverride( 1.0f ); rdata.setOriginSort( mUseOriginSort ); // If we have submesh culling enabled then prepare // the object space frustum to pass to the shape. Frustum culler; if ( mMeshCulling ) { culler = state->getCullingFrustum(); MatrixF xfm( true ); xfm.scale( Point3F::One / getScale() ); xfm.mul( getRenderWorldTransform() ); xfm.mul( culler.getTransform() ); culler.setTransform( xfm ); rdata.setCuller( &culler ); } // We might have some forward lit materials // so pass down a query to gather lights. LightQuery query; query.init( getWorldSphere() ); rdata.setLightQuery( &query ); MatrixF mat = getRenderTransform(); mat.scale( mObjScale ); GFX->setWorldMatrix( mat ); mShapeInstance->animate(); mShapeInstance->render( rdata ); if ( mRenderNormalScalar > 0 ) { ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>(); ri->renderDelegate.bind( this, &TSStatic::_renderNormals ); ri->type = RenderPassManager::RIT_Editor; state->getRenderPass()->addInst( ri ); } }
void TSStatic::prepRenderImage( SceneRenderState* state ) { if( !mShapeInstance ) return; //WLE - Vince //Lod preloading GameConnection* connection = GameConnection::getConnectionToServer(); if (connection && !connection->didFirstRender) { TSRenderState rdata; rdata.setSceneState( state ); rdata.setFadeOverride( 1.0f ); rdata.setOriginSort( mUseOriginSort ); for (S32 i = mShapeInstance->getSmallestVisibleDL(); i >= 0; i-- ) { mShapeInstance->setCurrentDetail( i ); mShapeInstance->render( rdata ); } } Point3F cameraOffset; getRenderTransform().getColumn(3,&cameraOffset); cameraOffset -= state->getDiffuseCameraPosition(); F32 dist = cameraOffset.len(); if (dist < 0.01f) dist = 0.01f; if (mUseAlphaLod) { mAlphaLOD = 1.0f; if ((mAlphaLODStart < mAlphaLODEnd) && mAlphaLODStart > 0.1f) { if (mInvertAlphaLod) { if (dist <= mAlphaLODStart) { return; } if (dist < mAlphaLODEnd) { mAlphaLOD = ((dist - mAlphaLODStart) / (mAlphaLODEnd - mAlphaLODStart)); } } else { if (dist >= mAlphaLODEnd) { return; } if (dist > mAlphaLODStart) { mAlphaLOD -= ((dist - mAlphaLODStart) / (mAlphaLODEnd - mAlphaLODStart)); } } } } F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z)); if ( mForceDetail == -1 ) mShapeInstance->setDetailFromDistance( state, dist * invScale ); else mShapeInstance->setCurrentDetail( mForceDetail ); if ( mShapeInstance->getCurrentDetail() < 0 ) return; GFXTransformSaver saver; // Set up our TS render state. TSRenderState rdata; rdata.setSceneState( state ); rdata.setFadeOverride( 1.0f ); rdata.setOriginSort( mUseOriginSort ); // If we have submesh culling enabled then prepare // the object space frustum to pass to the shape. Frustum culler; if ( mMeshCulling ) { culler = state->getCullingFrustum(); MatrixF xfm( true ); xfm.scale( Point3F::One / getScale() ); xfm.mul( getRenderWorldTransform() ); xfm.mul( culler.getTransform() ); culler.setTransform( xfm ); rdata.setCuller( &culler ); } // We might have some forward lit materials // so pass down a query to gather lights. LightQuery query; query.init( getWorldSphere() ); rdata.setLightQuery( &query ); MatrixF mat = getRenderTransform(); mat.scale( mObjScale ); GFX->setWorldMatrix( mat ); mShapeInstance->animate(); if(mShapeInstance) { if (mUseAlphaLod) { mShapeInstance->setAlphaAlways(mAlphaLOD); S32 s = mShapeInstance->mMeshObjects.size(); for(S32 x = 0; x < s; x++) { mShapeInstance->mMeshObjects[x].visible = mAlphaLOD; } } } mShapeInstance->render( rdata ); if ( mRenderNormalScalar > 0 ) { ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>(); ri->renderDelegate.bind( this, &TSStatic::_renderNormals ); ri->type = RenderPassManager::RIT_Editor; state->getRenderPass()->addInst( ri ); } }
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 TSStatic::prepRenderImage( SceneRenderState* state ) { if( !mShapeInstance ) return; Point3F cameraOffset; getRenderTransform().getColumn(3,&cameraOffset); cameraOffset -= state->getDiffuseCameraPosition(); F32 dist = cameraOffset.len(); if (dist < 0.01f) dist = 0.01f; if (mUseAlphaFade) { mAlphaFade = 1.0f; if ((mAlphaFadeStart < mAlphaFadeEnd) && mAlphaFadeStart > 0.1f) { if (mInvertAlphaFade) { if (dist <= mAlphaFadeStart) { return; } if (dist < mAlphaFadeEnd) { mAlphaFade = ((dist - mAlphaFadeStart) / (mAlphaFadeEnd - mAlphaFadeStart)); } } else { if (dist >= mAlphaFadeEnd) { return; } if (dist > mAlphaFadeStart) { mAlphaFade -= ((dist - mAlphaFadeStart) / (mAlphaFadeEnd - mAlphaFadeStart)); } } } } F32 invScale = (1.0f/getMax(getMax(mObjScale.x,mObjScale.y),mObjScale.z)); // If we're currently rendering our own reflection we // don't want to render ourselves into it. if ( mCubeReflector.isRendering() ) return; if ( mForceDetail == -1 ) mShapeInstance->setDetailFromDistance( state, dist * invScale ); else mShapeInstance->setCurrentDetail( mForceDetail ); if ( mShapeInstance->getCurrentDetail() < 0 ) return; GFXTransformSaver saver; // Set up our TS render state. TSRenderState rdata; rdata.setSceneState( state ); rdata.setFadeOverride( 1.0f ); rdata.setOriginSort( mUseOriginSort ); if ( mCubeReflector.isEnabled() ) rdata.setCubemap( mCubeReflector.getCubemap() ); // Acculumation rdata.setAccuTex(mAccuTex); // If we have submesh culling enabled then prepare // the object space frustum to pass to the shape. Frustum culler; if ( mMeshCulling ) { culler = state->getCullingFrustum(); MatrixF xfm( true ); xfm.scale( Point3F::One / getScale() ); xfm.mul( getRenderWorldTransform() ); xfm.mul( culler.getTransform() ); culler.setTransform( xfm ); rdata.setCuller( &culler ); } // We might have some forward lit materials // so pass down a query to gather lights. LightQuery query; query.init( getWorldSphere() ); rdata.setLightQuery( &query ); MatrixF mat = getRenderTransform(); mat.scale( mObjScale ); GFX->setWorldMatrix( mat ); if ( state->isDiffusePass() && mCubeReflector.isEnabled() && mCubeReflector.getOcclusionQuery() ) { RenderPassManager *pass = state->getRenderPass(); OccluderRenderInst *ri = pass->allocInst<OccluderRenderInst>(); ri->type = RenderPassManager::RIT_Occluder; ri->query = mCubeReflector.getOcclusionQuery(); mObjToWorld.mulP( mObjBox.getCenter(), &ri->position ); ri->scale.set( mObjBox.getExtents() ); ri->orientation = pass->allocUniqueXform( mObjToWorld ); ri->isSphere = false; state->getRenderPass()->addInst( ri ); } mShapeInstance->animate(); if(mShapeInstance) { if (mUseAlphaFade) { mShapeInstance->setAlphaAlways(mAlphaFade); S32 s = mShapeInstance->mMeshObjects.size(); for(S32 x = 0; x < s; x++) { mShapeInstance->mMeshObjects[x].visible = mAlphaFade; } } } mShapeInstance->render( rdata ); if ( mRenderNormalScalar > 0 ) { ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>(); ri->renderDelegate.bind( this, &TSStatic::_renderNormals ); ri->type = RenderPassManager::RIT_Editor; state->getRenderPass()->addInst( ri ); } }
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(); }
void ProjectedShadow::_renderToTexture( F32 camDist, const TSRenderState &rdata ) { PROFILE_SCOPE( ProjectedShadow_RenderToTexture ); GFXDEBUGEVENT_SCOPE( ProjectedShadow_RenderToTexture, ColorI( 255, 0, 0 ) ); RenderPassManager *renderPass = _getRenderPass(); if ( !renderPass ) return; GFXTransformSaver saver; // NOTE: GFXTransformSaver does not save/restore the frustum // so we must save it here before we modify it. F32 l, r, b, t, n, f; bool ortho; GFX->getFrustum( &l, &r, &b, &t, &n, &f, &ortho ); // Set the orthographic projection // matrix up, to be based on the radius // generated based on our shape. GFX->setOrtho( -mRadius, mRadius, -mRadius, mRadius, 0.001f, (mRadius * 2) * smDepthAdjust, true ); // Set the world to light space // matrix set up in shouldRender(). GFX->setWorldMatrix( mWorldToLight ); // Get the shapebase datablock if we have one. ShapeBaseData *data = NULL; if ( mShapeBase ) data = static_cast<ShapeBaseData*>( mShapeBase->getDataBlock() ); // Init or update the shadow texture size. if ( mShadowTexture.isNull() || ( data && data->shadowSize != mShadowTexture.getWidth() ) ) { U32 texSize = getNextPow2( data ? data->shadowSize : 256 * LightShadowMap::smShadowTexScalar ); mShadowTexture.set( texSize, texSize, GFXFormatR8G8B8A8, &PostFxTargetProfile, "BLShadow" ); } GFX->pushActiveRenderTarget(); if ( !mRenderTarget ) mRenderTarget = GFX->allocRenderToTextureTarget(); mRenderTarget->attachTexture( GFXTextureTarget::DepthStencil, _getDepthTarget( mShadowTexture->getWidth(), mShadowTexture->getHeight() ) ); mRenderTarget->attachTexture( GFXTextureTarget::Color0, mShadowTexture ); GFX->setActiveRenderTarget( mRenderTarget ); GFX->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, ColorI( 0, 0, 0, 0 ), 1.0f, 0 ); const SceneRenderState *diffuseState = rdata.getSceneState(); SceneManager *sceneManager = diffuseState->getSceneManager(); SceneRenderState baseState ( sceneManager, SPT_Shadow, SceneCameraState::fromGFXWithViewport( diffuseState->getViewport() ), renderPass ); baseState.getMaterialDelegate().bind( &ProjectedShadow::_getShadowMaterial ); baseState.setDiffuseCameraTransform( diffuseState->getCameraTransform() ); baseState.setWorldToScreenScale( diffuseState->getWorldToScreenScale() ); baseState.getCullingState().disableZoneCulling( true ); mParentObject->prepRenderImage( &baseState ); renderPass->renderPass( &baseState ); // Delete the SceneRenderState we allocated. mRenderTarget->resolve(); GFX->popActiveRenderTarget(); // If we're close enough then filter the shadow. if ( camDist < BasicLightManager::getShadowFilterDistance() ) { if ( !smShadowFilter ) { PostEffect *filter = NULL; if ( !Sim::findObject( "BL_ShadowFilterPostFx", filter ) ) Con::errorf( "ProjectedShadow::_renderToTexture() - 'BL_ShadowFilterPostFx' not found!" ); smShadowFilter = filter; } if ( smShadowFilter ) smShadowFilter->process( NULL, mShadowTexture ); } // Restore frustum if (!ortho) GFX->setFrustum(l, r, b, t, n, f); else GFX->setOrtho(l, r, b, t, n, f); // Set the last render time. mLastRenderTime = Platform::getVirtualMilliseconds(); // HACK: Will remove in future release! mDecalInstance->mCustomTex = &mShadowTexture; }
void Forest::prepRenderImage( SceneRenderState *state ) { PROFILE_SCOPE(Forest_RenderCells); // TODO: Fix stats. /* ForestCellVector &theCells = mData->getCells(); smTotalCells += theCells.size(); // Don't render if we don't have a grid! if ( theCells.empty() ) return false; */ // Prepare to render. GFXTransformSaver saver; // Figure out the grid range in the viewing area. const bool isReflectPass = state->isReflectPass(); const F32 cullScale = isReflectPass ? mReflectionLodScalar : 1.0f; // If we need to update our cached // zone state then do it now. if ( mZoningDirty ) { mZoningDirty = false; Vector<ForestCell*> cells; mData->getCells( &cells ); for ( U32 i=0; i < cells.size(); i++ ) cells[i]->_updateZoning( getSceneManager()->getZoneManager() ); } // TODO: Move these into the TSForestItemData as something we // setup once and don't do per-instance. // Set up the TS render state. TSRenderState rdata; rdata.setSceneState( state ); // Use origin sort on all forest elements as // its alot cheaper than the bounds sort. rdata.setOriginSort( true ); // We may have some forward lit materials in // the forest, so pass down a LightQuery for it. LightQuery lightQuery; rdata.setLightQuery( &lightQuery ); Frustum culler = state->getFrustum(); // Adjust the far distance if the cull scale has changed. if ( !mIsEqual( cullScale, 1.0f ) ) { const F32 visFarDist = culler.getFarDist() * cullScale; culler.setFarDist( visFarDist ); } Box3F worldBox; // Used for debug drawing. GFXDrawUtil* drawer = GFX->getDrawUtil(); drawer->clearBitmapModulation(); // Go thru the visible cells. const Box3F &cullerBounds = culler.getBounds(); const Point3F &camPos = state->getDiffuseCameraPosition(); U32 clipMask; smAverageItemsPerCell = 0.0f; U32 cellsProcessed = 0; ForestCell *cell; // First get all the top level cells which // intersect the frustum. Vector<ForestCell*> cellStack; mData->getCells( culler, &cellStack ); // Get the culling zone state. const BitVector &zoneState = state->getCullingState().getZoneVisibilityFlags(); // Now loop till we run out of cells. while ( !cellStack.empty() ) { // Pop off the next cell. cell = cellStack.last(); cellStack.pop_back(); const Box3F &cellBounds = cell->getBounds(); // If the cell is empty or its bounds is outside the frustum // bounds then we have nothing nothing more to do. if ( cell->isEmpty() || !cullerBounds.isOverlapped( cellBounds ) ) continue; // Can we cull this cell entirely? clipMask = culler.testPlanes( cellBounds, Frustum::PlaneMaskAll ); if ( clipMask == -1 ) continue; // Test cell visibility for interior zones. const bool visibleInside = !cell->getZoneOverlap().empty() ? zoneState.testAny( cell->getZoneOverlap() ) : false; // Test cell visibility for outdoor zone, but only // if we need to. bool visibleOutside = false; if( !cell->mIsInteriorOnly && !visibleInside ) { U32 outdoorZone = SceneZoneSpaceManager::RootZoneId; visibleOutside = !state->getCullingState().isCulled( cellBounds, &outdoorZone, 1 ); } // Skip cell if neither visible indoors nor outdoors. if( !visibleInside && !visibleOutside ) continue; // Update the stats. smAverageItemsPerCell += cell->getItems().size(); ++cellsProcessed; //if ( cell->isLeaf() ) //++leafCellsProcessed; // Get the distance from the camera to the cell bounds. F32 dist = cellBounds.getDistanceToPoint( camPos ); // If the largest item in the cell can be billboarded // at the cell distance to the camera... then the whole // cell can be billboarded. // if ( smForceImposters || ( dist > 0.0f && cell->getLargestItem().canBillboard( state, dist ) ) ) { // If imposters are disabled then skip out. if ( smDisableImposters ) continue; PROFILE_SCOPE(Forest_RenderBatches); // Keep track of how many cells were batched. ++smCellsBatched; // Ok... everything in this cell should be batched. First // create the batches if we don't have any. if ( !cell->hasBatches() ) cell->buildBatches(); //if ( drawCells ) //mCellRenderFlag[ cellIter - theCells.begin() ] = 1; // TODO: Light queries for batches? // Now render the batches... we pass the culler if the // cell wasn't fully visible so that each batch can be culled. smCellItemsBatched += cell->renderBatches( state, clipMask != 0 ? &culler : NULL ); continue; } // If this isn't a leaf then recurse. if ( !cell->isLeaf() ) { cell->getChildren( &cellStack ); continue; } // This cell has mixed billboards and mesh based items. ++smCellsRendered; PROFILE_SCOPE(Forest_RenderItems); //if ( drawCells ) //mCellRenderFlag[ cellIter - theCells.begin() ] = 2; // Use the cell bounds as the light query volume. // // This means all forward lit items in this cell will // get the same lights, but it performs much better. lightQuery.init( cellBounds ); // This cell is visible... have it render its items. smCellItemsRendered += cell->render( &rdata, clipMask != 0 ? &culler : NULL ); } // Keep track of the average items per cell. if ( cellsProcessed > 0 ) smAverageItemsPerCell /= (F32)cellsProcessed; // Got debug drawing to do? if ( smDrawCells && state->isDiffusePass() ) { ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>(); ri->renderDelegate.bind( this, &Forest::_renderCellBounds ); ri->type = RenderPassManager::RIT_Editor; state->getRenderPass()->addInst( ri ); } }
void TSMesh::innerRender( TSMaterialList *materials, const TSRenderState &rdata, TSVertexBufferHandle &vb, GFXPrimitiveBufferHandle &pb ) { PROFILE_SCOPE( TSMesh_InnerRender ); if( vertsPerFrame <= 0 ) return; F32 meshVisibility = rdata.getFadeOverride() * mVisibility; if ( meshVisibility < VISIBILITY_EPSILON ) return; const SceneRenderState *state = rdata.getSceneState(); RenderPassManager *renderPass = state->getRenderPass(); MeshRenderInst *coreRI = renderPass->allocInst<MeshRenderInst>(); coreRI->type = RenderPassManager::RIT_Mesh; const MatrixF &objToWorld = GFX->getWorldMatrix(); // Sort by the center point or the bounds. if ( rdata.useOriginSort() ) coreRI->sortDistSq = ( objToWorld.getPosition() - state->getCameraPosition() ).lenSquared(); else { Box3F rBox = mBounds; objToWorld.mul( rBox ); coreRI->sortDistSq = rBox.getSqDistanceToPoint( state->getCameraPosition() ); } if (getFlags(Billboard)) { Point3F camPos = state->getDiffuseCameraPosition(); Point3F objPos; objToWorld.getColumn(3, &objPos); Point3F targetVector = camPos - objPos; if(getFlags(BillboardZAxis)) targetVector.z = 0.0f; targetVector.normalize(); MatrixF orient = MathUtils::createOrientFromDir(targetVector); orient.setPosition(objPos); orient.scale(objToWorld.getScale()); coreRI->objectToWorld = renderPass->allocUniqueXform( orient ); } else coreRI->objectToWorld = renderPass->allocUniqueXform( objToWorld ); coreRI->worldToCamera = renderPass->allocSharedXform(RenderPassManager::View); coreRI->projection = renderPass->allocSharedXform(RenderPassManager::Projection); AssertFatal( vb.isValid(), "TSMesh::innerRender() - Got invalid vertex buffer!" ); AssertFatal( pb.isValid(), "TSMesh::innerRender() - Got invalid primitive buffer!" ); coreRI->vertBuff = &vb; coreRI->primBuff = &pb; coreRI->defaultKey2 = (U32) coreRI->vertBuff; coreRI->materialHint = rdata.getMaterialHint(); coreRI->visibility = meshVisibility; coreRI->cubemap = rdata.getCubemap(); // NOTICE: SFXBB is removed and refraction is disabled! //coreRI->backBuffTex = GFX->getSfxBackBuffer(); for ( S32 i = 0; i < primitives.size(); i++ ) { const TSDrawPrimitive &draw = primitives[i]; // We need to have a material. if ( draw.matIndex & TSDrawPrimitive::NoMaterial ) continue; #ifdef TORQUE_DEBUG // for inspection if you happen to be running in a debugger and can't do bit // operations in your head. S32 triangles = draw.matIndex & TSDrawPrimitive::Triangles; S32 strip = draw.matIndex & TSDrawPrimitive::Strip; S32 fan = draw.matIndex & TSDrawPrimitive::Fan; S32 indexed = draw.matIndex & TSDrawPrimitive::Indexed; S32 type = draw.matIndex & TSDrawPrimitive::TypeMask; TORQUE_UNUSED(triangles); TORQUE_UNUSED(strip); TORQUE_UNUSED(fan); TORQUE_UNUSED(indexed); TORQUE_UNUSED(type); #endif const U32 matIndex = draw.matIndex & TSDrawPrimitive::MaterialMask; BaseMatInstance *matInst = materials->getMaterialInst( matIndex ); #ifndef TORQUE_OS_MAC // Get the instancing material if this mesh qualifies. if ( meshType != SkinMeshType && pb->mPrimitiveArray[i].numVertices < smMaxInstancingVerts ) matInst = InstancingMaterialHook::getInstancingMat( matInst ); #endif // If we don't have a material instance after the overload then // there is nothing to render... skip this primitive. matInst = state->getOverrideMaterial( matInst ); if ( !matInst || !matInst->isValid()) continue; // If the material needs lights then gather them // here once and set them on the core render inst. if ( matInst->isForwardLit() && !coreRI->lights[0] && rdata.getLightQuery() ) rdata.getLightQuery()->getLights( coreRI->lights, 8 ); MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>(); *ri = *coreRI; ri->matInst = matInst; ri->defaultKey = matInst->getStateHint(); ri->primBuffIndex = i; // Translucent materials need the translucent type. if ( matInst->getMaterial()->isTranslucent() ) { ri->type = RenderPassManager::RIT_Translucent; ri->translucentSort = true; } renderPass->addInst( ri ); } }