简体   繁体   English

Directx 11深度测试不起作用

[英]Directx 11 depth test not working

I cannot get my program to correctly choose which models to place in front. 我无法让我的程序正确选择要放置在前面的模型。 I have followed the MSDN code exactly. 我完全遵循了MSDN代码。 My code appears to correctly draw all polygons in a particular call of DrawIndexed, but each subsequent call seems to cause models to be drawn in the order they are drawn, not based on whether they are closer to the screen. 我的代码似乎可以在DrawIndexed的特定调用中正确绘制所有多边形,但是随后的每个调用似乎都导致模型按照绘制顺序绘制,而不是取决于模型是否靠近屏幕。

Here is my code for initializing Direct3d: 这是我用于初始化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);

This is my code for rendering: 这是我的渲染代码:

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

I have tried searching extensively, and have followed every tutorial I could find. 我尝试了广泛的搜索,并遵循了所有可以找到的教程。 Nothing fixes it. 没有什么可以解决的。

In the case of the spheres, depth appears to be correct if viewing from one side, but not the other. 对于球体,如果从一侧而不是另一侧观察,深度似乎是正确的。

Any help would be appreciated. 任何帮助,将不胜感激。 Thanks. 谢谢。

From OP comment: 从OP评论:

The problem ended up being much simpler. 问题最终变得更加简单。 I did not set the minimum and max depth for the viewport object. 我没有为视口对象设置最小和最大深度。 It worked once I did so. 一旦这样做,它就会起作用。

I had the same problem, it works now: 我遇到了同样的问题,现在可以使用:

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

There are three key steps to Z-Buffering. Z缓冲有三个关键步骤。

  1. Setting the Appropriate Presentation Parameters 设置适当的演示参数
  2. Turning On Z-Buffering 开启Z缓冲
  3. Clearing the Z-Buffer 清除Z缓冲区

1) Setting the Appropriate Presentation Parameters 1)设置适当的演示参数

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

EnableAutoDepthStencil EnableAutoDepthStencil

In truth, z-buffering can be complex. 实际上,z缓冲可能很复杂。 Setting this value to TRUE tells Direct3D to automatically create the z-buffer and set it up in a way used most often. 将此值设置为TRUE指示Direct3D自动创建z缓冲区并以最常用的方式进行设置。 There are, of course, uses for the complex method, but we'll stick to simple for now. 当然,复杂方法有很多用途,但现在我们将坚持简单。 We'll cover ways the complex method can be useful later in the tutorial. 我们将在本教程的后面部分介绍复杂方法的有用方法。

AutoDepthStencilFormat AutoDepthStencilFormat

This is the format for each pixel in the z-buffer. 这是z缓冲区中每个像素的格式。 We don't use the regular pixel format defined in the Presentation Parameters. 我们不使用Presentation Parameters中定义的常规像素格式。 Instead, we use a special format for z-buffers. 相反,我们对z缓冲区使用一种特殊的格式。 This format is D3DFMT_D16. 此格式为D3DFMT_D16。 This means that each pixel is 16-bit. 这意味着每个像素均为16位。 There are other formats, but we will not need them for the extent of this tutorial. 还有其他格式,但是在本教程的范围内,我们将不需要它们。

2) Turning On Z-Buffering 2)开启Z缓冲

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

3) Clearing the Z-Buffer 3)清除Z缓冲区

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

By the way this works in DirectX 9.0c. 顺便说一下,这在DirectX 9.0c中有效。 Im not sure if it is compatible with DirectX 11. 我不确定它是否与DirectX 11兼容。

Had a similar problem in DirectX10, seems it was initialisation code, I am not sure about the CreateDevice and SwapChain against UNKNOWN driver type, as I have not used that before. DirectX10中也有类似的问题,似乎是初始化代码,我不确定针对UNKNOWN驱动程序类型的CreateDevice和SwapChain,因为我以前没有使用过。

There are a few differences I can see, the Stencil buffer does not specify the operations to perform depth stencil tests against. 我可以看到一些区别,模板缓冲区没有指定针对深度模板测试的操作。 (Unless this has been specified in the HLSL which is not visible here) (除非已在HLSL中指定,但此处未显示)

eg: 例如:

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

In any event, here is a working DirectX10 example, I am pretty sure you can adapt it quickly for DirectX11. 无论如何,这是一个有效的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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM