我想在Direct3D中绘制一个纹理圆,看起来像一个真正的3D球体。为此,我拿了一个texture的billard球并尝试在HLSL
中编写一个像素着色器,将其映射到一个简单的预变换四边形,使其看起来像一个3 - 维度球体(当然除了照明)。
这是我到目前为止所得到的:
struct PS_INPUT
{
float2 Texture : TEXCOORD0;
};
struct PS_OUTPUT
{
float4 Color : COLOR0;
};
sampler2D Tex0;
// main function
PS_OUTPUT ps_main( PS_INPUT In )
{
// default color for points outside the sphere (alpha=0, i.e. invisible)
PS_OUTPUT Out;
Out.Color = float4(0, 0, 0, 0);
float pi = acos(-1);
// map texel coordinates to [-1, 1]
float x = 2.0 * (In.Texture.x - 0.5);
float y = 2.0 * (In.Texture.y - 0.5);
float r = sqrt(x * x + y * y);
// if the texel is not inside the sphere
if(r > 1.0f)
return Out;
// 3D position on the front half of the sphere
float p[3] = {x, y, sqrt(1 - x*x + y*y)};
// calculate UV mapping
float u = 0.5 + atan2(p[2], p[0]) / (2.0*pi);
float v = 0.5 - asin(p[1]) / pi;
// do some simple antialiasing
float alpha = saturate((1-r) * 32); // scale by half quad width
Out.Color = tex2D(Tex0, float2(u, v));
Out.Color.a = alpha;
return Out;
}
我的四边形的纹理坐标范围从0到1,所以我首先将它们映射到[-1,1]。之后,我按照this article中的公式计算当前点的正确纹理坐标。
起初,结果看起来不错,但我希望能够随意旋转这个球体的错觉。所以我逐渐增加u
,希望围绕垂直轴旋转球体。这是结果:
正如您所看到的,当球到达边缘时,球的印记看起来不自然地变形。谁能看到任何理由呢?另外,我如何围绕任意轴实现旋转?
提前致谢!
答案 0 :(得分:4)
我终于找到了自己的错误:对应于球体前半部分当前点z
的{{1}}值的计算是错误的。当然必须是:
这就是全部,它现在正如预期的那样运作。此外,我想出了如何旋转球体。您只需在计算(x, y)
和p
之前旋转点u
,然后将其与例如this one之类的3D旋转矩阵相乘。
结果如下所示:
如果有人对如何平滑纹理有任何建议,请发表评论。