在Direct3D9中启用抗锯齿(多重采样渲染目标)

3

我正在尝试在D3D9应用程序中启用AA,但不确定如何正确设置表面。到目前为止,我已经做了以下工作:

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

初始化:

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
  );

然后,针对每个帧:

// 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);

然而,我的屏幕上没有任何显示(全是黑色)。没有发生错误(我检查了所有d3d调用的返回值)。我做错了什么?


你可以使用比这更短的变量名,例如 m_presentationParameters 可以缩写为 m_pp - bobobobo
1个回答

1

您不需要额外的表面,可以直接渲染到多重采样后备缓冲区。对我来说,使用StretchRect()的唯一原因是为了获得场景的非多重采样副本,以便用于后期处理(因为多重采样渲染目标是糟糕的纹理,所以您需要在已解析的纹理中获取场景数据)。如果您想要这样做,您不需要为后备缓冲区指定多重采样。然后,将场景渲染到多重采样渲染目标即可。


谢谢亚历山大。我也计划稍后进行后处理效果,所以我认为我需要额外的表面。你知道为什么这段代码不在屏幕上显示任何内容吗?我不确定应该按照什么顺序调用EndScene、StretchRect和Present,我尝试过的任何一种都似乎不起作用。 - Knio
代码看起来没问题 - 但我会把 EndScene 的调用直接放在 Present 之前。此外,尝试不对主后备缓冲区进行多重采样。对于 StretchRect 使用 D3DTEXF_LINEAR。最后,如果这些都没有帮助,启动 PIX 并查看出了什么问题。 - Alexander Gessler
1
我以前不知道PIX,这很有用!我的屏幕宽度/高度不完全是800x600,使用完全相同大小的表面使其工作。现在的一个问题是深度测试已经停止工作(我绘制的任何东西都会覆盖其他任何东西),我需要在新表面上设置深度测试或z缓冲区吗? - Knio
1
好的,我也需要使用相同的多重采样格式创建一个新的深度缓冲区。现在可以了。 - Knio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接