2

XNAプロジェクト用にHLSLでアニメーション化された太陽を作成しようとしています。

このサイトから学んだパーリン ノイズアルゴリズムを使用して、ピクセル シェーダーでテクスチャを生成しています。

これは、ピクセル シェーダー用に書いた hlsl コードです。

sampler myTexture;

struct VS_Output{
   float4 Position : POSITION0;
   float4 Color : COLOR0;
   float2 TextCoord : TEXCOORD0;
};

float CosineInterpolation( float x, float y, float fractional ) {
   float ft = 3.141592f * fractional;
   float f = ( 1.0f - cos( ft ) ) * 0.5f;

   return x * ( 1.0f - f ) + y * f;
}

float Noise(float2 xy)
{
    float2 noise = (frac(sin(dot(xy ,float2(12.9898,78.233)*2.0)) * 43758.5453));
    return abs(noise.x + noise.y) * 0.5;
}

float SmoothNoise( float integer_x, float integer_y ) {
   float corners = ( Noise( float2(integer_x - 1, integer_y - 1) ) + Noise( float2(integer_x + 1, integer_y + 1 )) + Noise( float2(integer_x + 1, integer_y - 1 )) + Noise( float2(integer_x - 1, integer_y + 1 )) ) / 16.0f;
   float sides = ( Noise( float2(integer_x, integer_y - 1 )) + Noise( float2(integer_x, integer_y + 1 )) + Noise( float2(integer_x + 1, integer_y )) + Noise( float2(integer_x - 1, integer_y )) ) / 8.0f;
   float center = Noise( float2(integer_x, integer_y )) / 4.0f;

   return corners + sides + center;
}

float InterpolatedNoise( float x, float y ) {
   float integer_x = x - frac(x), fractional_x = frac(x);
   float integer_y = y - frac(y), fractional_y = frac(y);

   float p1 = SmoothNoise( integer_x, integer_y );
   float p2 = SmoothNoise( integer_x + 1, integer_y );
   float p3 = SmoothNoise( integer_x, integer_y + 1 );
   float p4 = SmoothNoise( integer_x + 1, integer_y + 1 );

   p1 = CosineInterpolation( p1, p2, fractional_x );
   p2 = CosineInterpolation( p3, p4, fractional_x );

   return CosineInterpolation( p1, p2, fractional_y );
}

float CreatePerlinNoise( float x, float y ) {
    float result = 0.0f, amplitude = 0.0f, frequency = 0.0f, persistance = 0.1f;

    for ( int i = 1; i <= 4; i++ ) {
       frequency += 2;
       amplitude += persistance;

       result += InterpolatedNoise( x * frequency, y * frequency ) * amplitude;
    }

    return result;
}

float4 ps_main(VS_Output Input) : COLOR0
{  
   float index = CreatePerlinNoise(Input.TextCoord.x*256.0f, Input.TextCoord.y*256.0f);
   return tex2D(myTexture, index);
}

基本的に、このコードでは、テクスチャ座標コンポーネント ( TextCoord) を関数に渡すことで、グラデーション テクスチャ ( 1px x 256px )CreatePelinNoiseのカラー インデックスとして使用される値を返します。myTexture

ここに画像の説明を入力

AMD RenderMonkeyでの結果は次のとおりです。

ここに画像の説明を入力

しかし、球の極には、生成されたテクスチャが不均一になる見苦しい不要な効果があります。

ここに画像の説明を入力

この問題を解決し、生成されたテクスチャを均一にするにはどうすればよいですか?

4

1 に答える 1

4

これは、ノイズ関数を 2D テクスチャとして扱っているために発生します。これは、球に投影されると引き伸ばされたり歪んだりします基本的には、ピクセル シェーダーで 2D テクスチャをリアルタイムで生成し、それを球体に適用します。

パーリン ノイズの原理を本当に理解していれば、コードを 2 次元以上に一般化できます。Ken Perlin 自身も、ノイズ アルゴリズムを発明したときに、これとまったく同じアイデアを思いつきました。彼自身の言葉によると、「オブジェクトをプロシージャル テクスチャ (ノイズ) マテリアルのスープに浸す」。

ピクセル座標を 3D ノイズ関数 (float4 Position 変数) の入力として使用するだけで、カラー マッピング コードは損なわれません。これにより、目的の効果が得られるはずです。ちなみに、アニメーション化する場合は、4D に一般化して、4 番目のパラメーターを時間とともに変化させます。正しく行えば、素晴らしい「溶岩惑星」効果が得られるはずです (詳細については、Perlin のスライドを参照してください)。

ああ、スピードアップのヒント: コサイン補間を使用する代わりに、有名な 3*t^2-2*t^3 補間曲線を使用してください。0 から 1 の間では、高調波とほとんど同じように見えますが、計算コストは​​はるかに低くなります。

于 2013-01-02T00:08:26.990 に答える