gpt4 book ai didi

c++ - 顶点着色器中的采样后台缓冲区始终返回 0 和 float1 而不是 float4

转载 作者:太空宇宙 更新时间:2023-11-04 12:33:55 25 4
gpt4 key购买 nike

我现在完全迷路了。几天来一直在尝试读取顶点着色器中的后台缓冲区,但没有任何运气。

我正在尝试从后台缓冲区读取顶点位置及其相邻像素。 (我正在尝试计算一个顶点周围有多少个黑色像素,以及像素着色器中是否有任何颜色使顶点为红色)。我已经创建了一个单独的 ID3D11Texture2D 和一个 SRV 来与 backBuffer 一起使用。我将后备缓冲区复制到此 SRV 的资源中。使用 VSSetShaderResources 绑定(bind) SRV,但似乎无法在顶点着色器中读取它。

我将在这里分享一些创建这些元素的代码,并包括一些 RenderDoc 屏幕截图,这些屏幕截图不断显示 SRV 被绑定(bind)到 VS 阶段并具有与其关联的正确纹理,但每个 Load 或 []operator或 tex2dlod 或 SampleLevel(我也绑定(bind)了一个 SamplerState)只是一直返回一个 1.0 值,其余的 float4 永远不会返回,这意味着我只得到一个 float1。如果有人想看的话,我还会包含一个 renderdoc 捕获文件。

这是 rastertek.com 网站上教程 42 中的一个简单场景,有一个地平面,上面有一个立方体和一个球体:

https://i.imgur.com/cbVC48E.gif

// Here is some code when creating the secondary texture and SRV that houses a //backBuffer
// Get the pointer to the back buffer.
result = m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&backBufferPtr);
if(FAILED(result))
{
MessageBox((*(hwnd)), L"Get the pointer to the back buffer FAILED", L"Error", MB_OK);
return false;
}


// Create another texture2d that we will use to make an SRV out of, and this texture2d will be used to copy the backbuffer to so we can read it in a shader
D3D11_TEXTURE2D_DESC bbDesc;
backBufferPtr->GetDesc(&bbDesc);
bbDesc.MipLevels = 1;
bbDesc.ArraySize = 1;
bbDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
bbDesc.Usage = D3D11_USAGE_DEFAULT;
bbDesc.MiscFlags = 0;
bbDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
result = m_device->CreateTexture2D(&bbDesc, NULL, &m_backBufferTx2D);
if (FAILED(result))
{
MessageBox((*(m_hwnd)), L"Create a Tx2D for backbuffer SRV FAILED", L"Error", MB_OK);
return false;
}
D3D11_SHADER_RESOURCE_VIEW_DESC descSRV;
ZeroMemory(&descSRV, sizeof(descSRV));
descSRV.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
descSRV.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
descSRV.Texture2D.MipLevels = 1;
descSRV.Texture2D.MostDetailedMip = 0;
result = GetDevice()->CreateShaderResourceView(m_backBufferTx2D, &descSRV, &m_backBufferSRV);
if (FAILED(result))
{
MessageBox((*(m_hwnd)), L"Creating BackBuffer SRV FAILED.", L"Error", MB_OK);
return false;
}

// Create the render target view with the back buffer pointer.
result = m_device->CreateRenderTargetView(backBufferPtr, NULL, &m_renderTargetView);

首先,我将场景渲染成全白,然后将其复制到 SRV 并将其绑定(bind)到下一个应该对其进行采样的着色器。当我使用顶点在屏幕上的位置对后缓冲区进行采样时,我希望得到一个 float4(1.0, 1.0, 1.0, 1.0) 返回的值

https://i.imgur.com/N9CYg8c.png

如事件浏览器左上角所示,有三个 drawindexed 调用,用于将所有内容渲染为白色,然后是 CopyResource。我选择了下一个(第四个)DrawIndexed,右侧以红色标出的是下一个着色器的输入,清楚地表明 backBuffer 已成功绑定(bind)到顶点着色器。

现在来说说给我带来麻烦的部分

https://i.imgur.com/ENuXk0n.png

我将调试这个左上角的顶点,如屏幕截图所示,顶点着色器有一个Texture2D prevBackBuffer:寄存器(t0);写在最上面

https://i.imgur.com/8cihNsq.png

尝试对左相邻像素进行采样时这行代码返回 newCoord = float2(158, 220)在纹理 View 中输入这些像素值时,我得到了这个像素

https://i.imgur.com/DT72Fl1.png

所以到目前为止坐标没问题,并且正如我所概述的,我希望在对该像素进行采样时返回一个 float4(0.0, 0.0, 0.0, 1,0)(我正在尝试计算一个顶点周围有多少黑色像素,以及像素着色器中是否有任何颜色使顶点为红色)

然而,当我在更改像素坐标后立即对该像素进行采样时,因为加载从左下角开始计算像素,所以我需要newCoord = float2(158, 379),我明白了

https://i.imgur.com/8SuwOzz.png

为什么会这样,即使它超出范围,负载也应该返回全零,因为我不确定从左下角开始的整个负载计数我尝试使用左上角坐标 (158, 220) 进行采样但结束上升 0.0, ?, ?, ?

我完全被难住了,不知道接下来要尝试什么。我试过使用示例状态:

// Create a clamp texture sampler state description.
samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
samplerDesc.MipLODBias = 0.0f;
samplerDesc.MaxAnisotropy = 1;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
samplerDesc.BorderColor[0] = 0;
samplerDesc.BorderColor[1] = 0;
samplerDesc.BorderColor[2] = 0;
samplerDesc.BorderColor[3] = 0;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;

// Create the texture sampler state.
result = device->CreateSamplerState(&samplerDesc, &m_sampleStateClamp);

但在读取纹理时仍然无法返回正确的 float4。

任何想法、建议,我都会接受。哦,这是我正在检查的帧的 RenderDoc 文件: http://www.mediafire.com/file/1bfiqdpjkau4l0n/my_capture.rdc/file

最佳答案

所以根据我的经验,从后台缓冲区读取并不是您首先想要执行的操作。如果必须对渲染场景进行任何操作,最好的方法是将场景渲染到中间纹理,对该纹理执行操作,然后将最终场景渲染到后台缓冲区。这通常是动态阴影之类的事情的完成方式——场景是从光的角度渲染的,结果缓冲区被解释以获得阴影值,然后应用于最终场景(这也是为什么动态光源是仅限于商业游戏引擎——它们使用起来相当昂贵)。

这里可以应用类似的想法。首先,将整个场景渲染到中间纹理,绑定(bind)为渲染目标 View (其中像素格式由您指定,程序员)。接下来,将该中间纹理重新绑定(bind)为着色器资源 View ,并使用边缘检测着色器和真正的后台缓冲区(其中像素格式由硬件定义)再次渲染场景。

从根本上说,这就是我认为的问题所在 - 后台缓冲区是一种设备相关资源,它的格式可以根据硬件而改变。因此,从着色器中使用它并不安全,因为您并不总是知道格式是什么。另一方面,独立于设备的资源将始终具有相同的格式,您可以安全地从着色器中随意使用它。

关于c++ - 顶点着色器中的采样后台缓冲区始终返回 0 和 float1 而不是 float4,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57253953/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com