Skip to main content
gamedev.net
🔒 Locked

Render Targets

Started by beebs1 Feb 18, 2007 at 9:20 AM 7 replies 1.5k views
Original Post
beebs1
beebs1
Hi, I'm taking my first steps into deferred shading, and I would be grateful if someone could answer a couple of questions I have about the geometry stage. First I create 3 A8R8G8B8 offscreen plain surfaces for the normals, diffuse and specular, and one R32F surface for the depth. Then I call:
HRESULT SetRenderTarget(
  DWORD RenderTargetIndex,
  IDirect3DSurface9 * pRenderTarget
);
I'm confused here about what the RenderTargetIndex actually means, I assume valid values are 0 through 3 as my card supports 4 simultaneous render targets. Should I use 0 for depth, 1 for normals, etc...? Also, I'm not sure of how to draw only depth information - All I can see in SetRenderState are parameters to turn off z-buffering, which is not what I need. Is there an equivalent to glColorMask? Thanks for any replies! :)
sirob
sirob
In order to use MRTs, I think you're required to use shaders. I don't think the FFP supports MRTs.

After calling SetRenderTarget with various indices, you then output several colors from the same PS: COLOR0 goes to RT 0, COLOR1 to RT 1, etc.

For outputting just depth, you'd just output the Z value of the pixel as the appropriate output color.

Hope this helps.
Sirob Yes.» - status: Work-O-Rama.
beebs1
beebs1
Thanks for your reply - I just found a way by using:

SetRenderTarget( 0, m_pDepthRenderTarget );SetRenderState( D3DRS_COLORWRITEENABLE, NULL );// then draw scene...


I want to now display the depth render target fullscreen to check I have implemented this correctly (so far, at least...) - I'm guessing I need to do something like the following:

- Set the render target back
- Draw the depth buffer as a fullscreen quad?

Sorry about my obvious lack of knowledge here, I've never touched RTs in my life - can anyone tell me how to set the render target back?

Thanks again :)
circlesoft
circlesoft
Quote:
Original post by beebs1
Sorry about my obvious lack of knowledge here, I've never touched RTs in my life - can anyone tell me how to set the render target back?)

First, to get your backbuffer, you have to do GetRenderTarget() (before you change it to any other RT). Then just set it like normal. Notice that GetRenderTarget increases the reference count of the surface, so you will also have to release it.

Like this:

IDirect3DSurface9** backBufferRT;device->GetRenderTarget( 0, &backBufferRT );// Do rendering stuff...device->SetRenderTarget( 0, backBufferRT );// Do more rendering stuffbackBufferRT->Release()
beebs1
beebs1
Hi, thanks for your replies!

I'm still having trouble getting this first stage to work, I guess it's going to be a long road...

Would anyone check over this bit of code and tell me if it's doing what I think it is? The idea is to just 'render' a test mesh so that only the depth values are written into a buffer.
// init code --------------------// create the depth RTm_pDevice->CreateTexture(    m_parameters.BackBufferWidth,    m_parameters.BackBufferHeight,    1,    D3DUSAGE_RENDERTARGET,    D3DFMT_R32F,    D3DPOOL_DEFAULT,    &m_pDepthRT,    NULL );// store the original backbufferm_pDevice->GetBackBuffer( 0, 0, D3DBACKBUFFER_TYPE_MONO, &m_pBackBuffer );// per-frame code to write the depth values ---------------------// clear the backbufferm_pDevice->Clear(    0,    NULL,    D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,    D3DCOLOR_RGBA( 0, 0, 0, 255 ),    1.0f,    0 );m_pDevice->BeginScene();// set the depth RTIDirect3DSurface9 *pSurface;m_pDepthRT->GetSurfaceLevel( 0, &pSurface );m_pDevice->SetRenderTarget( 0, pSurface );// disable color writing so only depth values writtenm_pDevice->SetRenderState( D3DRS_COLORWRITEENABLE, NULL );// draw the test meshm_pMesh->DrawSubset( 0 );// reset the original render targetm_pDevice->SetRenderTarget( 0, m_pBackBuffer );// re-enable color writingm_pDevice->SetRenderState(    D3DRS_COLORWRITEENABLE,    D3DCOLORWRITEENABLE_ALPHA |    D3DCOLORWRITEENABLE_BLUE |    D3DCOLORWRITEENABLE_GREEN |    D3DCOLORWRITEENABLE_RED );pSurface->Release();


Is that correct? It's possible (probable?) that I got completely the wrong idea, but if someone could lend a hand it would be very much appreciated, thanks
Namethatnobodyelsetook
Namethatnobodyelsetook
It's writing depth to the ZBuffer, and nothing to your R32F render target (you disabled color writes). The usual way to get this to work is to use shaders. You'll need a vertex shader to pass depth values as a texture coordinate, and a pixel shader to simply output those depth values to a render target.

Typically with deferred shading, you'll have a pixel shader output multiple things to different render targets, such as normals, Z values, diffuse texture, and any other material properties (specular color, specular power, emissive colors, reflections, reflection masks, ... it all depends on what you want). You'll then have light passes which again will require shaders. A final pass to mix all the results will once again require shaders.
littlekid
littlekid
May I know if is it better to turn off the other render targets after i have finish using them?

e.g
pass1 needs RT1, RT2, RT3
pass2 needs RT1
pass3 needs RT1

Is it better to set these after pass1 and turn it on when i need.

Device->SetRenderTarget(1, NULL);
Device->SetRenderTarget(2, NULL);

Or can i just leave it there since in the next frame its will be used again?

Will any performance be affected?
sirob
sirob
If you don't set them to null, any call you make will render data on them. Even if this doesn't impact your application's results, this will not be benificial for performance.

Always unset RenderTargets when you're not rendering to them any more.
Sirob Yes.» - status: Work-O-Rama.
littlekid
littlekid
Does this means that even if my pixel shader does not write anything into the other RT, directx will still draw onto them?

from the SDK i know it says
oC# will write into the corresponding RT where # specifiy the RT Index.

hence if my pixel shader only have oC0, RT1 and RT2 will also get drawn?

How do i actually find the maximum number of RenderTargets my card can support?

Plus must I set back the Render Target to the original RT?
In my program, I change the default RT with a new RT, when I call device->present(), Nothing comes out, and it seems as the device is not even clearing the RenderTarget as the number from my FRAPS counter is all overlaped.

[Edited by - littlekid on February 19, 2007 7:58:29 AM]

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.