1

我生成简单的二维网格,三角形带代表水面。第一个生成的顶点位置为 [0,0],最后一个顶点的位置为 [1,1]。对于我的水模拟,我需要将顶点的当前位置存储到纹理中,然后从下一帧的纹理中采样这些值以获得水面的先前状态。

所以,我创建了顶点大小的纹理。例如,如果我将有一个 10x10 的顶点网格,我将使用具有 10x10 像素的纹理(一个像素对应一个顶点数据)。并将此纹理设置为渲染目标以将所有顶点数据渲染到其中。

根据这个:MSDN Coordinate Systems,如果我将使用网格中顶点的当前位置(左下角 [0;0],右上角 [1;1]),渲染纹理如下所示:

在此处输入图像描述

所以我需要对 NDC 做一些转换。我将它转换为这样的顶点着色器:

[顶点.x * 2 - 1; 顶点.y * 2 - 1]

考虑这个 3x3 网格:

在此处输入图像描述

现在,网格被拉伸到整个纹理大小。纹理坐标与 NDC 不同,显然我可以使用网格的原始坐标(转换之前)从纹理中采样值并获取顶点的先前值(位置)。

这是我的顶点/像素着色器代码示例:

此顶点着色器转换坐标并将其发送到具有 SV_POSITION 语义的像素着色器(描述像素位置)。

struct VertexInput 
{
    float4 pos : POSITION;
    float2 tex : TEXCOORD;
};

struct VertexOutput 
{
    float4 pos : SV_POSITION;
    float2 tex : TEXCOORD;
};

// convertes coordinates from 0,0 origin to -1,-1, etc.
float2 toNDC(float2 px)
{
    return float2(px.x * 2 - 1, px.y * 2 - 1);
}

VertexOutput main( VertexInput input )
{
    VertexOutput output;

    float2 ndc = toNDC(float2(input.pos.x, input.pos.z));

    output.pos = float4(ndc, 1, 1);
    output.tex = float2(input.pos.x, input.pos.z);

    return output;
}

这是像素着色器在定义的像素位置(SV_POSITION)保存顶点着色器的值。

struct PixelInput
{
    float4 pos : SV_POSITION;
    float2 tex : TEXCOORD;
};

float4 main(PixelInput input) : SV_TARGET
{
    return float4(input.tex.x, input.tex.y, 0, 1);
}

我们终于解决了我的问题!我在 Visual Studio 2012 中使用图形调试器,它允许我查看渲染的纹理及其值。我希望在像素位置 [0,1] (在纹理坐标系中)应该是值 [0,0] (或者 [0,0,0,1] 是精确的,对于 RGBA 格式),但似乎最终像素的值在 3 个顶点之间插值,并且给定顶点的值错误。

VS 图形调试器的屏幕截图:

渲染的 3x3 纹理(纹理坐标系中的 [0;1] 位置):

在此处输入图像描述

来自顶点和像素着色器的值:

在此处输入图像描述

如何将顶点着色器的精确值渲染到给定像素的纹理?我对计算机图形和 Direct3D 11 还很陌生,所以请原谅我的不足。

4

0 回答 0