3

我有一个 640x480 的渲染目标(它的主要后备缓冲区)。

我将一个全屏四边形传递给顶点着色器,全屏四边形的 X 和 Y 坐标都在 [-1,1] 之间,这意味着我只将坐标传递给像素着色器而不进行计算:

struct VSInput
{
    float4 Position : SV_POSITION0;
};

struct VSOutput
{
    float4 Position : SV_POSITION0;
};

VSOutput VS(VSInput input)
{
    VSOutput output = (VSOutput)0;
    output.Position = input.Position;
    return output;
}

但在像素着色器上,每个片段的 x 和 y 坐标位于屏幕空间中(0 < x < 640 和 0 < y < 480)。这是为什么?我一直认为坐标会在到达像素着色器的途中被插值并设置在 -1,1 之间,在这种情况下更是如此,因为我在顶点着色器上硬编码了 -1 和 1 之间的坐标!

但事实是,这个像素着色器有效:

float x = input.Position.x;

if(x < 200)
    output.Diffuse = float4(1.0, 0.0, 0.0, 1.0);
else if( x > 400)
    output.Diffuse = float4(0.0, 0.0, 1.0, 1.0);
else
    output.Diffuse = float4(0.0, 1.0, 0.0, 1.0);

return output;

它在我的渲染窗口上输出 3 条彩色条纹,但如果我将屏幕空间(上面代码中的 200 和 400)的值更改为 -1,1 空间并使用类似 if(x < 0.5) 的东西,它将无法工作。

我已经试过了

浮点 x = input.Position.x / input.Position.w;

因为我在某处读到这样我可以获得-1,1之间的值,但它也不起作用。

提前致谢。

4

1 回答 1

4

从关于 SV_POSITION的语义页面上的 MSDN :

在像素着色器中使用时,SV_Position 描述像素位置。

所以你看到了预期的行为。

最好的解决方案是将屏幕空间坐标作为附加参数传递。我喜欢使用这个“全屏三角形”顶点着色器:

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

// outputs a full screen triangle with screen-space coordinates
// input: three empty vertices
VSQuadOut VSQuad( uint vertexID : SV_VertexID ){
    VSQuadOut 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;
}

(原文出处:不带顶点缓冲的全屏四边形?

于 2012-11-27T23:51:56.870 回答