使用Direct3D中的像素着色器绘制旋转球体

时间:2013-07-24 16:41:14

标签: math mapping shader direct3d hlsl

我想在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,希望围绕垂直轴旋转球体。这是结果:

rotating billard ball

正如您所看到的,当球到达边缘时,球的印记看起来不自然地变形。谁能看到任何理由呢?另外,我如何围绕任意轴实现旋转?

提前致谢!

1 个答案:

答案 0 :(得分:4)

我终于找到了自己的错误:对应于球体前半部分当前点z的{​​{1}}值的计算是错误的。当然必须是:

z on a unit sphere

这就是全部,它现在正如预期的那样运作。此外,我想出了如何旋转球体。您只需在计算(x, y)p之前旋转点u,然后将其与例如this one之类的3D旋转矩阵相乘。

结果如下所示:

rotating billard ball

如果有人对如何平滑纹理有任何建议,请发表评论。