views:

649

answers:

1

I am trying to enable AA in a D3D9 application, but am not sure how to set up the surfaces correctly. So far, I have:

IDirect3DDevice9* m_pd3dDevice;
IDirect3DSurface9* screen;
IDirect3DSurface9* msaasurf;
D3DPRESENT_PARAMETERS m_presentationParameters;

Initialization:

m_presentationParameters.Windowed = TRUE;
m_presentationParameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
m_presentationParameters.MultiSampleType = D3DMULTISAMPLE_2_SAMPLES;
m_presentationParameters.MultiSampleQuality = 0;
m_presentationParameters.BackBufferFormat = D3DFMT_UNKNOWN;
m_presentationParameters.EnableAutoDepthStencil = TRUE;
m_presentationParameters.AutoDepthStencilFormat = D3DFMT_D16;
m_presentationParameters.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

// create d3d device
m_pD3D->CreateDevice(
  D3DADAPTER_DEFAULT, 
  D3DDEVTYPE_HAL, 
  hWnd,
  D3DCREATE_HARDWARE_VERTEXPROCESSING,
  &m_presentationParameters, &m_pd3dDevice 
)


// save screen surface
m_pd3dDevice->GetRenderTarget(0, &screen);
D3DSURFACE_DESC desc;
screen->GetDesc(&desc);

// Create multisample render target
m_pd3dDevice->CreateRenderTarget(
    800, 600, 
    D3DFMT_A8R8G8B8,
    desc.MultiSampleType, desc.MultiSampleQuality,
    false,
    &msaasurf,
    NULL
  );

And then, for each frame:

// render to multisample surface
m_pd3dDevice->SetRenderTarget(0, msaasurf);

m_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0, 0, 0 ), 1.0f, 0 );
m_pd3dDevice->BeginScene();

// render stuff here

m_pd3dDevice->EndScene();

m_pd3dDevice->SetRenderTarget(0, screen);

// get back buffer
IDirect3DSurface9* backBuffer = NULL;
m_pd3dDevice->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &backBuffer);

// copy rendertarget to backbuffer
m_pd3dDevice->StretchRect(msaasurf, NULL, backBuffer, NULL, D3DTEXF_NONE);
backBuffer->Release();

// Present the backbuffer contents to the display
m_pd3dDevice->Present(NULL, NULL, NULL, NULL);

However, nothing is appearing on my screen (all black). No errors are occuring (I check the return value of all d3d calls). What am I doing wrong?

+1  A: 

You don't need the extra surface, you can render directly to the multisampled backbuffer. For me, the only reason to use StretchRect() like this is to get a non-multisampled copy of the scene for use with postprocessing (because multisampled render targets are bad textures, so you need the scene data in a resolved texture). If you want to do this, you don't need to specify multisampling for the backbuffer. A multisampled render target to render the scene to is sufficient then.

Alexander Gessler
Thanks Alexander. I do also plan on doing post-processing effects later on, so I think I will need the extra surface. Do you know why this code doesn't display anything to the screen? I am not sure about the order EndScene, StretchRect, and Present should be called in, none i've tried seem to work.
Knio
The code seems fine to me - but I'd put the call `EndScene` directly before `Present`. Also, try no multisampling for the primary backbuffer. And `D3DTEXF_LINEAR` for `StretchRect`. And finally if this does not help, fire PIX and look what's going wrong.
Alexander Gessler
I didn't know about PIX before, this is useful! the width/height of my screen was not quite 800x600, using the exact same size for my surface made it work. One problem now is that depth testing has stopped working (everything I draw overwrites anything else), is there something I need to do to setup depth testing or a zbuffer on the new surface?
Knio
OK, I also needed to create a new depth buffer with the same multisample format. Works now.
Knio