【问题标题】:I need some clarification with the concept of depth/stencil buffers in direct3D 11 (c++)我需要对direct3D 11(c++)中深度/模板缓冲区的概念进行一些澄清
【发布时间】:2015-07-13 01:22:02
【问题描述】:

我正在遵循在线教程来帮助我创建我的第一个游戏,到目前为止,我了解 Direct3D 11 必须向我提出的每一个概念。

但是有一个概念我似乎还不能完全掌握;深度/模板缓冲区。

我了解深度/模板缓冲区用于“比较”游戏中不同对象的像素深度。如果两个对象相互重叠,则像素深度较小的对象将显示在更靠近相机的位置。然后通过填写 D3D11_TEXTURE2D_DESC.. 来定义深度/模板缓冲区。

但我的问题是;如果我填写了 D3D11_TEXTURE2D_DESC 结构,那么我是在告诉 directXHOW 在游戏中比较不同对象的像素吗?

如果您不理解我的问题,请尽量简单地解释深度/模板缓冲区的概念。另外请尝试通过填写 D3D11_TEXTURE2D_DESC 结构来解释我到底定义了什么

谢谢。

【问题讨论】:

  • 从文档看,D3D11_TEXTURE2D_DESC 是用来描述纹理的内容和布局的。因为它告诉 Direct3D 如何读取纹理。宽度、高度、颜色通道、每个颜色通道有多少位,以及它们的顺序(RGBA、BGRA、RGB 无 A、BGR 无 A,存储在浮点数中?可能是无符号整数?等)
  • 我现在正在自学 OpenGL,所以我可能错了。但我的理解是深度缓冲区有助于确定最终图像中将显示哪个像素。如果您有多边形重叠,并且首先绘制后面的多边形,那么当其他多边形绘制时,其深度值将与前一个多边形的深度值进行比较。如果它在顶部,则该像素将被写入颜色缓冲区。否则结果会被丢弃
  • 所以不,如果您填写描述结构,您就是在告诉 Direct3D 如何读取和存储结果(多少位,什么数据类型)。现在怎么比较。我不知道 D3D 的等价物是什么,但在 OpenGL 中,glDepthFunc() 可以改变 OpenGL 比较深度值的方式。您可以将其设置为GL_LESSGL_GREATER 等。这是 MS 关于深度模板缓冲区的文档。似乎他们使用D3D11_COMPARISON_FUNC 枚举:msdn.microsoft.com/en-us/library/windows/desktop/… 我认为这可能相当于glDepthFunc()
  • 我仍然不明白为什么我需要填写 D3D11_TEXTURE2D_DESC 结构来创建深度/模板缓冲区。这个结构与深度/模板缓冲区有什么关系?例如,如果我将 300 分配给 Width 成员,将 300 分配给 height 成员,那么我是在告诉 direct3D “比较”屏幕高度和宽度中所有 300 个像素的深度吗?
  • 您需要填写它,因为深度/模板缓冲区本质上是纹理。像素/颜色数据数组。一个图像。通过填写它,您可以指定显卡需要为该缓冲区分配多少空间,以及深度/像素值占用多少位。 GPU 需要知道为了知道位置 (x, y) 的像素在内存中的位置。它指定缓冲区的布局

标签: c++ direct3d direct3d11


【解决方案1】:

当您填写D3D11_TEXTURE2D_DESC 时,您是在描述深度/模板缓冲区本身:它有多大,它使用什么格式,您希望如何将它绑定到管道。

“样板”结构如下(取自 Direct3D Win32 Game Visual Studio template,使用 C++ 等效的 CD3D11_TEXTURE2D_DESC

CD3D11_TEXTURE2D_DESC depthStencilDesc(depthBufferFormat,
    backBufferWidth, backBufferHeight, 1, 1,
    D3D11_BIND_DEPTH_STENCIL);

ComPtr<ID3D11Texture2D> depthStencil;
DX::ThrowIfFailed(
    m_d3dDevice->CreateTexture2D(&depthStencilDesc, nullptr,
       depthStencil.GetAddressOf()));

depthBufferFormat 取决于您想要的精度级别、您是否使用模板缓冲区以及您的Direct3D Feature Level。该模板默认使用DXGI_FORMAT_D24_UNORM_S8_UINT,它适用于所有特征叶,并提供合理的深度精度和 8 位模板。大小必须与您的颜色后台缓冲区完全匹配。

您可以通过为缓冲区创建一个“视图”将深度模板缓冲区绑定到渲染管道。

CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D);
DX::ThrowIfFailed(
    m_d3dDevice->CreateDepthStencilView(depthStencil.Get(),
         &depthStencilViewDesc, m_depthStencilView.ReleaseAndGetAddressOf()));

然后你“清除”每一帧的视图,然后绑定视图进行渲染:

m_d3dContext->ClearDepthStencilView(m_depthStencilView.Get(),
    D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);

m_d3dContext->OMSetRenderTargets(1, m_renderTargetView.GetAddressOf(),
   m_depthStencilView.Get());

您告诉 Direct3D如何D3D11_DEPTH_STENCIL_DESC(或 C++ 等效的 D3D11_DEPTH_STENCIL_DESC)进行比较。

“默认”深度/模板状态是:

DepthEnable = TRUE;
DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
DepthFunc = D3D11_COMPARISON_LESS;
StencilEnable = FALSE;
StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK;
StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK;

const D3D11_DEPTH_STENCILOP_DESC defaultStencilOp =
    { D3D11_STENCIL_OP_KEEP,
      D3D11_STENCIL_OP_KEEP,
      D3D11_STENCIL_OP_KEEP,
      D3D11_COMPARISON_ALWAYS };

FrontFace = defaultStencilOp;
BackFace = defaultStencilOp;

DirectX Tool Kit中,我们提供了三种常见的深度状态:

// DepthNone
CD3D11_DEPTH_STENCIL_DESC desc(default);
desc.DepthEnable = FALSE;
desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
desc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;

// DepthDefault
CD3D11_DEPTH_STENCIL_DESC desc(default);
desc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;

// DepthRead
CD3D11_DEPTH_STENCIL_DESC desc(default);
desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
desc.DepthFunc = D3D11_COMPARISON_LESS_EQUAL;

【讨论】:

  • 我想这个信息对于 d3d11 来说是最新的。但是您能否详细说明“DepthNone”、“DepthDefault”和“DepthRead”的含义?
  • 这些是原始 XNA Game Studio 框架定义的状态。 DepthNone 用于完全不使用深度缓冲区进行渲染时,DepthDefault 是使用深度缓冲区进行隐藏表面移除的常用模式(即如果像素落后则拒绝,如果像素落后则更新深度缓冲区你在前面),DepthRead 用于使用深度缓冲区但不更新它(即,如果像素落后则拒绝)通常用于半透明像素。这三个都假设您没有使用模板缓冲区。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-22
  • 1970-01-01
  • 1970-01-01
  • 2013-08-06
  • 1970-01-01
  • 2018-09-13
  • 2013-04-12
相关资源
最近更新 更多