簡體   English   中英

頂點着色器中的采樣返回緩沖區始終返回0和float1而不是float4

[英]Sampling Back Buffer in vertex Shader always returns 0 and float1 instead of float4

我現在完全迷路了。 幾天來一直在嘗試讀取頂點着色器中的backbuffer,但沒有任何運氣。

我正在嘗試從后緩沖區及其附近的像素讀取頂點位置。 (我試圖計算頂點周圍有多少個黑色像素,以及像素着色器中是否有頂點紅色的顏色)。 我創建了一個單獨的ID3D11Texture2D和一個SRV與backBuffer一起使用。 我將后緩沖區復制到此SRV的資源中。 使用VSSetShaderResources綁定SRV,但似乎無法從頂點着色器中讀取SRV。

我將在此處分享這些元素的創建過程中的一些代碼,以及一些RenderDoc屏幕快照,這些屏幕快照始終顯示SRV已綁定到VS舞台並具有正確的紋理,但每個Load或[] operator或tex2dlod或SampleLevel(我也綁定了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,並將其綁定到應該采樣的下一個着色器。 當我在屏幕上的頂點位置采樣后緩沖時,我期望返回一個float4(1.0,1.0,1.0,1.0)值

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

如事件瀏覽器左上角所示,有三個drawindexed調用以白色呈現所有內容,然后是CopyResource。 我選擇了下一個(第四個)DrawIndexed,並在右側用紅色勾勒出了下一個着色器的輸入,清楚地表明backBuffer已成功綁定到頂點着色器。

現在讓我麻煩的部分

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

我將如屏幕截圖所示調試該左上角的頂點,該頂點着色器具有Texture2D prevBackBuffer:register(t0); 寫在頂部

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

當嘗試采樣左相鄰像素時,此代碼行在紋理視圖中輸入這些像素值時返回newCoord = float2(158,220),我得到了這個像素

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

因此,以我的經驗來看,從后台緩沖區讀取並不是真正要首先執行的操作。 如果必須對渲染的場景進行任何操作,最好的方法是將場景渲染為中間紋理,對該紋理執行操作,然后將最終的場景渲染到后台緩沖區。 通常這是完成動態陰影之類的方式-從燈光的角度渲染場景,然后解釋生成的緩沖區以獲取陰影值,然后將其應用於最終場景(這也是為什么動態光源是受限於商業游戲引擎-使用起來相當昂貴)。

類似的想法可以在這里應用。 首先,將整個場景渲染為中間紋理,綁定為渲染目標視圖(其中像素格式由您( 程序員 )指定)。 接下來,將中間紋理重新綁定為着色器資源視圖,並使用邊緣檢測着色器和實際的后緩沖區(其中像素格式由硬件定義)再次渲染場景。

從根本上講,這就是我認為的問題-后備緩沖區是與設備相關的資源,其格式可以根據硬件而改變。 因此,從着色器使用它並不安全,因為您並不總是知道格式是什么。 另一方面,與設備無關的資源將始終具有相同的格式,並且可以從着色器中隨意使用,但可以放心使用。

我無法在頂點着色器中對SRV進行采樣,但是我能夠使用的是在計算着色器中使用backBuffer.SampleLevel,我還必須將采樣器更改為如下所示:

D3D11_SAMPLER_DESC samplerDesc;

samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_BORDER;
samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_BORDER;
samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_BORDER;
samplerDesc.MipLODBias = 0.0f;
samplerDesc.MaxAnisotropy = 1;
samplerDesc.ComparisonFunc = D3D11_COMPARISON_ALWAYS;
samplerDesc.BorderColor[0] = 0.5f;
samplerDesc.BorderColor[1] = 0.5f;
samplerDesc.BorderColor[2] = 0.5f;
samplerDesc.BorderColor[3] = 0.5f;
samplerDesc.MinLOD = 0;
samplerDesc.MaxLOD = 0;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM