Beispiel #1
0
void GFXD3D11TextureTarget::attachTexture( RenderSlot slot, GFXCubemap *tex, U32 face, U32 mipLevel/*=0*/ )
{
   GFXDEBUGEVENT_SCOPE( GFXPCD3D11TextureTarget_attachTexture_Cubemap, ColorI::RED );

   AssertFatal(slot < MaxRenderSlotId, "GFXD3D11TextureTarget::attachTexture - out of range slot.");

   // Mark state as dirty so device can know to update.
   invalidateState();

   // Release what we had, it's definitely going to change.
   SAFE_RELEASE(mTargetViews[slot]);
   SAFE_RELEASE(mTargets[slot]);
   SAFE_RELEASE(mTargetSRViews[slot]);

   mResolveTargets[slot] = NULL;

   // Cast the texture object to D3D...
   AssertFatal(!tex || static_cast<GFXD3D11Cubemap*>(tex), "GFXD3DTextureTarget::attachTexture - invalid cubemap object.");

   if(slot == Color0)
   {
      mTargetSize = Point2I::Zero;
      mTargetFormat = GFXFormatR8G8B8A8;
   }

   // Are we clearing?
   if(!tex)
   {
      // Yup - just exit, it'll stay NULL.      
      return;
   }

   GFXD3D11Cubemap *cube = static_cast<GFXD3D11Cubemap*>(tex);

   mTargets[slot] = cube->get2DTex();
   mTargets[slot]->AddRef();
   mTargetViews[slot] = cube->getRTView(face);
   mTargetViews[slot]->AddRef();
   mTargetSRViews[slot] = cube->getSRView();
   mTargetSRViews[slot]->AddRef();
   
   // Update surface size
   if(slot == Color0)
   {
      ID3D11Texture2D *surface = mTargets[Color0];
      if ( surface )
      {
         D3D11_TEXTURE2D_DESC sd;
         surface->GetDesc(&sd);
         mTargetSize = Point2I(sd.Width, sd.Height);

         S32 format = sd.Format;
         GFXREVERSE_LOOKUP( GFXD3D11TextureFormat, GFXFormat, format );
         mTargetFormat = (GFXFormat)format;
      }
   }

}
Beispiel #2
0
void GFXD3D11WindowTarget::resolveTo(GFXTextureObject *tex)
{
	GFXDEBUGEVENT_SCOPE(GFXPCD3D11WindowTarget_resolveTo, ColorI::RED);

	D3D11_TEXTURE2D_DESC desc;
	ID3D11Texture2D* surf = ((GFXD3D11TextureObject*)(tex))->get2DTex();
	surf->GetDesc(&desc);
	D3D11DEVICECONTEXT->ResolveSubresource(surf, 0, D3D11->mDeviceBackbuffer, 0, desc.Format);
}
Beispiel #3
0
void GFXD3D11TextureTarget::resolveTo( GFXTextureObject *tex )
{
   GFXDEBUGEVENT_SCOPE( GFXPCD3D11TextureTarget_resolveTo, ColorI::RED );

   if ( mTargets[Color0] == NULL )
      return;

   D3D11_TEXTURE2D_DESC desc;
   mTargets[Color0]->GetDesc(&desc);
   D3D11DEVICECONTEXT->CopySubresourceRegion(((GFXD3D11TextureObject*)(tex))->get2DTex(), 0, 0, 0, 0, mTargets[Color0], 0, NULL);
      
}
Beispiel #4
0
void SkyBox::_renderObject( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *mi )
{
   GFXDEBUGEVENT_SCOPE( SkyBox_RenderObject, ColorF::WHITE );

   GFXTransformSaver saver;  
   GFX->setVertexBuffer( mVB );         

   MatrixF worldMat = MatrixF::Identity;
   worldMat.setPosition( state->getCameraPosition() );

   SceneData sgData;
   sgData.init( state );
   sgData.objTrans = &worldMat;

   mMatrixSet->restoreSceneViewProjection();
   mMatrixSet->setWorld( worldMat );
   if ( state->isReflectPass() )
      mMatrixSet->setProjection( state->getSceneManager()->getNonClipProjection() );

   while ( mMatInstance->setupPass( state, sgData ) )
   {         
      mMatInstance->setTransforms( *mMatrixSet, state );
      mMatInstance->setSceneInfo( state, sgData );

      GFX->drawPrimitive( GFXTriangleList, 0, mPrimCount );     
   }

   // Draw render band.
   if ( mFogBandHeight > 0 && mFogBandMatInst )
   {
      const FogData &fog = state->getSceneManager()->getFogData();
      if ( mLastFogColor != fog.color )
      {
         mLastFogColor = fog.color;
         _initRender();
      }

      // Just need it to follow the camera... no rotation.
      MatrixF camPosMat( MatrixF::Identity );
      camPosMat.setPosition( worldMat.getPosition() );
      sgData.objTrans = &camPosMat;
      mMatrixSet->setWorld( *sgData.objTrans );

      while ( mFogBandMatInst->setupPass( state, sgData ) )
      {
         mFogBandMatInst->setTransforms( *mMatrixSet, state );
         mFogBandMatInst->setSceneInfo( state, sgData );

         GFX->setVertexBuffer( mFogBandVB );      
         GFX->drawPrimitive( GFXTriangleList, 0, 16 );
      }
   }
}
void GFXPCD3D9TextureTarget::attachTexture( RenderSlot slot, GFXCubemap *tex, U32 face, U32 mipLevel/*=0*/ )
{
   GFXDEBUGEVENT_SCOPE( GFXPCD3D9TextureTarget_attachTexture_Cubemap, ColorI::RED );

   AssertFatal(slot < MaxRenderSlotId, "GFXPCD3D9TextureTarget::attachTexture - out of range slot.");

   // Mark state as dirty so device can know to update.
   invalidateState();

   // Release what we had, it's definitely going to change.
   mDevice->destroyD3DResource( mTargets[slot] ); // SAFE_RELEASE
   mTargets[slot] = NULL;
   mResolveTargets[slot] = NULL;

   // Cast the texture object to D3D...
   AssertFatal(!tex || dynamic_cast<GFXD3D9Cubemap*>(tex), 
      "GFXD3DTextureTarget::attachTexture - invalid cubemap object.");

   GFXD3D9Cubemap *cube = static_cast<GFXD3D9Cubemap*>(tex);

   if(slot == Color0)
   {
      mTargetSize = Point2I::Zero;
      mTargetFormat = GFXFormatR8G8B8A8;
   }

   // Are we clearing?
   if(!tex)
   {
      // Yup - just exit, it'll stay NULL.      
      return;
   }

   D3D9Assert(cube->mCubeTex->GetCubeMapSurface( (D3DCUBEMAP_FACES)face, mipLevel, &mTargets[slot] ),
      "GFXD3DTextureTarget::attachTexture - could not get surface level for the passed texture!");

   // Update surface size
   if(slot == Color0)
   {
      IDirect3DSurface9 *surface = mTargets[Color0];
      if ( surface )
      {
         D3DSURFACE_DESC sd;
         surface->GetDesc(&sd);
         mTargetSize = Point2I(sd.Width, sd.Height);

         S32 format = sd.Format;
         GFXREVERSE_LOOKUP( GFXD3D9TextureFormat, GFXFormat, format );
         mTargetFormat = (GFXFormat)format;
      }
   }
}
void RenderImposterMgr::render( SceneState *state )
{
   PROFILE_SCOPE( RenderImposterMgr_Render );

   if (  !mElementList.size() ||
         (  !mDiffuseShaderState.mShader && 
            !mDiffuseShaderState.init( "TSImposterShaderData", NULL ) ) )
      return;

   GFXDEBUGEVENT_SCOPE( RenderImposterMgr_Render, ColorI::RED );

   _innerRender( state, mDiffuseShaderState );
}
void GFXPCD3D9WindowTarget::resolveTo( GFXTextureObject *tex )
{
   GFXDEBUGEVENT_SCOPE( GFXPCD3D9WindowTarget_resolveTo, ColorI::RED );

   IDirect3DSurface9 *surf;
   D3D9Assert( ((GFXD3D9TextureObject*)(tex))->get2DTex()->GetSurfaceLevel( 0, &surf ),
      "GFXPCD3D9WindowTarget::resolveTo() - GetSurfaceLevel failed!" );

   D3D9Assert( mDevice->getDevice()->StretchRect( mBackbuffer, NULL, surf, NULL, D3DTEXF_NONE ),
      "GFXPCD3D9WindowTarget::resolveTo() - StretchRect failed!" );

   surf->Release();    
}
Beispiel #8
0
void CubeReflector::updateReflection( const ReflectParams &params )
{
   GFXDEBUGEVENT_SCOPE( CubeReflector_UpdateReflection, ColorI::WHITE );

   mIsRendering = true;

   // Setup textures and targets...
   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 );  

   const GFXFormat reflectFormat = REFLECTMGR->getReflectFormat();

   if (  texResize || 
         cubemap.isNull() ||
         cubemap->getFormat() != reflectFormat )
   {
      cubemap = GFX->createCubemap();
      cubemap->initDynamic( texDim, reflectFormat );
   }
   
   GFXTexHandle depthBuff = LightShadowMap::_getDepthTarget( texDim, texDim );

   if ( renderTarget.isNull() )
      renderTarget = GFX->allocRenderToTextureTarget();   

   GFX->pushActiveRenderTarget();
   renderTarget->attachTexture( GFXTextureTarget::DepthStencil, depthBuff );

  
   F32 oldVisibleDist = gClientSceneGraph->getVisibleDistance();
   gClientSceneGraph->setVisibleDistance( mDesc->farDist );   


   for ( U32 i = 0; i < 6; i++ )
      updateFace( params, i );
   

   GFX->popActiveRenderTarget();

   gClientSceneGraph->setVisibleDistance(oldVisibleDist);

   mIsRendering = false;
   mLastTexSize = texDim;
}
void RenderImposterMgr::_renderPrePass( const SceneState *state, RenderPrePassMgr *prePassBin, bool startPrePass )
{
   PROFILE_SCOPE( RenderImposterMgr_RenderPrePass );

   if (  !mElementList.size() || !startPrePass ||
         (  !mPrePassShaderState.mShader && 
            !mPrePassShaderState.init( "TSImposterPrePassShaderData", 
               &prePassBin->getOpaqueStenciWriteDesc() ) ) )
      return;

   GFXDEBUGEVENT_SCOPE( RenderImposterMgr_RenderPrePass, ColorI::RED );

   _innerRender( state, mPrePassShaderState );
}
Beispiel #10
0
void GFXPCD3D9WindowTarget::activate()
{
   GFXDEBUGEVENT_SCOPE( GFXPCD3D9WindowTarget_activate, ColorI::RED );

   LPDIRECT3DDEVICE9 d3dDevice = mDevice->getDevice();
   
   // In debug lets do a complete test to be sure we don't
   // have a bad depth format for this display mode.   
   #ifdef TORQUE_DEBUG
      if ( mDepthStencil && mBackbuffer )
      {

         D3DSURFACE_DESC desc;
         D3D9Assert( mBackbuffer->GetDesc( &desc ), 
            "GFXPCD3D9TextureTarget::activate() - Failed to get surface description!");
         D3DFORMAT renderFormat = desc.Format;

         D3D9Assert( mDepthStencil->GetDesc( &desc ), 
            "GFXPCD3D9TextureTarget::activate() - Failed to get surface description!");
         D3DFORMAT depthFormat = desc.Format;

         HRESULT hr = mDevice->getD3D()->CheckDepthStencilMatch(  mDevice->getAdaterIndex(),
                                                                  D3DDEVTYPE_HAL,
                                                                  mDevice->mDisplayMode.Format,
                                                                  renderFormat,
                                                                  depthFormat );

         D3D9Assert( hr, "GFXPCD3D9WindowTarget::activate() - Bad depth format for this back buffer!" );
      }
   #endif
   
   D3D9Assert( d3dDevice->SetRenderTarget( 0, mBackbuffer ), 
      "GFXPCD3D9WindowTarget::activate() - Failed to set backbuffer target!" );

   D3D9Assert( d3dDevice->SetDepthStencilSurface( mDepthStencil ), 
      "GFXPCD3D9WindowTarget::activate() - Failed to set depthstencil target!" );

   D3DPRESENT_PARAMETERS pp;

   mSwapChain->GetPresentParameters(&pp);

   // Update our video mode here, too.
   GFXVideoMode vm;
   vm = mWindow->getVideoMode();
   vm.resolution.x = pp.BackBufferWidth;
   vm.resolution.y = pp.BackBufferHeight;
   vm.fullScreen = !pp.Windowed;

   mSize = vm.resolution;
}
Beispiel #11
0
void GFXD3D11TextureTarget::resolve()
{
   GFXDEBUGEVENT_SCOPE( GFXPCD3D11TextureTarget_resolve, ColorI::RED );

   for (U32 i = 0; i < MaxRenderSlotId; i++)
   {
      // We use existance @ mResolveTargets as a flag that we need to copy
      // data from the rendertarget into the texture.
      if (mResolveTargets[i])
      {
         D3D11_TEXTURE2D_DESC desc;
		   mTargets[i]->GetDesc(&desc);
         D3D11DEVICECONTEXT->CopySubresourceRegion(mResolveTargets[i]->get2DTex(), 0, 0, 0, 0, mTargets[i], 0, NULL);
      }
   }
}
void EditTSCtrl::renderMissionArea()
{
   MissionArea* obj = MissionArea::getServerObject();
   if ( !obj )
      return;

   if ( !mRenderMissionArea && !obj->isSelected() )
      return;

   GFXDEBUGEVENT_SCOPE( Editor_renderMissionArea, ColorI::WHITE );

   F32 minHeight = 0.0f;
   F32 maxHeight = 0.0f;

   TerrainBlock* terrain = getActiveTerrain();
   if ( terrain )
   {
      terrain->getMinMaxHeight( &minHeight, &maxHeight );
      Point3F pos = terrain->getPosition();

      maxHeight += pos.z + mMissionAreaHeightAdjust;
      minHeight += pos.z - mMissionAreaHeightAdjust;
   }

   const RectI& area = obj->getArea();
   Box3F areaBox( area.point.x,
                  area.point.y,
                  minHeight,
                  area.point.x + area.extent.x,
                  area.point.y + area.extent.y,
                  maxHeight );

   GFXDrawUtil* drawer = GFX->getDrawUtil();

   GFXStateBlockDesc desc;
   desc.setCullMode( GFXCullNone );
   desc.setBlend( true );
   desc.setZReadWrite( false, false );

   desc.setFillModeSolid();
   drawer->drawCube( desc, areaBox, mMissionAreaFillColor );

   desc.setFillModeWireframe();
   drawer->drawCube( desc, areaBox, mMissionAreaFrameColor );
}
void MetaShapeRenderer::render( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat )
{
   if ( overrideMat )
      return;

	PROFILE_SCOPE(MetaShapeRenderer_Render);

	mPolyList.render();

   if ( mVertexBuffer.isNull() )
      return;

   // Set up a GFX debug event (this helps with debugging rendering events in external tools)
   GFXDEBUGEVENT_SCOPE( MetaShapeRenderer_Render, ColorI::RED );

   // GFXTransformSaver is a handy helper class that restores
   // the current GFX matrices to their original values when
   // it goes out of scope at the end of the function
   GFXTransformSaver saver;

   // Calculate our object to world transform matrix
   MatrixF objectToWorld = getRenderTransform();
   objectToWorld.scale( getScale() );

   // Apply our object transform
   GFX->multWorld( objectToWorld );

   // Deal with reflect pass otherwise
   // set the normal StateBlock
   if ( state->isReflectPass() )
      GFX->setStateBlock( mReflectSB );
   else
      GFX->setStateBlock( mNormalSB );

   // Set up the "generic" shaders
   // These handle rendering on GFX layers that don't support
   // fixed function. Otherwise they disable shaders.
   GFX->setupGenericShaders( GFXDevice::GSModColorTexture );

   // Set the vertex buffer
   GFX->setVertexBuffer( mVertexBuffer );

   // Draw our triangles
   GFX->drawPrimitive( GFXTriangleList, 0, 12 );
}
void ForcedMaterialMeshMgr::render(SceneRenderState * state)
{
   PROFILE_SCOPE(ForcedMaterialMeshMgr_render);

   if(!mOverrideInstance && mOverrideMaterial.isValid())
   {
      mOverrideInstance = mOverrideMaterial->createMatInstance();
      mOverrideInstance->init( MATMGR->getDefaultFeatures(), getGFXVertexFormat<GFXVertexPNTBT>() );
   }

   // Early out if nothing to draw.
   if(!mElementList.size() || !mOverrideInstance)
      return;

   GFXDEBUGEVENT_SCOPE(ForcedMaterialMeshMgr_Render, ColorI::RED);

   // Automagically save & restore our viewport and transforms.
   GFXTransformSaver saver;

   // init loop data
   SceneData sgData;
   sgData.init( state );

   MeshRenderInst *ri = static_cast<MeshRenderInst*>(mElementList[0].inst);
   setupSGData( ri, sgData );

   while (mOverrideInstance->setupPass(state, sgData))
   {   
      for( U32 j=0; j<mElementList.size(); j++)
      {
         MeshRenderInst* passRI = static_cast<MeshRenderInst*>(mElementList[j].inst);
         if(passRI->primBuff->getPointer()->mPrimitiveArray[passRI->primBuffIndex].numVertices < 1)
            continue;

         getRenderPass()->getMatrixSet().setWorld(*passRI->objectToWorld);
         getRenderPass()->getMatrixSet().setView(*passRI->worldToCamera);
         getRenderPass()->getMatrixSet().setProjection(*passRI->projection);
         mOverrideInstance->setTransforms(getRenderPass()->getMatrixSet(), state, sgData);

         mOverrideInstance->setBuffers(passRI->vertBuff, passRI->primBuff);
         GFX->drawPrimitive( passRI->primBuffIndex );                  
      }
   }
}
Beispiel #15
0
void GFXDrawUtil::_drawWirePolyhedron( const GFXStateBlockDesc &desc, const AnyPolyhedron &poly, const ColorI &color, const MatrixF *xfm )
{
   GFXDEBUGEVENT_SCOPE( GFXDrawUtil_DrawWirePolyhedron, ColorI::GREEN );

   const U32 numEdges = poly.getNumEdges();
   const Point3F* points = poly.getPoints();
   const Polyhedron::Edge* edges = poly.getEdges();

   // Allocate a temporary vertex buffer.

   GFXVertexBufferHandle< GFXVertexPC > verts( mDevice, numEdges * 2, GFXBufferTypeVolatile);

   // Fill it with the vertices for the edges.
   
   verts.lock();
   for( U32 i = 0; i < numEdges; ++ i )
   {
      const U32 nvert = i * 2;
      verts[ nvert + 0 ].point = points[ edges[ i ].vertex[ 0 ] ];
      verts[ nvert + 0 ].color = color;

      verts[ nvert + 1 ].point = points[ edges[ i ].vertex[ 1 ] ];
      verts[ nvert + 1 ].color = color;
   }

   if( xfm )
   {
      for( U32 i = 0; i < numEdges; ++ i )
      {
         xfm->mulP( verts[ i + 0 ].point );
         xfm->mulP( verts[ i + 1 ].point );
      }
   }
   verts.unlock();

   // Render the line list.

   mDevice->setStateBlockByDesc( desc );

   mDevice->setVertexBuffer( verts );
   mDevice->setupGenericShaders();

   mDevice->drawPrimitive( GFXLineList, 0, numEdges );
}
void ImposterCapture::_renderToTexture( GFXTexHandle texHandle, GBitmap *outBitmap, const ColorI &color )
{
   GFXDEBUGEVENT_SCOPE( ImposterCapture_RenderToTexture, ColorI::RED );
   PROFILE_SCOPE( ImposterCapture_RenderToTexture );

   mRenderTarget->attachTexture( GFXTextureTarget::Color0, texHandle );
   mRenderTarget->attachTexture( GFXTextureTarget::DepthStencil, mDepthBuffer );
   GFX->setActiveRenderTarget( mRenderTarget );

   GFX->clear( GFXClearZBuffer | GFXClearStencil | GFXClearTarget, color, 1.0f, 0 );

   mShapeInstance->render( mRData, mDl, 1.0f );

   mState->getRenderPass()->renderPass( mState );

   mRenderTarget->resolve();

   texHandle->copyToBmp( outBitmap );
}
Beispiel #17
0
void GFXD3D11WindowTarget::activate()
{
   GFXDEBUGEVENT_SCOPE(GFXPCD3D11WindowTarget_activate, ColorI::RED);

   //clear ther rendertargets first
   ID3D11RenderTargetView* rtViews[8] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };

   D3D11DEVICECONTEXT->OMSetRenderTargets(8, rtViews, NULL);
   D3D11DEVICECONTEXT->OMSetRenderTargets(1, &D3D11->mDeviceBackBufferView, D3D11->mDeviceDepthStencilView);

   DXGI_SWAP_CHAIN_DESC pp;
   D3D11->mSwapChain->GetDesc(&pp);

   // Update our video mode here, too.
   GFXVideoMode vm;
   vm = mWindow->getVideoMode();
   vm.resolution.x = pp.BufferDesc.Width;
   vm.resolution.y = pp.BufferDesc.Height;
   vm.fullScreen = !pp.Windowed;
   mSize = vm.resolution;
}
Beispiel #18
0
void GFXPCD3D9TextureTarget::resolve()
{
   GFXDEBUGEVENT_SCOPE( GFXPCD3D9TextureTarget_resolve, ColorI::RED );

   for (U32 i = 0; i < MaxRenderSlotId; i++)
   {
      // We use existance @ mResolveTargets as a flag that we need to copy
      // data from the rendertarget into the texture.
      if (mResolveTargets[i])
      {
         IDirect3DSurface9 *surf;
         D3D9Assert( mResolveTargets[i]->get2DTex()->GetSurfaceLevel( 0, &surf ),
            "GFXPCD3D9TextureTarget::resolve() - GetSurfaceLevel failed!" );

         D3D9Assert( mDevice->getDevice()->StretchRect( mTargets[i], NULL, surf, NULL, D3DTEXF_NONE ),
            "GFXPCD3D9TextureTarget::resolve() - StretchRect failed!" );

         surf->Release();
      }
   }
}
Beispiel #19
0
void GFXD3D11TextureTarget::activate()
{
   GFXDEBUGEVENT_SCOPE( GFXPCD3D11TextureTarget_activate, ColorI::RED );

   AssertFatal( mTargets[GFXTextureTarget::Color0], "GFXD3D11TextureTarget::activate() - You can never have a NULL primary render target!" );
  
   // Clear the state indicator.
   stateApplied();
   
   // Now set all the new surfaces into the appropriate slots.
   ID3D11RenderTargetView* rtViews[MaxRenderSlotId] = { NULL, NULL, NULL, NULL, NULL, NULL};

   ID3D11DepthStencilView* dsView = (ID3D11DepthStencilView*)(mTargetViews[GFXTextureTarget::DepthStencil]);
   for (U32 i = 0; i < 4; i++)
   {
      rtViews[i] = (ID3D11RenderTargetView*)mTargetViews[GFXTextureTarget::Color0 + i];
   }

   D3D11DEVICECONTEXT->OMSetRenderTargets(MaxRenderSlotId, rtViews, dsView);

}
Beispiel #20
0
void GFXPCD3D9TextureTarget::activate()
{
   GFXDEBUGEVENT_SCOPE( GFXPCD3D9TextureTarget_activate, ColorI::RED );

   AssertFatal( mTargets[GFXTextureTarget::Color0], 
      "GFXPCD3D9TextureTarget::activate() - You can never have a NULL primary render target!" );

   const U32 NumRenderTargets = getMin( mDevice->getNumRenderTargets(), (U32)Color4 - Color0 );

   LPDIRECT3DDEVICE9 d3dDevice = mDevice->getDevice();

   // Clear the state indicator.
   stateApplied();

   IDirect3DSurface9 *depth = mTargets[GFXTextureTarget::DepthStencil];
   
   // In debug lets do a complete test to be sure we don't
   // have a bad depth format for this display mode.   
   #ifdef TORQUE_DEBUG

      if ( depth && mTargets[GFXTextureTarget::Color0] )
      {
         D3DSURFACE_DESC desc;
         D3D9Assert( mTargets[GFXTextureTarget::Color0]->GetDesc( &desc ), 
            "GFXPCD3D9TextureTarget::activate() - Failed to get surface description!");
         D3DFORMAT renderFormat = desc.Format;

         D3D9Assert( depth->GetDesc( &desc ), 
            "GFXPCD3D9TextureTarget::activate() - Failed to get surface description!");
         D3DFORMAT depthFormat = desc.Format;

         HRESULT hr = mDevice->getD3D()->CheckDepthStencilMatch(  mDevice->getAdaterIndex(),
                                                                  D3DDEVTYPE_HAL,
                                                                  mDevice->mDisplayMode.Format,
                                                                  renderFormat,
                                                                  depthFormat );
                                                                  
         D3D9Assert( hr, "GFXPCD3D9TextureTarget::activate() - Bad depth format for this target!" );
      }

   #endif

   // First clear the non-primary targets to make the debug DX runtime happy.
   for(U32 i = 1; i < NumRenderTargets; i++)
      D3D9Assert(d3dDevice->SetRenderTarget( i, NULL ), 
         avar("GFXPCD3D9TextureTarget::activate() - failed to clear texture target %d!", i) );

   // Now set all the new surfaces into the appropriate slots.
   for(U32 i = 0; i < NumRenderTargets; i++)
   {
      IDirect3DSurface9 *target = mTargets[GFXTextureTarget::Color0 + i];
      if ( target )
      {
         D3D9Assert(d3dDevice->SetRenderTarget(i, target), 
            avar("GFXPCD3D9TextureTarget::activate() - failed to set slot %d for texture target!", i) );
      }
   }

   // TODO: This is often the same shared depth buffer used by most
   // render targets.  Are we getting performance hit from setting it
   // multiple times... aside from the function call?

   D3D9Assert(d3dDevice->SetDepthStencilSurface( depth ), 
      "GFXPCD3D9TextureTarget::activate() - failed to set depthstencil target!" );
}
//-----------------------------------------------------------------------------
// render
//-----------------------------------------------------------------------------
void RenderMeshMgr::render(SceneRenderState * state)
{
   PROFILE_SCOPE(RenderMeshMgr_render);

   // Early out if nothing to draw.
   if(!mElementList.size())
      return;


   GFXDEBUGEVENT_SCOPE( RenderMeshMgr_Render, ColorI::GREEN );

   // Automagically save & restore our viewport and transforms.
   GFXTransformSaver saver;

   // Restore transforms
   MatrixSet &matrixSet = getRenderPass()->getMatrixSet();
   matrixSet.restoreSceneViewProjection();

   // init loop data
   GFXTextureObject *lastLM = NULL;
   GFXCubemap *lastCubemap = NULL;
   GFXTextureObject *lastReflectTex = NULL;
   GFXTextureObject *lastMiscTex = NULL;

   SceneData sgData;
   sgData.init( state );

   U32 binSize = mElementList.size();

   for( U32 j=0; j<binSize; )
   {
      MeshRenderInst *ri = static_cast<MeshRenderInst*>(mElementList[j].inst);

      setupSGData( ri, sgData );
      BaseMatInstance *mat = ri->matInst;

      // If we have an override delegate then give it a 
      // chance to swap the material with another.
      if ( mMatOverrideDelegate )
      {
         mat = mMatOverrideDelegate( mat );
         if ( !mat )
         {
            j++;
            continue;
         }
      }

      if( !mat )
         mat = MATMGR->getWarningMatInstance();


      U32 matListEnd = j;
      lastMiscTex = sgData.miscTex;
      U32 a;

      while( mat && mat->setupPass(state, sgData ) )
      {
         for( a=j; a<binSize; a++ )
         {
            MeshRenderInst *passRI = static_cast<MeshRenderInst*>(mElementList[a].inst);

            // Check to see if we need to break this batch.
            if (  newPassNeeded( ri, passRI ) ||
                  lastMiscTex != passRI->miscTex )
            {
               lastLM = NULL;
               break;
            }

            matrixSet.setWorld(*passRI->objectToWorld);
            matrixSet.setView(*passRI->worldToCamera);
            matrixSet.setProjection(*passRI->projection);
            mat->setTransforms(matrixSet, state);

            setupSGData( passRI, sgData );
            mat->setSceneInfo( state, sgData );

            // If we're instanced then don't render yet.
            if ( mat->isInstanced() )
            {
               // Let the material increment the instance buffer, but
               // break the batch if it runs out of room for more.
               if ( !mat->stepInstance() )
               {
                  a++;
                  break;
               }

               continue;
            }

            // TODO: This could proably be done in a cleaner way.
            //
            // This section of code is dangerous, it overwrites the
            // lightmap values in sgData.  This could be a problem when multiple
            // render instances use the same multi-pass material.  When
            // the first pass is done, setupPass() is called again on
            // the material, but the lightmap data has been changed in
            // sgData to the lightmaps in the last renderInstance rendered.

            // This section sets the lightmap data for the current batch.
            // For the first iteration, it sets the same lightmap data,
            // however the redundancy will be caught by GFXDevice and not
            // actually sent to the card.  This is done for simplicity given
            // the possible condition mentioned above.  Better to set always
            // than to get bogged down into special case detection.
            //-------------------------------------
            bool dirty = false;

            // set the lightmaps if different
            if( passRI->lightmap && passRI->lightmap != lastLM )
            {
               sgData.lightmap = passRI->lightmap;
               lastLM = passRI->lightmap;
               dirty = true;
            }

            // set the cubemap if different.
            if ( passRI->cubemap != lastCubemap )
            {
               sgData.cubemap = passRI->cubemap;
               lastCubemap = passRI->cubemap;
               dirty = true;
            }

            if ( passRI->reflectTex != lastReflectTex )
            {
               sgData.reflectTex = passRI->reflectTex;
               lastReflectTex = passRI->reflectTex;
               dirty = true;
            }

            if ( dirty )
               mat->setTextureStages( state, sgData );

            // Setup the vertex and index buffers.
            mat->setBuffers( passRI->vertBuff, passRI->primBuff );

            // Render this sucker.
            if ( passRI->prim )
               GFX->drawPrimitive( *passRI->prim );
            else
               GFX->drawPrimitive( passRI->primBuffIndex );
         }

         // Draw the instanced batch.
         if ( mat->isInstanced() )
         {
            // Sets the buffers including the instancing stream.
            mat->setBuffers( ri->vertBuff, ri->primBuff );

            // Render the instanced stream.
            if ( ri->prim )
               GFX->drawPrimitive( *ri->prim );
            else
               GFX->drawPrimitive( ri->primBuffIndex );
         }

         matListEnd = a;
      }

      // force increment if none happened, otherwise go to end of batch
      j = ( j == matListEnd ) ? j+1 : matListEnd;
   }
}
Beispiel #22
0
void RenderGlowMgr::render( SceneRenderState *state )
{
   PROFILE_SCOPE( RenderGlowMgr_Render );
   
   if ( !isGlowEnabled() )
      return;

   const U32 binSize = mElementList.size();

   // If this is a non-diffuse pass or we have no objects to
   // render then tell the effect to skip rendering.
   if ( !state->isDiffusePass() || binSize == 0 )
   {
      getGlowEffect()->setSkip( true );
      return;
   }

   GFXDEBUGEVENT_SCOPE( RenderGlowMgr_Render, ColorI::GREEN );

   GFXTransformSaver saver;

   // Tell the superclass we're about to render, preserve contents
   const bool isRenderingToTarget = _onPreRender( state, true );

   // Clear all the buffers to black.
   GFX->clear( GFXClearTarget, ColorI::BLACK, 1.0f, 0);

   // Restore transforms
   MatrixSet &matrixSet = getRenderPass()->getMatrixSet();
   matrixSet.restoreSceneViewProjection();

   // init loop data
   SceneData sgData;
   sgData.init( state, SceneData::GlowBin );

   for( U32 j=0; j<binSize; )
   {
      MeshRenderInst *ri = static_cast<MeshRenderInst*>(mElementList[j].inst);

      setupSGData( ri, sgData );

      BaseMatInstance *mat = ri->matInst;
      GlowMaterialHook *hook = mat->getHook<GlowMaterialHook>();
      if ( !hook )
      {
         hook = new GlowMaterialHook( ri->matInst );
         ri->matInst->addHook( hook );
      }
      BaseMatInstance *glowMat = hook->getMatInstance();

      U32 matListEnd = j;

      while( glowMat && glowMat->setupPass( state, sgData ) )
      {
         U32 a;
         for( a=j; a<binSize; a++ )
         {
            MeshRenderInst *passRI = static_cast<MeshRenderInst*>(mElementList[a].inst);

            if ( newPassNeeded( ri, passRI ) )
               break;

            matrixSet.setWorld(*passRI->objectToWorld);
            matrixSet.setView(*passRI->worldToCamera);
            matrixSet.setProjection(*passRI->projection);
            glowMat->setTransforms(matrixSet, state);

            glowMat->setSceneInfo(state, sgData);
            glowMat->setBuffers(passRI->vertBuff, passRI->primBuff);

            if ( passRI->prim )
               GFX->drawPrimitive( *passRI->prim );
            else
               GFX->drawPrimitive( passRI->primBuffIndex );
         }
         matListEnd = a;
         setupSGData( ri, sgData );
      }

      // force increment if none happened, otherwise go to end of batch
      j = ( j == matListEnd ) ? j+1 : matListEnd;
   }

   // Finish up.
   if ( isRenderingToTarget )
      _onPostRender();

   // Make sure the effect is gonna render.
   getGlowEffect()->setSkip( false );
}
Beispiel #23
0
void GFXPCD3D9TextureTarget::attachTexture( RenderSlot slot, GFXTextureObject *tex, U32 mipLevel/*=0*/, U32 zOffset /*= 0*/ )
{
   GFXDEBUGEVENT_SCOPE( GFXPCD3D9TextureTarget_attachTexture, ColorI::RED );

   AssertFatal(slot < MaxRenderSlotId, "GFXPCD3D9TextureTarget::attachTexture - out of range slot.");

   // TODO:  The way this is implemented... you can attach a texture 
   // object multiple times and it will release and reset it.
   //
   // We should rework this to detect when no change has occured
   // and skip out early.

   // Mark state as dirty so device can know to update.
   invalidateState();

   // Release what we had, it's definitely going to change.
   mDevice->destroyD3DResource( mTargets[slot] ); // SAFE_RELEASE
   mTargets[slot] = NULL;
   mResolveTargets[slot] = NULL;

   if(slot == Color0)
   {
      mTargetSize = Point2I::Zero;
      mTargetFormat = GFXFormatR8G8B8A8;
   }

   // Are we clearing?
   if(!tex)
   {
      // Yup - just exit, it'll stay NULL.      
      return;
   }


   // Take care of default targets
   if( tex == GFXTextureTarget::sDefaultDepthStencil )
   {
      mTargets[slot] = mDevice->mDeviceDepthStencil;
      mTargets[slot]->AddRef();
   }
   else
   {
      // Cast the texture object to D3D...
      AssertFatal(dynamic_cast<GFXD3D9TextureObject*>(tex), 
         "GFXPCD3D9TextureTarget::attachTexture - invalid texture object.");

      GFXD3D9TextureObject *d3dto = static_cast<GFXD3D9TextureObject*>(tex);

      // Grab the surface level.
      if( slot == DepthStencil )
      {
         mTargets[slot] = d3dto->getSurface();
         if ( mTargets[slot] )
            mTargets[slot]->AddRef();
      }
      else
      {
         // getSurface will almost always return NULL. It will only return non-NULL
         // if the surface that it needs to render to is different than the mip level
         // in the actual texture. This will happen with MSAA.
         if( d3dto->getSurface() == NULL )
         {
            D3D9Assert(d3dto->get2DTex()->GetSurfaceLevel(mipLevel, &mTargets[slot]), 
               "GFXPCD3D9TextureTarget::attachTexture - could not get surface level for the passed texture!");
         } 
         else 
         {
            mTargets[slot] = d3dto->getSurface();
            mTargets[slot]->AddRef();

            // Only assign resolve target if d3dto has a surface to give us.
            //
            // That usually means there is an MSAA target involved, which is why
            // the resolve is needed to get the data out of the target.
            mResolveTargets[slot] = d3dto;

            if ( tex && slot == Color0 )
            {
               mTargetSize.set( tex->getSize().x, tex->getSize().y );
               mTargetFormat = tex->getFormat();
            }
         }           
      }

      // Update surface size
      if(slot == Color0)
      {
         IDirect3DSurface9 *surface = mTargets[Color0];
         if ( surface )
         {
            D3DSURFACE_DESC sd;
            surface->GetDesc(&sd);
            mTargetSize = Point2I(sd.Width, sd.Height);

            S32 format = sd.Format;
            GFXREVERSE_LOOKUP( GFXD3D9TextureFormat, GFXFormat, format );
            mTargetFormat = (GFXFormat)format;
         }
      }
   }
}
void RenderTranslucentMgr::render( SceneRenderState *state )
{
    PROFILE_SCOPE(RenderTranslucentMgr_render);

    // Early out if nothing to draw.
    if(!mElementList.size())
        return;

    GFXDEBUGEVENT_SCOPE(RenderTranslucentMgr_Render, ColorI::BLUE);

    // Find the particle render manager (if we don't have it)
    if(mParticleRenderMgr == NULL)
    {
        RenderPassManager *rpm = state->getRenderPass();
        for( U32 i = 0; i < rpm->getManagerCount(); i++ )
        {
            RenderBinManager *bin = rpm->getManager(i);
            if( bin->getRenderInstType() == RenderParticleMgr::RIT_Particles )
            {
                mParticleRenderMgr = reinterpret_cast<RenderParticleMgr *>(bin);
                break;
            }
        }
    }

    GFXTransformSaver saver;

    SceneData sgData;
    sgData.init( state );

    GFXVertexBuffer * lastVB = NULL;
    GFXPrimitiveBuffer * lastPB = NULL;

    // Restore transforms
    MatrixSet &matrixSet = getRenderPass()->getMatrixSet();
    matrixSet.restoreSceneViewProjection();

    U32 binSize = mElementList.size();
    for( U32 j=0; j<binSize; )
    {
        RenderInst *baseRI = mElementList[j].inst;

        U32 matListEnd = j;

        // render these separately...
        if ( baseRI->type == RenderPassManager::RIT_ObjectTranslucent )
        {
            ObjectRenderInst* objRI = static_cast<ObjectRenderInst*>(baseRI);
            objRI->renderDelegate( objRI, state, NULL );

            lastVB = NULL;
            lastPB = NULL;
            j++;
            continue;
        }
        //Volumetric Fog Add
        else if (baseRI->type == RenderPassManager::RIT_VolumetricFog)
        {
            ObjectRenderInst* objRI = static_cast<ObjectRenderInst*>(baseRI);
            objRI->renderDelegate(objRI,state,NULL);

            lastVB = NULL;
            lastPB = NULL;
            j++;
            continue;
        }
        //Volumetric Fog Add
        else if ( baseRI->type == RenderPassManager::RIT_Particle )
        {
            ParticleRenderInst *ri = static_cast<ParticleRenderInst*>(baseRI);

            // Tell Particle RM to draw the system. (This allows the particle render manager
            // to manage drawing offscreen particle systems, and allows the systems
            // to be composited back into the scene with proper translucent
            // sorting order)
            mParticleRenderMgr->renderInstance(ri, state);

            lastVB = NULL;    // no longer valid, null it
            lastPB = NULL;    // no longer valid, null it

            j++;
            continue;
        }
        else if ( baseRI->type == RenderPassManager::RIT_Translucent )
        {
            MeshRenderInst* ri = static_cast<MeshRenderInst*>(baseRI);
            BaseMatInstance *mat = ri->matInst;

            setupSGData( ri, sgData );

            while( mat->setupPass( state, sgData ) )
            {
                U32 a;
                for( a=j; a<binSize; a++ )
                {
                    RenderInst* nextRI = mElementList[a].inst;
                    if ( nextRI->type != RenderPassManager::RIT_Translucent )
                        break;

                    MeshRenderInst *passRI = static_cast<MeshRenderInst*>(nextRI);

                    // Check to see if we need to break this batch.
                    if ( newPassNeeded( ri, passRI ) )
                        break;

                    // Z sorting and stuff is still not working in this mgr...
                    setupSGData( passRI, sgData );
                    mat->setSceneInfo(state, sgData);
                    matrixSet.setWorld(*passRI->objectToWorld);
                    matrixSet.setView(*passRI->worldToCamera);
                    matrixSet.setProjection(*passRI->projection);
                    mat->setTransforms(matrixSet, state);

                    // If we're instanced then don't render yet.
                    if ( mat->isInstanced() )
                    {
                        // Let the material increment the instance buffer, but
                        // break the batch if it runs out of room for more.
                        if ( !mat->stepInstance() )
                        {
                            a++;
                            break;
                        }

                        continue;
                    }

                    // Setup the vertex and index buffers.
                    mat->setBuffers( passRI->vertBuff, passRI->primBuff );

                    // Render this sucker.
                    if ( passRI->prim )
                        GFX->drawPrimitive( *passRI->prim );
                    else
                        GFX->drawPrimitive( passRI->primBuffIndex );
                }

                // Draw the instanced batch.
                if ( mat->isInstanced() )
                {
                    // Sets the buffers including the instancing stream.
                    mat->setBuffers( ri->vertBuff, ri->primBuff );

                    // Render the instanced stream.
                    if ( ri->prim )
                        GFX->drawPrimitive( *ri->prim );
                    else
                        GFX->drawPrimitive( ri->primBuffIndex );
                }

                matListEnd = a;
            }

            // force increment if none happened, otherwise go to end of batch
            j = ( j == matListEnd ) ? j+1 : matListEnd;
        }
    }
}
Beispiel #25
0
void ReflectionManager::update(  F32 timeSlice, 
                                 const Point2I &resolution, 
                                 const CameraQuery &query )
{
   GFXDEBUGEVENT_SCOPE( UpdateReflections, ColorI::WHITE );

   if ( mReflectors.empty() )
      return;

   PROFILE_SCOPE( ReflectionManager_Update );

   // Calculate our target time from the slice.
   U32 targetMs = timeSlice * smFrameReflectionMS;

   // Setup a culler for testing the 
   // visibility of reflectors.
   Frustum culler;
   culler.set( false,
               query.fov,
               (F32)resolution.x / (F32)resolution.y,
               query.nearPlane, 
               query.farPlane,
               query.cameraMatrix );

   // Manipulate the frustum for tiled screenshots
   const bool screenShotMode = gScreenShot && gScreenShot->isPending();
   if ( screenShotMode )
      gScreenShot->tileFrustum( culler );

   // We use the frame time and not real time 
   // here as this may be called multiple times 
   // within a frame.
   U32 startOfUpdateMs = Platform::getVirtualMilliseconds();

   // Save this for interested parties.
   mLastUpdateMs = startOfUpdateMs;

   ReflectParams refparams;
   refparams.query = &query;
   refparams.viewportExtent = resolution;
   refparams.culler = culler;
   refparams.startOfUpdateMs = startOfUpdateMs;

   // Update the reflection score.
   ReflectorList::iterator reflectorIter = mReflectors.begin();
   for ( ; reflectorIter != mReflectors.end(); reflectorIter++ )
      (*reflectorIter)->calcScore( refparams );

   // Sort them by the score.
   dQsort( mReflectors.address(), mReflectors.size(), sizeof(ReflectorBase*), compareReflectors );
   
   // Update as many reflections as we can 
   // within the target time limit.
   mTimer->getElapsedMs();
   mTimer->reset();
   U32 numUpdated = 0;
   reflectorIter = mReflectors.begin();
   for ( ; reflectorIter != mReflectors.end(); reflectorIter++ )
   {      
      // We're sorted by score... so once we reach 
      // a zero score we have nothing more to update.
      if ( (*reflectorIter)->score <= 0.0f && !screenShotMode )
         break;

      (*reflectorIter)->updateReflection( refparams );
      (*reflectorIter)->lastUpdateMs = startOfUpdateMs;
      numUpdated++;

      // If we run out of update time then stop.
      if ( mTimer->getElapsedMs() > targetMs && !screenShotMode && (*reflectorIter)->score < 1000.0f )
         break;
   }

   // Set metric/debug related script variables...

   U32 numVisible = 0;
   U32 numOccluded = 0;

   reflectorIter = mReflectors.begin();
   for ( ; reflectorIter != mReflectors.end(); reflectorIter++ )
   {      
      ReflectorBase *pReflector = (*reflectorIter);
      if ( pReflector->isOccluded() )
         numOccluded++;
      else
         numVisible++;
   }

#ifdef TORQUE_GATHER_METRICS
   U32 numEnabled = mReflectors.size();   
   U32 totalElapsed = mTimer->getElapsedMs();
   const GFXTextureProfileStats &stats = ReflectRenderTargetProfile.getStats();
   
   F32 mb = ( stats.activeBytes / 1024.0f ) / 1024.0f;
   char temp[256];

   dSprintf( temp, 256, "%s %d %0.2f\n", 
      ReflectRenderTargetProfile.getName().c_str(),
      stats.activeCount,
      mb );   

   Con::setVariable( "$Reflect::textureStats", temp );
   Con::setIntVariable( "$Reflect::renderTargetsAllocated", stats.allocatedTextures );
   Con::setIntVariable( "$Reflect::poolSize", stats.activeCount );
   Con::setIntVariable( "$Reflect::numObjects", numEnabled );   
   Con::setIntVariable( "$Reflect::numVisible", numVisible ); 
   Con::setIntVariable( "$Reflect::numOccluded", numOccluded );
   Con::setIntVariable( "$Reflect::numUpdated", numUpdated );
   Con::setIntVariable( "$Reflect::elapsed", totalElapsed );
#endif
}
void EditTSCtrl::renderGrid()
{
   if( !isOrthoDisplayType() )
      return;

   GFXDEBUGEVENT_SCOPE( Editor_renderGrid, ColorI::WHITE );

   // Calculate the displayed grid size based on view
   F32 drawnGridSize = mGridPlaneSize;
   F32 gridPixelSize = projectRadius(1.0f, mGridPlaneSize);
   if(gridPixelSize < mGridPlaneSizePixelBias)
   {
      U32 counter = 1;
      while(gridPixelSize < mGridPlaneSizePixelBias)
      {
         drawnGridSize = mGridPlaneSize * counter * 10.0f;
         gridPixelSize = projectRadius(1.0f, drawnGridSize);

         ++counter;

         // No infinite loops here
         if(counter > 1000)
            break;
      }
   }

   F32 minorTickSize = 0;
   F32 gridSize = drawnGridSize;
   U32 minorTickMax = mGridPlaneMinorTicks + 1;
   if(minorTickMax > 0)
   {
      minorTickSize = drawnGridSize;
      gridSize = drawnGridSize * minorTickMax;
   }

   // Build the view-based origin
   VectorF dir;
   smCamMatrix.getColumn( 1, &dir );

   Point3F gridPlanePos = smCamPos + dir;
   Point2F size(mOrthoWidth + 2 * gridSize, mOrthoHeight + 2 * gridSize);

   GFXStateBlockDesc desc;
   desc.setBlend( true );
   desc.setZReadWrite( true, false );

   GFXDrawUtil::Plane plane = GFXDrawUtil::PlaneXY;
   switch( getDisplayType() )
   {
      case DisplayTypeTop:
      case DisplayTypeBottom:
         plane = GFXDrawUtil::PlaneXY;
         break;

      case DisplayTypeLeft:
      case DisplayTypeRight:
         plane = GFXDrawUtil::PlaneYZ;
         break;

      case DisplayTypeFront:
      case DisplayTypeBack:
         plane = GFXDrawUtil::PlaneXZ;
         break;
         
      default:
         break;
   }

   GFX->getDrawUtil()->drawPlaneGrid( desc, gridPlanePos, size, Point2F( minorTickSize, minorTickSize ), mGridPlaneMinorTickColor, plane );
   GFX->getDrawUtil()->drawPlaneGrid( desc, gridPlanePos, size, Point2F( gridSize, gridSize ), mGridPlaneColor, plane );
}
void AdvancedLightBinManager::render( SceneRenderState *state )
{
   PROFILE_SCOPE( AdvancedLightManager_Render );

   // Take a look at the SceneRenderState and see if we should skip drawing the pre-pass
   if( state->disableAdvancedLightingBins() )
      return;

   // Automagically save & restore our viewport and transforms.
   GFXTransformSaver saver;

   if( !mLightManager )
      return;

   // Get the sunlight. If there's no sun, and no lights in the bins, no draw
   LightInfo *sunLight = mLightManager->getSpecialLight( LightManager::slSunLightType );
   if( !sunLight && mLightBin.empty() )
      return;

   GFXDEBUGEVENT_SCOPE( AdvancedLightBinManager_Render, ColorI::RED );

   // Tell the superclass we're about to render
   if ( !_onPreRender( state ) )
      return;

   // Clear as long as there isn't MRT population of light buffer with lightmap data
   if ( !MRTLightmapsDuringPrePass() )
      GFX->clear(GFXClearTarget, ColorI(0, 0, 0, 0), 1.0f, 0);

   // Restore transforms
   MatrixSet &matrixSet = getRenderPass()->getMatrixSet();
   matrixSet.restoreSceneViewProjection();

   const MatrixF &worldToCameraXfm = matrixSet.getWorldToCamera();

   // Set up the SG Data
   SceneData sgData;
   sgData.init( state );

   // There are cases where shadow rendering is disabled.
   const bool disableShadows = state->isReflectPass() || ShadowMapPass::smDisableShadows;

   // Pick the right material for rendering the sunlight... we only
   // cast shadows when its enabled and we're not in a reflection.
   LightMaterialInfo *vectorMatInfo;
   if (  sunLight &&
         sunLight->getCastShadows() &&
         !disableShadows &&
         sunLight->getExtended<ShadowMapParams>() )
      vectorMatInfo = _getLightMaterial( LightInfo::Vector, ShadowType_PSSM, false );
   else
      vectorMatInfo = _getLightMaterial( LightInfo::Vector, ShadowType_None, false );

   // Initialize and set the per-frame parameters after getting
   // the vector light material as we use lazy creation.
   _setupPerFrameParameters( state );
   
   // Draw sunlight/ambient
   if ( sunLight && vectorMatInfo )
   {
      GFXDEBUGEVENT_SCOPE( AdvancedLightBinManager_Render_Sunlight, ColorI::RED );

      // Set up SG data
      setupSGData( sgData, state, sunLight );
      vectorMatInfo->setLightParameters( sunLight, state, worldToCameraXfm );

      // Set light holds the active shadow map.       
      mShadowManager->setLightShadowMapForLight( sunLight );

      // Set geometry
      GFX->setVertexBuffer( mFarFrustumQuadVerts );
      GFX->setPrimitiveBuffer( NULL );

      // Render the material passes
      while( vectorMatInfo->matInstance->setupPass( state, sgData ) )
      {
         vectorMatInfo->matInstance->setSceneInfo( state, sgData );
         vectorMatInfo->matInstance->setTransforms( matrixSet, state );
         GFX->drawPrimitive( GFXTriangleFan, 0, 2 );
      }
   }

   // Blend the lights in the bin to the light buffer
   for( LightBinIterator itr = mLightBin.begin(); itr != mLightBin.end(); itr++ )
   {
      LightBinEntry& curEntry = *itr;
      LightInfo *curLightInfo = curEntry.lightInfo;
      LightMaterialInfo *curLightMat = curEntry.lightMaterial;
      const U32 numPrims = curEntry.numPrims;
      const U32 numVerts = curEntry.vertBuffer->mNumVerts;

      // Skip lights which won't affect the scene.
      if ( !curLightMat || curLightInfo->getBrightness() <= 0.001f )
         continue;

      GFXDEBUGEVENT_SCOPE( AdvancedLightBinManager_Render_Light, ColorI::RED );

      setupSGData( sgData, state, curLightInfo );
      curLightMat->setLightParameters( curLightInfo, state, worldToCameraXfm );
      mShadowManager->setLightShadowMap( curEntry.shadowMap );

      // Let the shadow know we're about to render from it.
      if ( curEntry.shadowMap )
         curEntry.shadowMap->preLightRender();

      // Set geometry
      GFX->setVertexBuffer( curEntry.vertBuffer );
      GFX->setPrimitiveBuffer( curEntry.primBuffer );

      // Render the material passes
      while( curLightMat->matInstance->setupPass( state, sgData ) )
      {
         // Set transforms
         matrixSet.setWorld(*sgData.objTrans);
         curLightMat->matInstance->setTransforms(matrixSet, state);
         curLightMat->matInstance->setSceneInfo(state, sgData);

         if(curEntry.primBuffer)
            GFX->drawIndexedPrimitive(GFXTriangleList, 0, 0, numVerts, 0, numPrims);
         else
            GFX->drawPrimitive(GFXTriangleList, 0, numPrims);
      }

      // Tell it we're done rendering.
      if ( curEntry.shadowMap )
         curEntry.shadowMap->postLightRender();
   }

   // Set NULL for active shadow map (so nothing gets confused)
   mShadowManager->setLightShadowMap(NULL);
   GFX->setVertexBuffer( NULL );
   GFX->setPrimitiveBuffer( NULL );

   // Fire off a signal to let others know that light-bin rendering is ending now
   getRenderSignal().trigger(state, this);

   // Finish up the rendering
   _onPostRender();
}
void SceneManager::_renderScene( SceneRenderState* state, U32 objectMask, SceneZoneSpace* baseObject, U32 baseZone )
{
   AssertFatal( this == gClientSceneGraph, "SceneManager::_buildSceneGraph - Only the client scenegraph can support this call!" );

   PROFILE_SCOPE( SceneGraph_batchRenderImages );

   // In the editor, override the type mask for diffuse passes.

   if( gEditingMission && state->isDiffusePass() )
      objectMask = EDITOR_RENDER_TYPEMASK;

   // Update the zoning state and traverse zones.

   if( getZoneManager() )
   {
      // Update.

      getZoneManager()->updateZoningState();

      // If zone culling isn't disabled, traverse the
      // zones now.

      if( !state->getCullingState().disableZoneCulling() )
      {
         // Find the start zone if we haven't already.

         if( !baseObject )
         {
            getZoneManager()->findZone( state->getCameraPosition(), baseObject, baseZone );
            AssertFatal( baseObject != NULL, "SceneManager::_renderScene - findZone() did not return an object" );
         }

         // Traverse zones starting in base object.

         SceneTraversalState traversalState( &state->getCullingState() );
         PROFILE_START( Scene_traverseZones );
         baseObject->traverseZones( &traversalState, baseZone );
         PROFILE_END();

         // Set the scene render box to the area we have traversed.

         state->setRenderArea( traversalState.getTraversedArea() );
      }
   }

   // Set the query box for the container query.  Never
   // make it larger than the frustum's AABB.  In the editor,
   // always query the full frustum as that gives objects
   // the opportunity to render editor visualizations even if
   // they are otherwise not in view.

   if( !state->getFrustum().getBounds().isOverlapped( state->getRenderArea() ) )
   {
      // This handles fringe cases like flying backwards into a zone where you
      // end up pretty much standing on a zone border and looking directly into
      // its "walls".  In that case the traversal area will be behind the frustum
      // (remember that the camera isn't where visibility starts, it's the near
      // distance).

      return;
   }

   Box3F queryBox = state->getFrustum().getBounds();
   if( !gEditingMission )
   {
      queryBox.minExtents.setMax( state->getRenderArea().minExtents );
      queryBox.maxExtents.setMin( state->getRenderArea().maxExtents );
   }

   PROFILE_START( Scene_cullObjects );

   //TODO: We should split the codepaths here based on whether the outdoor zone has visible space.
   //    If it has, we should use the container query-based path.
   //    If it hasn't, we should fill the object list directly from the zone lists which will usually
   //       include way fewer objects.
   
   // Gather all objects that intersect the scene render box.

   mBatchQueryList.clear();
   getContainer()->findObjectList( queryBox, objectMask, &mBatchQueryList );

   // Cull the list.

   U32 numRenderObjects = state->getCullingState().cullObjects(
      mBatchQueryList.address(),
      mBatchQueryList.size(),
      !state->isDiffusePass() ? SceneCullingState::CullEditorOverrides : 0 // Keep forced editor stuff out of non-diffuse passes.
   );

   //HACK: If the control object is a Player and it is not in the render list, force
   // it into it.  This really should be solved by collision bounds being separate from
   // object bounds; only because the Player class is using bounds not encompassing
   // the actual player object is it that we have this problem in the first place.
   // Note that we are forcing the player object into ALL passes here but such
   // is the power of proliferation of things done wrong.

   GameConnection* connection = GameConnection::getConnectionToServer();
   if( connection )
   {
      Player* player = dynamic_cast< Player* >( connection->getControlObject() );
      if( player )
      {
         mBatchQueryList.setSize( numRenderObjects );
         if( !mBatchQueryList.contains( player ) )
         {
            mBatchQueryList.push_back( player );
            numRenderObjects ++;
         }
      }
   }

   PROFILE_END();

   // Render the remaining objects.

   PROFILE_START( Scene_renderObjects );
   state->renderObjects( mBatchQueryList.address(), numRenderObjects );
   PROFILE_END();

   // Render bounding boxes, if enabled.

   if( smRenderBoundingBoxes && state->isDiffusePass() )
   {
      GFXDEBUGEVENT_SCOPE( Scene_renderBoundingBoxes, ColorI::WHITE );

      GameBase* cameraObject = 0;
      if( connection )
         cameraObject = connection->getCameraObject();

      GFXStateBlockDesc desc;
      desc.setFillModeWireframe();
      desc.setZReadWrite( true, false );

      for( U32 i = 0; i < numRenderObjects; ++ i )
      {
         SceneObject* object = mBatchQueryList[ i ];

         // Skip global bounds object.
         if( object->isGlobalBounds() )
            continue;

         // Skip camera object as we're viewing the scene from it.
         if( object == cameraObject )
            continue;

         const Box3F& worldBox = object->getWorldBox();
         GFX->getDrawUtil()->drawObjectBox(
            desc,
            Point3F( worldBox.len_x(), worldBox.len_y(), worldBox.len_z() ),
            worldBox.getCenter(),
            MatrixF::Identity,
            ColorI::WHITE
         );
      }
   }
}
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();
}
Beispiel #30
0
void TerrainBlock::_updateBaseTexture(bool writeToCache)
{
   if ( !mBaseShader && !_initBaseShader() )
      return;

   // This can sometimes occur outside a begin/end scene.
   const bool sceneBegun = GFX->canCurrentlyRender();
   if ( !sceneBegun )
      GFX->beginScene();

   GFXDEBUGEVENT_SCOPE( TerrainBlock_UpdateBaseTexture, ColorI::GREEN );

   PROFILE_SCOPE( TerrainBlock_UpdateBaseTexture );

   GFXTransformSaver saver;

   const U32 maxTextureSize = GFX->getCardProfiler()->queryProfile( "maxTextureSize", 1024 );

   U32 baseTexSize = getNextPow2( mBaseTexSize );
   baseTexSize = getMin( maxTextureSize, baseTexSize );
   Point2I destSize( baseTexSize, baseTexSize );

   // Setup geometry
   GFXVertexBufferHandle<GFXVertexPT> vb;
   {
      F32 copyOffsetX = 2.0f * GFX->getFillConventionOffset() / (F32)destSize.x;
      F32 copyOffsetY = 2.0f * GFX->getFillConventionOffset() / (F32)destSize.y;

      GFXVertexPT points[4];
      points[0].point = Point3F(1.0 - copyOffsetX, -1.0 + copyOffsetY, 0.0);
      points[0].texCoord = Point2F(1.0, 1.0f);
      points[1].point = Point3F(1.0 - copyOffsetX, 1.0 + copyOffsetY, 0.0);
      points[1].texCoord = Point2F(1.0, 0.0f);
      points[2].point = Point3F(-1.0 - copyOffsetX, -1.0 + copyOffsetY, 0.0);
      points[2].texCoord = Point2F(0.0, 1.0f);
      points[3].point = Point3F(-1.0 - copyOffsetX, 1.0 + copyOffsetY, 0.0);
      points[3].texCoord = Point2F(0.0, 0.0f);

      vb.set( GFX, 4, GFXBufferTypeVolatile );
      GFXVertexPT *ptr = vb.lock();
      if(ptr)
      {
         dMemcpy( ptr, points, sizeof(GFXVertexPT) * 4 );
         vb.unlock();
      }
   }

   GFXTexHandle blendTex;

   // If the base texture is already a valid render target then 
   // use it to render to else we create one.
   if (  mBaseTex.isValid() && 
         mBaseTex->isRenderTarget() &&
         mBaseTex->getFormat() == GFXFormatR8G8B8A8 &&
         mBaseTex->getWidth() == destSize.x &&
         mBaseTex->getHeight() == destSize.y )
      blendTex = mBaseTex;
   else
      blendTex.set( destSize.x, destSize.y, GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, "" );

   GFX->pushActiveRenderTarget();   

   // Set our shader stuff
   GFX->setShader( mBaseShader );
   GFX->setShaderConstBuffer( mBaseShaderConsts );
   GFX->setStateBlock( mBaseShaderSB );
   GFX->setVertexBuffer( vb );

   mBaseTarget->attachTexture( GFXTextureTarget::Color0, blendTex );
   GFX->setActiveRenderTarget( mBaseTarget );

   GFX->clear( GFXClearTarget, ColorI(0,0,0,255), 1.0f, 0 );

   GFX->setTexture( 0, mLayerTex );
   mBaseShaderConsts->setSafe( mBaseLayerSizeConst, (F32)mLayerTex->getWidth() );      

   for ( U32 i=0; i < mBaseTextures.size(); i++ )
   {
      GFXTextureObject *tex = mBaseTextures[i];
      if ( !tex )
         continue;

      GFX->setTexture( 1, tex );

      F32 baseSize = mFile->mMaterials[i]->getDiffuseSize();
      F32 scale = 1.0f;
      if ( !mIsZero( baseSize ) )
         scale = getWorldBlockSize() / baseSize;
      
      // A mistake early in development means that texture
      // coords are not flipped correctly.  To compensate
      // we flip the y scale here.
      mBaseShaderConsts->setSafe( mBaseTexScaleConst, Point2F( scale, -scale ) );
      mBaseShaderConsts->setSafe( mBaseTexIdConst, (F32)i );

      GFX->drawPrimitive( GFXTriangleStrip, 0, 2 );
   }

   mBaseTarget->resolve();
   
   GFX->setShader( NULL );
   //GFX->setStateBlock( NULL ); // WHY NOT?
   GFX->setShaderConstBuffer( NULL );
   GFX->setVertexBuffer( NULL );

   GFX->popActiveRenderTarget();

   // End it if we begun it... Yeehaw!
   if ( !sceneBegun )
      GFX->endScene();

   /// Do we cache this sucker?
   if (mBaseTexFormat == NONE || !writeToCache)
   {
      // We didn't cache the result, so set the base texture
      // to the render target we updated.  This should be good
      // for realtime painting cases.
      mBaseTex = blendTex;
   }
   else if (mBaseTexFormat == DDS)
   {
      String cachePath = _getBaseTexCacheFileName();

      FileStream fs;
      if ( fs.open( _getBaseTexCacheFileName(), Torque::FS::File::Write ) )
      {
         // Read back the render target, dxt compress it, and write it to disk.
         GBitmap blendBmp( destSize.x, destSize.y, false, GFXFormatR8G8B8A8 );
         blendTex.copyToBmp( &blendBmp );

         /*
         // Test code for dumping uncompressed bitmap to disk.
         {
         FileStream fs;
         if ( fs.open( "./basetex.png", Torque::FS::File::Write ) )
         {
         blendBmp.writeBitmap( "png", fs );
         fs.close();
         }         
         }
         */

         blendBmp.extrudeMipLevels();

         DDSFile *blendDDS = DDSFile::createDDSFileFromGBitmap( &blendBmp );
         DDSUtil::squishDDS( blendDDS, GFXFormatDXT1 );

         // Write result to file stream
         blendDDS->write( fs );
         
         delete blendDDS;
      }
      fs.close();
   }
   else
   {
      FileStream stream;
      if (!stream.open(_getBaseTexCacheFileName(), Torque::FS::File::Write))
      {
         mBaseTex = blendTex;
         return;
      }

      GBitmap bitmap(blendTex->getWidth(), blendTex->getHeight(), false, GFXFormatR8G8B8);
      blendTex->copyToBmp(&bitmap);
      bitmap.writeBitmap(formatToExtension(mBaseTexFormat), stream);
   }
}