7

ハイトマップを生成し、それをOpenGLでメッシュとして表示するプログラムがあります。照明を追加しようとすると、メッシュを覆う奇妙な正方形になってしまいます。それらは他の領域よりもいくつかの領域でより目立ちますが、常にそこにあります。

クワッドメッシュを使用していましたが、トライアングルメッシュに切り替えても何も変わりませんでした。頂点法線を計算するために少なくとも3つの異なる方法を使用しましたが、すべて同じ効果があります。シェーダーを使用して手動で照明を行っていましたが、組み込みのOpenGL照明システムを使用しても何も変わりません。

私の最新の通常生成コード(facesは頂点へのインデックスの配列、頂点配列です):

int i;
for (i = 0; i < NINDEX; i += 3) {
    vec v[3];
    v[0] = verts[faces[i + 0]];
    v[1] = verts[faces[i + 1]];
    v[2] = verts[faces[i + 2]];

    vec v1 = vec_sub(v[1], v[0]);
    vec v2 = vec_sub(v[2], v[0]);

    vec n = vec_norm(vec_cross(v2, v1));

    norms[faces[i + 0]] = vec_add(norms[faces[i + 0]], n);
    norms[faces[i + 1]] = vec_add(norms[faces[i + 1]], n);
    norms[faces[i + 2]] = vec_add(norms[faces[i + 2]], n);
}

for (i = 0; i < NVERTS; i++) {
    norms[i] = vec_norm(norms[i]);
}

私が使ったコードはそれだけではありませんが、それが問題の原因ではないかと思います。

メッシュを描画します:

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, verts);

glEnableClientState(GL_NORMAL_ARRAY);
glNormalPointer(GL_FLOAT, 0, norms);

glDrawElements(GL_TRIANGLES, NINDEX, GL_UNSIGNED_SHORT, faces);

そして、私は現在シェーダーを使用していません。

これを引き起こしている可能性がありますか?

編集:スクリーンショットのより包括的なセット:

最後の1つについては、シェーダーコードは

バーテックス:

varying vec3 lightvec, normal;

void main() {
    vec3 lightpos = vec3(0, 0, 100);
    vec3 v = vec3(gl_ModelViewMatrix * gl_Vertex);
    normal = gl_NormalMatrix * gl_Normal;

    lightvec = normalize(lightpos - v);

    gl_Position = ftransform();
}

断片:

varying vec3 lightvec, normal;

void main(void) {
    float l = dot(lightvec, normal);
    gl_FragColor = vec4(l, l, l, 1);
} 
4

2 に答える 2

2

次のように、フラグメントシェーダーで法線を正規化する必要があります。

varying vec3 lightvec, normal;

void main(void) {
    vec3 normalNormed = normalize(normal);
    float l = dot(lightvec, normalNormed);
    gl_FragColor = vec4(l, l, l, 1);
} 

ただし、これは高額になる可能性があります。この場合、指向性ライトでも機能するのは、頂点ライトを使用することです。したがって、頂点シェーダーでライト値を計算します

varying float lightItensity;

void main() {
    vec3 lightpos = vec3(0, 0, 100);
    vec3 v = vec3(gl_ModelViewMatrix * gl_Vertex);
    normal = gl_NormalMatrix * gl_Normal;

    lightvec = normalize(lightpos - v);

    lightItensity = dot(normal, lightvec);

    gl_Position = ftransform();
}

フラグメントシェーダーで使用し、

varying float light;

void main(void) {
    float l = light;
    gl_FragColor = vec4(l, l, l, 1);
} 

これで修正されることを願っています。修正されない場合はお知らせください。

編集:これは、最も起こりそうなことを説明する小さな図です

ここに画像の説明を入力してください

EDIT2:

それでも問題が解決しない場合は、三角形を追加します。ハイトマップの値を補間し、間にいくつかの頂点を追加します。

または、テッセレーションスキームを変更してみてください。たとえば、そのような正三角形のメッシュは、アーティファクトを目立たなくする可能性があります。

ここに画像の説明を入力してください

ハイトマップで補間を行う必要があります。

そうでなければ私にはわかりません..頑張ってください!

于 2012-06-13T19:59:17.113 に答える
1

非シェーダーバージョンの明確な答えはありませんが、フラグメントシェーダーでピクセル単位照明を行う場合は、フラグメントシェーダー内の通常のライトベックとlightvecを正規化する必要があることを付け加えたいと思います。

これを行わない場合、それらは単位長ではありません(2つの正規化されたベクトル間の線形補間は必ずしも正規化されません)。ドット積の大きさは頂点からの距離の関数として変化するため、これはシェーダーバージョンで表示されるアーティファクトの一部を説明する可能性があります。これは、表示されているもののように見えます。

編集:別の考えですが、非シェーダーバージョンをレンダリングするときに、メッシュの不均一なスケーリング(異なるx、y、z)を実行していますか?スケーリングする場合は、法線を逆スケール係数で変更するか、を設定する必要がありますglEnable(GL_NORMALIZE)。詳細については、こちらを参照してください: http ://www.lighthouse3d.com/tutorials/glsl-tutorial/normalization-issues/

于 2012-06-13T17:02:57.360 に答える