2

我有两个渲染目标视图,我的后台缓冲区和一个表示专用掩码的 Texture2D(我不能使用模板缓冲区来满足我的需要)。我的渲染方法大致如下:

// clear the render target and depth stencil views, set render targets, 
// update subresources, set vertex buffers, topology, input layout, etc.

// draw to the back buffer and the mask
m_d3dContext->PSSetShader(m_pixelShader1.Get(), nullptr, 0);
m_d3dContext->IASetIndexBuffer(m_indexBuffer1.Get(), DXGI_FORMAT_R16_UINT, 0); 
m_d3dContext->DrawIndexed(m_indexCount1, 0, 0);

// read from the mask and draw to the back buffer
m_d3dContext->PSSetShader(m_pixelShader2.Get(), nullptr, 0);
m_d3dContext->IASetIndexBuffer(m_indexBuffer2.Get(), DXGI_FORMAT_R16_UINT, 0);
m_d3dContext->DrawIndexed(m_indexCount2, 0, 0);

PixelShader1 看起来像这样(省略输入结构和其他一些部分):

struct PixelShaderInput
{
    float4 Color   : COLOR;
    float2 Texture : TEXCOORD;
};

struct PixelShaderOutput
{
    float4 Color : SV_TARGET0;
    float4 Mask  : SV_TARGET1;
};

PixelShaderOutput main(PixelShaderInput input)
{
    PixelShaderOutput output; 
    output.Color.rgba = input.Color;
    output.Mask.rgba = float4(1, 0, 0, 1);
    return output;
}

PixelShader2 看起来像这样:

struct PixelShaderInput
{
    float3 Color   : COLOR0;
    float2 Texture : TEXCOORD0;
    float4 Mask    : COLOR1;
};

struct PixelShaderOutput
{
    float4 Color : SV_TARGET0; 
};

PixelShaderOutput main(PixelShaderInput input)
{
    PixelShaderOutput output; 

    // do some work with input.Texture

    if (input.Mask.x == 0)
    {
        output.Color = float4(0, 0, 0, 1); }
    }
    else
    {
        output.Color = float4(1, 1, 1, 1); 
    }

    return output;
}

使用 Visual Studio 的图形调试工具,可以看到 PixelShader1 正确写入了遮罩纹理。在帧的末尾,红色的几何图形出现在正确的位置。此外,后台缓冲区的输出(看起来不同)也符合预期。所以我坚信 PixelShader1 是正确的。

但是,我从 PixelShader2 得到了意想不到的结果。通过它,input.Mask.x 的值到处都是。人们会期望它们为 1 或 0,因为这是所有其他像素着色器将它们设置为的值,但是这些值看起来非常像纹理坐标。

那么,首先,我正在尝试做的事情是否可能?如果是的话,谁能发现我在阅读 COLOR1 时的错误?我已经被这件事难住了好几个小时,所以任何帮助都将不胜感激。

我正在使用 DirectX 11、着色器模型 4.0 级别 9_1 和 vc110。

4

1 回答 1

1

您的 PixelShader2 的编写方式有一些概念错误。PixelShader1 将 Color 和 Mask 的值写入两个渲染纹理。在 PixelShader 2 中,您需要从纹理中读取这些值,而不是作为顶点输入。

Texture2D<float4> MaskTexture;
SamplerState MaskSampler;

struct PixelShaderInput
{
    float3 Color   : COLOR0;
    float2 Texture : TEXCOORD0;
};

struct PixelShaderOutput
{
    float4 Color : SV_TARGET0; 
};

PixelShaderOutput main(PixelShaderInput input)
{
    PixelShaderOutput output; 

    // do some work with input.Texture

    float maskValue = MaskTexture.Sample(MaskSampler, Texture).x;

    if (maskValue == 0)
    {
        output.Color = float4(0, 0, 0, 1);
    }
    else
    {
        output.Color = float4(1, 1, 1, 1); 
    }

    return output;
}

因此,为了做到这一点,您需要通过 SetShaderResources() 将 MaskTexture(这是您从 PixelShader1 输出的第二个渲染目标输出)作为 ShaderResource 传递。您还需要创建一个 SamplerState 并通过 SetSamplerStates() 将其设置到设备中。

于 2013-03-15T03:57:47.597 回答