我生成简单的2D网格,其中三角形条带代表水面。第一个生成的顶点具有位置[0,0],最后一个具有[1,1]。对于我的水模拟,我需要将顶点的当前位置存储到纹理中,然后从下一帧中的纹理中采样这些值以获得水面的先前状态。
所以,我创建了一个顶点大小的纹理。例如,如果我将有一个10x10顶点网格,我使用一个10x10像素的纹理(一个顶点数据一个像素)。并将此纹理设置为渲染目标,以将所有顶点数据渲染到其中。
根据这个:MSDN Coordinate Systems,如果我将使用网格中顶点的当前位置(左下角为[0; 0],右上角为[1; 1]),渲染纹理看起来像这样:
所以我需要转换到NDC。我在这样的顶点着色器中转换它:
[vertex.x * 2 - 1; vertex.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都很陌生,所以请原谅我的不足之处。