2013-07-24 1 views
2

Я хотел бы нарисовать текстурированный круг в Direct3D, который выглядит как настоящая трехмерная сфера. Для этого я взял бильярдного шара и попытался написать пиксельный шейдер в HLSL, который отображает его на простой предварительно преобразованный квадратик таким образом, что он выглядит как трехмерная сфера (кроме освещения , конечно).Рисование вращающейся сферы с использованием пиксельного шейдера в Direct3D

Это то, что я получил до сих пор:

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

Как вы можете видеть, отпечаток мяча выглядит неестественно деформирована, когда она достигает края. Может ли кто-нибудь увидеть причину этого? И, кроме того, как я мог выполнять вращения вокруг произвольной оси?

Заранее благодарен!

ответ

4

Я, наконец, нашел ошибку самостоятельно: вычисление значения z, которое соответствует текущей точке (x, y) на передней половине сферы, было неправильным. Это, конечно, должны быть:

z on a unit sphere

Вот и все, он работает как exspected в настоящее время. Кроме того, я выяснил, как вращать сферу. Вам просто нужно повернуть точку p перед вычислением u и v, умножив ее на матрицу 3D-вращения, например this one.

Результат выглядит следующим образом:

rotating billard ball

Если у кого есть какие-либо рекомендации относительно того, как я мог бы сгладить текстуру Литт немного, пожалуйста, оставьте комментарий.