3

ゲーム エンジンで 3D タイル オブジェクト間の継ぎ目をより適切に処理する方法を見つけるのに苦労しています。カメラがこのように十分な角度で下に傾けられた場合にのみ、それらが表示されます...テクスチャの問題またはテクスチャレンダリングの問題ではないと思います(ただし、間違っている可能性があります)。

以下に 2 つのスクリーンショットを示します。最初のスクリーンショットは問題を示し、2 番目のスクリーンショットは Blender でタイルに使用している UV ラッピングです。小さいミップマップでテクスチャをオーバードローする必要がある場合でも、うまくいくように、UV にオーバーラップのための余地を用意しています。次のテクスチャ パラメータを使用してテクスチャをロードしています。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

3D タイルの側面がわずかに描かれているように見えます。特に、この角度から適用されている照明角度 (指向性) によるアーティファクトに気付きます。

この影響を排除するためにチェックできるトリックやものはありますか? 「レイヤー」でレンダリングしていますが、カメラの距離に基づいてそれらのレイヤー内でレンダリングしています(最初に遠い)。これらのオブジェクトはすべて同じレイヤーにあります。どんなアイデアでも大歓迎です!

役に立ったら、これは OpenGLES2.0 を使用した iPhone/iPad 用のプロジェクトです。コード スニペットがあれば喜んで提供します。開始するのに適した場所を教えてください。

低角度でのタイル間の継ぎ目を示すエンジンのスクリーンショット

Blender からの UV

頂点/ピクセル シェーダーとモデル頂点による更新

現在、私は PowerVR の POD 形式を使用して、Blender からエクスポートされたモデル データを保存しています (Collada を介して、次に PowerVR による Collada2Pod コンバーターを介して)。GL_SHORT 頂点座標 (モデル空間) は次のとおりです。

64 -64 32
64 64 32
-64 64 32
-64 -64 32
64 -64 -32
-64 -64 -32
-64 64 -32
64 64 -32
64 -64 32
64 -64 -32
64 64 -32
64 64 32
64 64 32
64 64 -32
-64 64 -32
-64 64 32
-64 64 32
-64 64 -32
-64 -64 -32
-64 -64 32
64 -64 -32
64 -64 32
-64 -64 32
-64 -64 -32

したがって、すべてが完全に平らになるはずです。シェーダーは次のとおりです。

attribute highp vec3  inVertex; 
attribute highp vec3  inNormal;
attribute highp vec2  inTexCoord;

uniform highp mat4  ProjectionMatrix;
uniform highp mat4  ModelviewMatrix;
uniform highp mat3  ModelviewITMatrix;
uniform highp vec3  LightColor;
uniform highp vec3  LightPosition1;
uniform highp float LightStrength1;
uniform highp float LightStrength2;
uniform highp vec3  LightPosition2;
uniform highp float Shininess;

varying mediump vec2  TexCoord;
varying lowp    vec3  DiffuseLight;
varying lowp    vec3  SpecularLight;

void main()
{
    // transform normal to eye space
    highp vec3 normal = normalize(ModelviewITMatrix * inNormal);

    // transform vertex position to eye space
    highp vec3 ecPosition = vec3(ModelviewMatrix * vec4(inVertex, 1.0));

    // initalize light intensity varyings
    DiffuseLight = vec3(0.0);
    SpecularLight = vec3(0.0);

    // Run the directional light
    PointLight(true, normal, LightPosition1, ecPosition, LightStrength1);
    PointLight(true, normal, LightPosition2, ecPosition, LightStrength2);

    // Transform position
    gl_Position = ProjectionMatrix * ModelviewMatrix * vec4(inVertex, 1.0);

    // Pass through texcoords and filter
    TexCoord = inTexCoord;
}      
4

2 に答える 2

2

あなたのボックスがどのように描かれているかはわかりませんが、これが問題だと思います。各ボックスの頂点を計算するとき、次のようなことをすると思います(疑似コード)

int i、j、k;
浮き幅

ディムの i、j、k の場合:
  upper_left = (i,j,k)*幅;
  upper_right = (upper_left.x+width,upper_left.y,upper_left.z);
  lower_left = (upper_left.x, upper_left.y+width,upper_left.z);
  lower_right = (upper_left.x+幅,upper_left.y+幅,upper_left.z);

追加すると精度が失われ、同じ位置を共有する必要があるコーナーが実際には共有されないため、これは失敗します。これがギャップを作っているのです。

代わりに、このようなことをする必要があります

i、j、k:
  upper_left = (i,j,k)*幅;
  upper_right = (i+1,j,k)*幅;
  左下 = (i,j+1,k)*幅;
  右下 = (i+1,j+1,k)*幅;

これにより、コーナーが同じ座標を使用することが保証されます。

編集

まだまだ精度の問題です。私が理解していることから、ブロックごとにドローコールを行っています。ブロックごとに変更されるのはModelviewMatrix. これは、この行が期待されていることを意味します

位置 = ProjectionMatrix * ModelviewMatrix * vec4(inVertex, 1.0);

inVertex と ModelviewMatrix の 2 つの異なる値に対して同じ値が返されますが、これは誤りです。

これを解決するには、インスタンスごとの値をユニフォームに保存し、属性で指定されたインデックスから属性ごとの値を計算することにより、「偽の」インスタンス化を行うことができます (ES はインスタンス化をサポートしていないため)。

編集2:

わかりました、今のところ「偽の」インスタンス化について考えないでください。ここで、座標が同じであることを確認してください。したがって、1 つのブロックだけに座標を提供する代わりに、代わりにすべてのブロックに座標を提供し、1 つの ModelViewMatrix だけを使用します。その方が早さもありそうですね。

于 2011-08-30T06:53:20.123 に答える
1

これらを試してください

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
于 2011-08-31T15:06:41.473 に答える