Rendering to a texture is a commonly used advanced technique in 3D rendering. This technique allows the user to render to a texture surface instead of the back buffer. The resulting texture can then be used a regular texture and applied to scene geometry as desired. For example, this technique can be used to create an “in game billboard”. First compose your billboard as a SWF file in Flash Studio, render the SWF file to a texture and then apply the texture to the appropriate scene geometry.
In this tutorial, we simply render the UI from the last tutorial to the back wall. If you depress the middle mouse button to move the light source around, you will see that the appearance of the UI changes appropriately.
We will now walk you through the inner workings of this sample.
In all of the previous tutorials, we have been loading the cell.x scene file. This file contains the vertex coordinates, triangle indices and texture information needed to display the floor, walls and ceiling of the room. If you look at this file, you will notice that the same wall texture (cellwall.jpg) is used for all the four walls. We want our UI to be rendered only on the back wall. Therefore, we create a separate texture to be used for the back wall called cellwallRT.jpg. Next, modify the MeshMaterialList array to refer to this texture for the back wall.
Material { 1.000000;1.000000;1.000000;1.000000;; 40.000000; 1.000000;1.000000;1.000000;; 0.000000;0.000000;0.000000;; TextureFilename { "cellwallRT.jpg"; }
As noted from previous tutorials, the parsing of the cell.x file is done internally by the DXUT framework. During this parsing, DXUT initializes the vertex and index buffers and creates the textures referred to in the materials list. The textures are created using the CreateTexture call; however the usage parameters passed to this function are not appropriate for Render Textures. Please refer to DXSDK documentation for more information on this subject. In order to create a texture that can be used as a render target, recreate the render texture using the right usage parameters and attach it to the background mesh. Also release the texture originally created by DXUT to avoid memory leaks.
pd3dDevice->CreateTexture(rtw,rth,0, D3DUSAGE_RENDERTARGET|D3DUSAGE_AUTOGENMIPMAP, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_pRenderTex, 0); g_Background[0].m_pTextures[BACK_WALL] = g_pRenderTex; ptex->Release();
First save the original back buffer surfaces, so that we can revert back once we are done rendering.
pd3dDevice->GetRenderTarget(0, &poldSurface); pd3dDevice->GetDepthStencilSurface(&poldDepthSurface);
Next, obtain the render surface from our texture and set it as the render target.
ptex->GetSurfaceLevel(0, &psurface); HRESULT hr = pd3dDevice->SetRenderTarget(0, psurface );
Adjust the movie view port to the dimensions of our texture, call Display and then revert back to the original render surface saved in first step.