14

3D アイランドをレンダリングする OpenGL ES 2.0 アプリを作成しています。島の周りにスカイ ドームを生成するコードは既にあります。これは三角形で構成された半球で、島の上に z 点が上にあるように配置されています。

ドームには、パーリン ノイズ テクスチャをオーバーレイしてさまざまな速度で移動することで作成された、非常に基本的な移動する雲がいくつかあります。

しかし、最終的にはドームもレンダリングする必要があります。

  • 太陽 (空を横切って追跡) 月 (フェーズを含む)
  • 星(夜)
  • 静的テクスチャとしての遠い土地
  • 夜、夜明け、夕暮れ、昼をシミュレートするさまざまな色

現時点ではテスト ハーネスで実行されていますが、最終的には Android で実行されるため、これを非常に効率的に行う必要があります。したがって、たとえば、太陽、月、星はテクスチャにすぎませんが、それらのポイントは妥当な精度でプロットされる場合があります。

ドームを生成するコードと、日付と時刻に対して太陽をプロットするコードは既にあります。ほとんどの場合、私が必要とするシェーダーと、それらに付属するものです。

これらのことを示す例はありますか? 基本的なキューブ マップや限定的な機能を備えたものはたくさんありますが、必要なレベルの高度なものはありません。明らかに、これは OpenGL ES 2.0 であるため、シェーダーで実行する必要があります。

既存のスカイ ドームのシェーダーは、2 層のパーリン ノイズをレンダリングして雲をシミュレートします。テクスチャは連続的にラップするため、xy 平面に対するドームの頂点の角度に基づいて u オフセットを計算し (x と y を atan に入力することにより)、ドームの頂点 z を使用して v オフセットを計算できます。

頂点シェーダーは、私がそれを行う方法を示しています。

#ifdef GL_ES
precision mediump float;
precision mediump int;
#endif

attribute vec4 aVertex;

uniform mat4 uPMVMatrix;
uniform float uTime;
uniform float uSkyDomeRadius;

const float PI = 3.1415926535897932384626433832795;

varying vec2 texCoord0, texCoord1;

void main()
{
    vec2 centre = vec2(600., 600.);

    gl_Position = uPMVMatrix * aVertex;

    float slow_time = uTime / 100.;

    vec2 dome_point = aVertex.xy - centre;
    float tex_u = atan(dome_point.x, dome_point.y);// / (.25 * PI);
    float tex_v = aVertex.z / (uSkyDomeRadius * .5);

    texCoord0 = vec2(tex_u / 2.0 + slow_time, tex_v / 2.0);
    texCoord1 = vec2(tex_u + slow_time / 2.0, tex_v);
}

また、雲が動くように、フレームごとに ua bit をオフセットする時間を使用します。これは、atan が -PI から PI に移動し、フラグメント シェーダーが補間する texCoord0 と texCoord1 の値が突然、補間をホース処理する大きな距離で区切られていることを除いて、正常に機能します。

これを説明する最良の方法は、ベースに 16 個の三角形がある場合、0/16 から 1/16 への補間、1/16 から 2/16 への補間などであるということです。しかし、15/16 から 0/16 に到達すると、インターポレーターが逆方向に移動し、変動が大きいため、フラグ シェーダーが小さなスペースでテクスチャを何度も繰り返し、図のように縞模様になります。

角度が逆になると補間がうまくいかない

シームレスな 360 度のビューを表示する方法がわかりません。これを修正する唯一の方法は、ドーム全体を回転させて継ぎ目が常にカメラの後ろになるようにすることだと思いますが、カメラがまっすぐ上を向いている場合はまだ表示される可能性があります。ドームの頂上。

ソースを使用した実際の例は、特にこの種の問題に対処する場合に最適です。

4

1 に答える 1

3

問題は、0° と 360° の角度で同じ頂点を使用することです。これで、最初の頂点のテクスチャ座標が 15/16, 0 で、2 番目の頂点のテクスチャ座標が 1,0 ではなく 0, 0 の三角形ができました。これを修正するには、球体を開いて、同じ空間位置に 1 対の頂点 (1 つは 0°、もう 1 つは 360°) を持たせる必要があります。こうすることで、2 つの頂点が異なるテクスチャ座標を持つことができ、テクスチャが乱れることはありません。

それらを回転するには、ラッピング モードを使用する必要があります。テクスチャ ラッピングが繰り返すように設定されていることを確認してください。変更していない場合は、正しく設定する必要がありますが、 functionglTexParameterで設定できます。パラメーターはGL_TEXTURE_WRAP_SおよびGL_TEXTURE_WRAP_Tであり、値は である必要がありますGL_REPEAT。次に、テクスチャ値が > 1 の場合、ラップ アラウンドせずにテクスチャを繰り返します。これで、球体の始点 (0° の頂点) と終点 (360° の頂点) の頂点を区別できるようになるだけでよいので、修正できますtex_u。そのためにはおそらく追加の属性が必要です。

于 2012-12-23T17:39:12.273 に答える