【问题标题】:Directx 11 depth test not workingDirectx 11 深度测试不起作用
【发布时间】:2011-12-25 18:26:27
【问题描述】:

我无法让我的程序正确选择要放在前面的模型。我完全遵循了 MSDN 代码。我的代码似乎在 DrawIndexed 的特定调用中正确绘制了所有多边形,但每个后续调用似乎都会导致模型按照它们的绘制顺序进行绘制,而不是基于它们是否更靠近屏幕。

这是我初始化 Direct3d 的代码:

DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory( &sd, sizeof( sd ) );
sd.BufferCount = 1;
sd.BufferDesc.Width = width;
sd.BufferDesc.Height = height;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = hWnd;
sd.SampleDesc.Count = 4;
sd.SampleDesc.Quality = 0;
sd.Windowed = !fullScreen;
sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
D3D_FEATURE_LEVEL  FeatureLevelsRequested = D3D_FEATURE_LEVEL_11_0;
UINT               numFeatureLevelsRequested = 1;
D3D_FEATURE_LEVEL  FeatureLevelsSupported;
HRESULT hr;
if( FAILED (hr = D3D11CreateDeviceAndSwapChain( adapters[0], 
    D3D_DRIVER_TYPE_UNKNOWN, 
    NULL, 
    NULL,
    NULL, 
    NULL, 
    D3D11_SDK_VERSION, 
    &sd, 
    &swapchain, 
    &dev, 
    &FeatureLevelsSupported,
    &devcon )))
{
    //return;
}
ID3D11Texture2D *pBack = NULL;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBack);

// use the back buffer address to create the render target
dev->CreateRenderTargetView(pBack, NULL, &backbuffer);
pBack->Release();

// set the render target as the back buffer
// Create depth stencil texture
D3D11_TEXTURE2D_DESC descDepth;
ZeroMemory(&descDepth, sizeof(descDepth));
descDepth.Width = width;
descDepth.Height = height;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format =DXGI_FORMAT_D24_UNORM_S8_UINT;
descDepth.SampleDesc.Count = 4;
descDepth.SampleDesc.Quality = 0;
descDepth.Usage = D3D11_USAGE_DEFAULT;
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;

hr = dev->CreateTexture2D( &descDepth, NULL, &g_pDepthStencil);
if(FAILED(hr))
    exit(hr);

// Create the depth stencil view
D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
ZeroMemory(&descDSV, sizeof(descDSV));

descDSV.Format = descDepth.Format;
descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DMS;
descDSV.Texture2D.MipSlice = 0;;  
//descDSV.Texture2DMS.UnusedField_NothingToDefine = 0;  

hr = dev->CreateDepthStencilView( g_pDepthStencil, &descDSV, &g_pDepthStencilView);
if(FAILED(hr))
    exit(hr);
devcon->OMSetRenderTargets(1, &backbuffer, g_pDepthStencilView);
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));

viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = width;
viewport.Height = height;

devcon->RSSetViewports(1, &viewport);

这是我的渲染代码:

void Direct3DRenderer::Render()
{

    devcon->ClearRenderTargetView(backbuffer, D3DXCOLOR(0.0f, 0.2f, 0.4f, 1.0f));
    devcon->ClearDepthStencilView(g_pDepthStencilView,  D3D11_CLEAR_DEPTH|D3D11_CLEAR_STENCIL, 1.0f, 0 );
    camera.location = simulation->GetWorld()->GetCameraCoordinates();
    camera.direction = simulation->GetWorld()->GetCameraLookAt();
    //camera.up = simulation->GetWorld()->GetCameraOrientation();
    Vec3d lookAt = camera.location + camera.direction;
    XMVECTOR eye = XMVectorSet((float)camera.location[0], (float)camera.location[1], (float)camera.location[2], 0.f);
    XMVECTOR look = XMVectorSet(lookAt[0], lookAt[1], lookAt[2], 0);
    XMVECTOR up = XMVectorSet(camera.up[0], camera.up[1], camera.up[2], 0);
    g_View = XMMatrixLookAtLH(eye, look, up);

    ConstantBuffer oncePerFrame;
    oncePerFrame.matrix = XMMatrixTranspose(g_View);
    devcon->UpdateSubresource(oncePerFrameBuffer, 0, NULL, &oncePerFrame, 0, 0);

    UINT stride = sizeof(VERTEX);
    UINT offset = 0;

    const std::vector<Graphical*> graphicalList = simulation->GetWorld()->GetGraphicalList();

    for(int ind = 0; ind < graphicalList.size(); ++ind)
    {
        switch(graphicalList[ind]->GetModelType())
        {
            case 1:  //Sphere
                {
                    ConstantBuffer oncePerModel2;
                    oncePerModel2.matrix = XMMatrixTranspose(XMMatrixScalingFromVector(graphicalList[ind]->GetScaleX()) * XMMatrixTranslationFromVector(graphicalList[ind]->GetTranslationX()));
                    devcon->UpdateSubresource(oncePerModelBuffer, 0, NULL, &oncePerModel2, 0, 0);
                    devcon->IASetVertexBuffers(0, 1, &(sphereModel.vertexBuffer), &stride, &offset);
                    devcon->IASetIndexBuffer(sphereModel.indexBuffer, DXGI_FORMAT_R32_UINT, 0);
                    devcon->DrawIndexed(sphereModel.indexCount, 0, 0);
                }
                break;
        }
    }
    ConstantBuffer oncePerModel;
    oncePerModel.matrix = XMMatrixTranspose(g_World);
    devcon->UpdateSubresource(oncePerModelBuffer, 0, NULL, &oncePerModel, 0, 0);

    devcon->IASetVertexBuffers(0, 1, &terrainModel.vertexBuffer, &stride, &offset);
    devcon->IASetIndexBuffer(terrainModel.indexBuffer, DXGI_FORMAT_R32_UINT, 0);
    devcon->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
    devcon->DrawIndexed(terrainModel.indexCount, 0, 0);

    swapchain->Present(0, 0);
}

我尝试过广泛搜索,并按照我能找到的每个教程进行操作。没有什么能解决它。

在球体的情况下,如果从一侧看,深度似乎是正确的,但从另一侧看是正确的。

任何帮助将不胜感激。谢谢。

【问题讨论】:

  • 这只是一个猜测,但您是否尝试过使用 0.0 而不是 1.0 来清除深度缓冲区?
  • 刚试过。它只是什么都不显示。这是有道理的,因为我相信它已经将每个像素设置为深度 0,所以没有什么比它更接近了,所以一切都会被丢弃。
  • 你试过*your3ddevice*-&gt;SetRenderState(D3DRS_ZENABLE, TRUE);吗?
  • 你能把深度缓冲区作为一个纹理来看看吗?它可以表明问题所在。

标签: c++ directx direct3d depth-buffer directx-11


【解决方案1】:

来自 OP 评论:

问题最终变得简单多了。我没有设置最小值和 视口对象的最大深度。一旦我这样做了,它就起作用了。

我遇到了同样的问题,现在可以了:

D3D11_VIEWPORT screenViewport;
/* ... */
screenViewport.MinDepth = 0;
screenViewport.MaxDepth = 1;
/* ... */
context->RSSetViewports(1, &screenViewport);

【讨论】:

    【解决方案2】:

    Z-Buffering 有三个关键步骤。

    1. 设置适当的演示参数
    2. 开启 Z 缓冲
    3. 清除 Z 缓冲区

    1) 设置合适的表现参数

    D3DPRESENT_PARAMETERS d3dpp;
    //...
    d3dpp.EnableAutoDepthStencil = TRUE;
    d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
    

    启用AutoDepthStencil

    事实上,z 缓冲可能很复杂。将此值设置为 TRUE 告诉 Direct3D 自动创建 z 缓冲区并以最常用的方式设置它。当然,复杂方法也有一些用途,但我们现在还是坚持简单。我们将在本教程后面介绍复杂方法的用途。

    AutoDepthStencilFormat

    这是 z 缓冲区中每个像素的格式。我们不使用 Presentation Parameters 中定义的常规像素格式。相反,我们对 z 缓冲区使用特殊格式。此格式为 D3DFMT_D16。这意味着每个像素都是 16 位的。还有其他格式,但在本教程的范围内我们不需要它们。

    2) 开启 Z 缓冲

    // d3ddev is your Direct3D device - a variable of type LPDIRECT3DDEVICE9
    d3ddev->SetRenderState(D3DRS_ZENABLE, TRUE);
    

    3) 清除 Z-Buffer

    d3ddev->Clear(0, NULL, D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
    

    顺便说一下,这适用于 DirectX 9.0c。我不确定它是否与 DirectX 11 兼容。

    【讨论】:

    • 问题最终变得简单多了。我没有设置视口对象的最小和最大深度。一旦我这样做了,它就起作用了。
    • 我认为这也不是 Direct3D 11 吗?看起来像早期版本
    【解决方案3】:

    在 DirectX10 中也有类似的问题,似乎是初始化代码,我不确定 CreateDevice 和 SwapChain 是否针对 UNKNOWN 驱动程序类型,因为我以前没有使用过。

    我可以看到一些差异,模板缓冲区没有指定执行深度模板测试的操作。 (除非已在此处不可见的 HLSL 中指定)

    例如:

    // Stencil test parameters
    dsDesc.StencilEnable = true;
    dsDesc.StencilReadMask = 0xFF;
    dsDesc.StencilWriteMask = 0xFF;
    
    // Stencil operations if pixel is front-facing
    dsDesc.FrontFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
    dsDesc.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_INCR;
    dsDesc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
    dsDesc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
    
    // Stencil operations if pixel is back-facing
    dsDesc.BackFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
    dsDesc.BackFace.StencilDepthFailOp = D3D10_STENCIL_OP_DECR;
    dsDesc.BackFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
    dsDesc.BackFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
    

    无论如何,这是一个有效的 DirectX10 示例,我很确定您可以快速适应 DirectX11。

    logger->debug("initD3D: Calling D3D10CreateDeviceAndSwapChain.\n");
    
    SYSTEMTIME sysTime;
    GetSystemTime(&sysTime);
    srand((unsigned int)sysTime.wMilliseconds);
    logger->debug("in initD3D.\n");
    shutdownXX = false;
    
    count = 1;
    quality = 0;
    
    //Create the back buffer desc.
    ZeroMemory(&swapDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
    
    swapDesc.BufferCount = 1;
    swapDesc.BufferDesc.Width = width;
    swapDesc.BufferDesc.Height = height;
    
    swapDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    
    swapDesc.BufferDesc.RefreshRate.Numerator = 60;
    swapDesc.BufferDesc.RefreshRate.Denominator = 1;
    swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapDesc.OutputWindow = hwnd;
    swapDesc.SampleDesc.Count = count;
    swapDesc.SampleDesc.Quality = quality;
    swapDesc.Windowed = FALSE;
    
    
    swapDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    swapDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
    swapDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
    
    //Create the device.
    HRESULT hr = D3D10CreateDeviceAndSwapChain(
            NULL, 
            D3D10_DRIVER_TYPE_HARDWARE, 
            NULL, 
            0, 
            D3D10_SDK_VERSION, 
            &swapDesc, 
            &swapChain, 
            &device);
    if (!chk(hr, TEXT("Could not create D3D Device D3D10CreateDeviceAndSwapChain failed.")))
        return false;
    
    ID3D10Texture2D *buffer;
    
    logger->debug("initD3D: Calling swapChain->GetBuffer.\n");
    hr = swapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*) &buffer);
    if (!chk(hr, TEXT("Could not create D3D Device: swapChain->GetBuffer failed.")))
        return false;
    
    D3D10_TEXTURE2D_DESC BBDesc;
    ZeroMemory(&BBDesc, sizeof(D3D10_TEXTURE2D_DESC));
    buffer->GetDesc( &BBDesc );
    
    D3D10_RENDER_TARGET_VIEW_DESC RTVDesc;
    ZeroMemory(&RTVDesc, sizeof(D3D10_RENDER_TARGET_VIEW_DESC));
    RTVDesc.Format = BBDesc.Format;
    //RTVDesc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2D;
    RTVDesc.ViewDimension = D3D10_RTV_DIMENSION_TEXTURE2DMS;
    RTVDesc.Texture2D.MipSlice = 0;
    
    logger->debug("initD3D: Calling device->CreateRenderTargetView.\n");
    hr = device->CreateRenderTargetView(buffer, &RTVDesc, &renderTView);
    buffer->Release();
    
    if (!chk(hr, TEXT("Could not create D3D Device: device->CreateRenderTargetView failed.")))
        return false;
    
    
    ZeroMemory(&descDepth, sizeof(D3D10_TEXTURE2D_DESC));
    descDepth.Width = width;
    descDepth.Height = height;
    descDepth.MipLevels = 1;
    descDepth.ArraySize = 1;
    descDepth.Format = DXGI_FORMAT_D32_FLOAT_S8X24_UINT;
    //descDepth.Format = DXGI_FORMAT_D32_FLOAT;
    descDepth.SampleDesc.Count = count;
    descDepth.SampleDesc.Quality = quality;
    descDepth.Usage = D3D10_USAGE_DEFAULT;
    descDepth.BindFlags = D3D10_BIND_DEPTH_STENCIL;
    descDepth.CPUAccessFlags = 0;
    descDepth.MiscFlags = 0;
    
    hr = device->CreateTexture2D(&descDepth, NULL, &stencil);
    if (!chk(hr, TEXT("device->device->CreateTexture2D Failed\n")))
        return false;
    
    // Depth test parameters
    dsDesc.DepthEnable = true;
    dsDesc.DepthWriteMask = D3D10_DEPTH_WRITE_MASK_ALL;
    dsDesc.DepthFunc = D3D10_COMPARISON_LESS;
    
    // Stencil test parameters
    dsDesc.StencilEnable = true;
    dsDesc.StencilReadMask = 0xFF;
    dsDesc.StencilWriteMask = 0xFF;
    
    // Stencil operations if pixel is front-facing
    dsDesc.FrontFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
    dsDesc.FrontFace.StencilDepthFailOp = D3D10_STENCIL_OP_INCR;
    dsDesc.FrontFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
    dsDesc.FrontFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
    
    // Stencil operations if pixel is back-facing
    dsDesc.BackFace.StencilFailOp = D3D10_STENCIL_OP_KEEP;
    dsDesc.BackFace.StencilDepthFailOp = D3D10_STENCIL_OP_DECR;
    dsDesc.BackFace.StencilPassOp = D3D10_STENCIL_OP_KEEP;
    dsDesc.BackFace.StencilFunc = D3D10_COMPARISON_ALWAYS;
    
    
    hr = device->CreateDepthStencilState(&dsDesc, &pDSState);
    if (!chk(hr, TEXT("device->device->CreateDepthStencilState Failed\n")))
        return false;
    device->OMSetDepthStencilState(pDSState, 1);
    
    ZeroMemory(&descDSV, sizeof(D3D10_DEPTH_STENCIL_VIEW_DESC));
    descDSV.Format = descDepth.Format;
    //descDSV.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2D;
    descDSV.ViewDimension = D3D10_DSV_DIMENSION_TEXTURE2DMS;
    descDSV.Texture2D.MipSlice = 0;
    
    hr = device->CreateDepthStencilView(stencil, &descDSV, &depthStencil);
    if (!chk(hr, TEXT("device->device->CreateDepthStencilView Failed\n")))
        return false;
    
    device->OMSetRenderTargets(1, &renderTView, depthStencil);
    
    resizeD3D10Window(width, height);
    
    return true;
    

    【讨论】:

      猜你喜欢
      • 2013-07-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-19
      • 2018-07-01
      • 2016-05-18
      • 2019-08-30
      • 2012-03-09
      相关资源
      最近更新 更多