D3D11 Post 暗图像中的着色器结果

D3D11 Post Shader Results in Dark Image

我正在尝试实施 post 着色器(像素着色器)作为测试。我有一个所有东西都渲染到的纹理,post 着色器只是将这个纹理复制到后台缓冲区。

如果此纹理大于后台缓冲区,post 着色过程会导致变暗:

但是,如果此纹理与后台缓冲区大小相同(或更小),post 着色过程将以精确副本结束:

post着色器非常简单:

struct VSOut {
    float4 position : SV_Position;
    float2 uv : TexCoord;
};

float time;

Texture2D inTex;

SamplerState textureSampler = sampler_state {
    Texture = inTex;
    MagFilter = point;
    MinFiler = point;
    AddressU = clamp;
    AddressV = clamp;
};

float4 main(VSOut vs) : SV_TARGET {
    float4 color = inTex.Sample(textureSampler, vs.uv);

    return color;
}

而在它之前的顶点着色器只是一个全屏三角形:

struct VSOut {
    float4 position : SV_Position;
    float2 uv : TexCoord;
};

VSOut main(uint vertexID : SV_VertexID) {
    VSOut result;

    result.uv = float2((vertexID << 1) & 2, vertexID & 2);
    result.position = float4(result.uv * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f), 0.0f, 1.0f);

    return result;
}

我试过更改 post 着色器中的过滤器,但这似乎不会影响颜色。为什么会发生这种情况?

编辑:根据要求,渲染纹理创建代码:

D3D11_TEXTURE2D_DESC Desc2D;

Desc2D.Width = 1280; //Window is 720p - this produces a bright image
Desc2D.Height = 720;
Desc2D.MipLevels = 0;
Desc2D.ArraySize = 1;
Desc2D.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
Desc2D.SampleDesc.Count = 1;
Desc2D.SampleDesc.Quality = 0;
Desc2D.Usage = D3D11_USAGE_DEFAULT;
Desc2D.CPUAccessFlags = NULL;
Desc2D.MiscFlags = NULL;
Desc2D.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;

hr = Device->CreateTexture2D(&Desc2D, nullptr, &PreRenderTexture);

您正在通过设置 D3D11_TEXTURE2D_DESC::MipLevels=0 使用一整套 mipmap 创建渲染纹理。请参阅文档 here

当您渲染到纹理时,大概只渲染到顶级 mipmap。其他 mipmap 级别,虽然在技术上未定义(来自 CreateTexture2D 上的文档),但通常开始时是黑色的。

在您的着色器中,您对渲染纹理进行采样。当它是屏幕的确切尺寸或更小时,您总是对最高的 milevel 进行采样,其中包含您的渲染结果。如果纹理较大,一些像素将来自较低级别的 mipmap,并且是未定义的(但可能是黑色的,如前所述)。这会产生抖动类型的效果,并使结果变暗。

有很多解决办法。最简单的方法是创建只有一个级别的渲染目标,其他级别可能是不必要的。您还可以将着色器中的采样偏置为始终在 HLSL 中使用带有 SampleLevel 的顶层。或者,您可以为渲染目标中的较低级别生成 mip 链。或者,您始终可以将纹理设置为屏幕大小或更小。