将一堆值渲染到rendertarget时遇到一些麻烦。这些值永远不会在我想要它们的确切范围内。基本上,我使用全屏四边形和像素着色器渲染到我的rendertarget纹理,然后打算将纹理坐标用作着色器中某些计算的基础。四边形的纹理坐标范围从左上角的(0,0)到右下角的(1,1)...问题是,插值后,这些值没有像这样到达像素着色器。
一个示例: 我渲染为4x4纹理,在这种情况下,着色器仅在红色和绿色通道中输出纹理坐标(u,v):
return float4(texCoord.rg, 0, 1);
我要摆脱的是一种纹理,其中左上角的像素是RGB(0,0,0),因此是黑色,右上角的像素是RGB(255,0,0),因此是明亮的红色,左下角的像素为RGB(0,255,0)-亮绿色。
但是,相反,我在这里得到此:
(直四边形渲染,无校正)
左上方的像素是黑色,但在其他角落我只能得到相对深红色和深绿色。它们的RGB值为(191,0,0)和(0,191,0)。我强烈怀疑它与四边形的采样位置有关:左上像素正确地对四边形的左上角进行采样,并获得(0,0)作为UV坐标,但其他角点像素未从中采样四边形的其他角。我已经在左图中说明了这一点,蓝色框代表四边形,白色点代表上采样坐标。
现在,我知道在Direct3D9中渲染屏幕对齐的四边形时应将半像素偏移应用于坐标。让我们看看我从中得到什么样的结果:
(以DX9的半像素偏移量渲染的四进制)
红色和绿色变亮,但仍然不正确:223是我在红色或绿色通道上获得的最大值。但是现在,我什至没有纯黑色,而是带有RGB(32,32,0)的深黄灰色!
我真正需要的是这种渲染:
(目标渲染,减小的四边形尺寸)
与第一个图形相比,看起来我必须将四边形的右边界和底边界恰好向左移动一个像素。然后,像素的右列和底行都应正确地从四边形的边界正确获取UV坐标:
VertexPositionTexture[] quad = new VertexPositionTexture[]
{
new VertexPositionTexture(new Vector3(-1.0f, 1.0f, 1f), new Vector2(0,0)),
new VertexPositionTexture(new Vector3(1.0f - pixelSize.X, 1.0f, 1f), new Vector2(1,0)),
new VertexPositionTexture(new Vector3(-1.0f, -1.0f + pixelSize.Y, 1f), new Vector2(0,1)),
new VertexPositionTexture(new Vector3(1.0f - pixelSize.X, -1.0f + pixelSize.Y, 1f), new Vector2(1,1)),
};
但是,这还没有完全解决,导致底部和右侧像素根本无法渲染。我想这些像素的中心不再被四边形覆盖,因此不会被着色器处理。如果我将pixelSize的计算量更改为微小的量,以使四边形稍大一些,则至少在4x4纹理上有效。它不适用于较小的纹理,并且我担心它会巧妙地扭曲uv值在较大纹理上的均匀分布:
Vector2 pixelSize = new Vector2((2f / textureWidth) - 0.001f, (2f / textureHeight) - 0.001f);
(我将pixelSize的计算值修改为0.001f-对于较小的纹理,例如1D查找表,此方法无效,我必须将其增大到0.01f或更大的值)
当然,这是一个简单的示例,我可以在CPU上更轻松地执行此计算,而不必担心将UV映射到像素中心……不过,仍然必须有一种方法可以实际渲染完整,完整的[0, 1]在rendertarget上的像素范围!