当前位置: 首页 > 知识库问答 >
问题:

深度缓冲区(到纹理)输出错误?

卫嘉泽
2023-03-14

对于SSAO效果,我必须生成两种纹理:法线(在视图空间中)和深度。

根据微软教程(阅读深度模板缓冲区作为纹理章节),我决定使用深度缓冲区作为纹理。

不幸的是,渲染后我从深度缓冲区(下图)中没有得到任何信息:

我想这是不对的。奇怪的是,深度缓冲区似乎有效(我得到了正确的人脸顺序等)。

深度缓冲区代码:

//create depth stencil texture (depth buffer)
D3D11_TEXTURE2D_DESC descDepth;
ZeroMemory(&descDepth, sizeof(descDepth));
descDepth.Width = width;
descDepth.Height = height;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format = DXGI_FORMAT_R24G8_TYPELESS;
descDepth.SampleDesc.Count = antiAliasing.getCount();
descDepth.SampleDesc.Quality = antiAliasing.getQuality();
descDepth.Usage = D3D11_USAGE_DEFAULT;
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;

ID3D11Texture2D* depthStencil = NULL;
result = device->CreateTexture2D(&descDepth, NULL, &depthStencil);
ERROR_HANDLE(SUCCEEDED(result), L"Could not create depth stencil texture.", MOD_GRAPHIC);

D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
//setup the description of the shader resource view
shaderResourceViewDesc.Format = DXGI_FORMAT_R24_UNORM_X8_TYPELESS;
shaderResourceViewDesc.ViewDimension = antiAliasing.isOn() ? D3D11_SRV_DIMENSION_TEXTURE2DMS : D3D11_SRV_DIMENSION_TEXTURE2D;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
shaderResourceViewDesc.Texture2D.MipLevels = 1;

//create the shader resource view.
ERROR_HANDLE(SUCCEEDED(device->CreateShaderResourceView(depthStencil, &shaderResourceViewDesc, &depthStencilShaderResourceView)),
    L"Could not create shader resource view for depth buffer.", MOD_GRAPHIC);

createDepthStencilStates();
//set the depth stencil state.
context->OMSetDepthStencilState(depthStencilState3D, 1);

D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc;
// Initialize the depth stencil view.
ZeroMemory(&depthStencilViewDesc, sizeof(depthStencilViewDesc));

// Set up the depth stencil view description.
depthStencilViewDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
depthStencilViewDesc.ViewDimension = antiAliasing.isOn() ? D3D11_DSV_DIMENSION_TEXTURE2DMS : D3D11_DSV_DIMENSION_TEXTURE2D;
depthStencilViewDesc.Texture2D.MipSlice = 0;
//depthStencilViewDesc.Flags = D3D11_DSV_READ_ONLY_DEPTH;

// Create the depth stencil view.
result = device->CreateDepthStencilView(depthStencil, &depthStencilViewDesc, &depthStencilView);
ERROR_HANDLE(SUCCEEDED(result), L"Could not create depth stencil view.", MOD_GRAPHIC);

使用第一遍渲染后,我将深度模板与其他渲染目标(颜色、法线)一起设置为纹理资源,将其附加到数组:

ID3D11ShaderResourceView ** textures = new ID3D11ShaderResourceView *[targets.size()+1];
for (unsigned i = 0; i < targets.size(); i++) {
    textures[i] = targets[i]->getShaderResourceView();
}
textures[targets.size()] = depthStencilShaderResourceView;
context->PSSetShaderResources(0, targets.size()+1, textures);

在第二次通过之前,我调用上下文-

然后,我使用简单的后期处理着色器渲染纹理(从第一遍深度缓冲区渲染目标),只是为了调试(第二遍):

Texture2D ColorTexture[3];
SamplerState ObjSamplerState;

float4 main(VS_OUTPUT input) : SV_TARGET0{
    float4 Color;
    Color = float4(0, 1, 1, 1);
    float2 textureCoordinates = input.textureCoordinates.xy * 2;
    if (input.textureCoordinates.x < 0.5f && input.textureCoordinates.y < 0.5f) {
        Color = ColorTexture[0].Sample(ObjSamplerState, textureCoordinates);
    }
    if (input.textureCoordinates.x > 0.5f && input.textureCoordinates.y < 0.5f) {
        textureCoordinates.x -= 0.5f;
        Color = ColorTexture[1].Sample(ObjSamplerState, textureCoordinates);
    }
    if (input.textureCoordinates.x < 0.5f && input.textureCoordinates.y > 0.5f) { //depth texture
        textureCoordinates.y -= 0.5f;
        Color = ColorTexture[2].Sample(ObjSamplerState, textureCoordinates);
    }
...

它适用于法线纹理。为什么它不适用于深度缓冲区(作为着色器资源视图)?


共有1个答案

欧阳声
2023-03-14

根据评论:

纹理被正确渲染和采样,但由于数据位于0.999和1.0f之间,数据似乎一致为红色。

您可以做一些事情来提高可用的深度精度,但最简单的是简单地确保您的远近剪辑距离对于您正在绘制的场景来说不会太小/太大。

假设以米为单位,0.1(10厘米)的近距离距离和200(米)的远距离比1厘米和20公里更合理。

即便如此,不要期望看到太多的黑色/黑暗区域,z缓冲区的非线性特性仍然意味着您的大部分深度值都向1分流。如果深度缓冲区的可视化很重要,那么只需在显示数据之前将数据重新调整为标准化的0-1范围。

 类似资料:
  • 我有一个正在开发的OpenGL应用程序。正在渲染的地形似乎没有遵循深度缓冲规则,所以我猜我在某个地方搞砸了 我的代码中有GL11.glEnable(GL11.GL_CULL_FACE) 这是飞机在没有四边形在另一个后面的情况下的样子,所以即使没有z缓冲区,事情看起来也很正常。请注意,这是从“自上而下”的视图中,其中“相机”在飞机上方 而现在,从不同的角度看 离场景最远的四边形正在更靠近计算机的四边

  • 我正在使用JOGL,但这个问题一般适用于OpenGL。似乎存在类似的问题,但它们要么针对GLSL代码,要么与复制帧缓冲区的内容有关,要么是一般建议-使用帧缓冲区对象,而不是。 我正在做一些阴影映射。如何使用帧缓冲对象将深度通道直接渲染到纹理? 能否请你贴一段初始化纹理和帧缓冲对象的代码,以及渲染场景前初始化一切的代码? 目前,我使用<code>glCopyTexSubImage2D<code>。我

  • 我做了一个在上面渲染天空盒和粒子的应用程序。我想添加一些效果,我需要使用帧缓冲区来渲染天空盒、粒子颜色、深度和位置以分离纹理。然后我想使用简单的着色器来使用这些纹理中的值并以适当的方式混合它们。我为纹理、帧缓冲区和屏幕四边形(渲染简单的矩形)编写了辅助类,但不幸的是——当我尝试使用它时没有任何渲染。 当绑定帧缓冲区被注释掉时,我的场景如下所示: 修改着色器表明深度和位置值计算正确。因此问题在于纹理

  • 我是OpenGL的新手。我想使用帧缓冲区读取并保存渲染场景中的所有深度值。我设法将其设置为附加到深度组件的帧缓冲区。但是当我将深度纹理渲染到默认帧缓冲区(显示窗口)时,它只显示白色,即使我线性化了深度值(教程从https://learnopengl.com/开始)。当我在默认帧缓冲区片段着色器中从gl_FragCoord. z访问深度值时,我会得到一个深度图,并且绘图也可以,但是当将深度作为纹理从

  • 我在游戏中使用延迟渲染器。因此,第一个渲染过程是使用多个渲染rarget创建反照率和法线缓冲区,并填充深度缓冲区。所有这些缓冲区实际上都是纹理。 现在我想从其他渲染通道访问深度缓冲区,从而访问其他帧缓冲区,而不改变深度纹理。我只想读取深度值。对于这些通道,我主要绘制全屏四边形,我不希望他们更新深度纹理并将其消隐为深度值0。 如何将一个给定的深度纹理附加到另一个帧缓冲区,并确保它是只写的?

  • 在DirectX中,您可以有单独的渲染目标和深度缓冲区,因此可以绑定渲染目标和一个深度缓冲区、执行一些渲染、移除深度缓冲区然后使用旧的深度缓冲区作为纹理进行更多渲染。 你会如何在opengl中做到这一点?根据我的理解,您有一个帧缓冲区对象,其中包含颜色缓冲区和可选的深度缓冲区。我不认为我可以同时绑定多个帧缓冲器对象,我是否必须在每次更改时(可能一帧几次)重新创建帧缓冲器对象?普通的 opengl