4

Appleのサンプルコードに基づいて、OpenGL-ESでかなり基本的な形状を作成しています。彼らはポイントの配列を使用し、最初の配列にインデックスの配列を入れ、3つのインデックスの各セットがポリゴンを作成します。それはすべて素晴らしいです、私は私が望む形を作ることができます。シェイプを正しくシェーディングするには、各ポリゴンの各頂点の法線を計算する必要があると思います。最初は形状が立方体だったのでとても簡単でしたが、今は(少し)より高度な形状を作成して、それらの法線を自動的に作成したいと思っています。ポリゴンの2つのエッジ(ここではすべてのポリゴンは三角形です)のベクトルを取得し、そのポリゴンのすべての頂点に外積を使用すれば、十分に簡単に思えます。その後、以下のようなコードを使用して形状を描画します。

glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 0, triangleVertices);

glEnableVertexAttribArray(GLKVertexAttribColor);
glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, 0, triangleColours);

glEnableVertexAttribArray(GLKVertexAttribNormal);
glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, 0, triangleNormals);

glDrawArrays(GL_TRIANGLES, 0, 48);

glDisableVertexAttribArray(GLKVertexAttribPosition);
glDisableVertexAttribArray(GLKVertexAttribColor);
glDisableVertexAttribArray(GLKVertexAttribNormal);

私が理解するのに苦労しているのは、なぜこれを手動で行わなければならないのかということです。表面に垂直なベクトル以外のものが必要な場合もあると思いますが、これがこれまでで最も人気のあるユースケースであると確信しているので、もっと簡単な方法はないでしょうか。明らかな何かを見逃したことがありますか?glCalculateNormals()は素晴らしいでしょう。

//これがGLKVector3[]の回答パスで、法線、頂点(3つはそれぞれポリゴンにグループ化されています)、そして頂点の数で埋めたいと考えています。

- (void) calculateSurfaceNormals: (GLKVector3 *) normals forVertices: (GLKVector3 *)incomingVertices count:(int) numOfVertices
{

    for(int i = 0; i < numOfVertices; i+=3)
    {
        GLKVector3 vector1 = GLKVector3Subtract(incomingVertices[i+1],incomingVertices[i]);
        GLKVector3 vector2 = GLKVector3Subtract(incomingVertices[i+2],incomingVertices[i]);        
        GLKVector3 normal = GLKVector3Normalize(GLKVector3CrossProduct(vector1, vector2));
        normals[i] = normal;
        normals[i+1] = normal;
        normals[i+2] = normal;
    }
}
4

1 に答える 1

3

そして、その答えは次のとおりです。OpenGLは、シーン管理ライブラリでもジオメトリライブラリでもありませんが、画面に素敵な画像を描画する描画APIにすぎません。照明には法線が必要であり、法線を与えます。それで全部です。これがユーザーだけで実行でき、実際の図面とは関係がないのに、なぜ法線を計算する必要があるのでしょうか。

多くの場合、実行時にそれらを計算するのではなく、ファイルからロードします。そして、法線を計算する方法はたくさんあります。面ごとの法線または頂点ごとの法線が必要ですか?特定のハードエッジまたは特定の滑らかなパッチが必要ですか?面法線を平均して頂点法線を取得する場合、これらをどのように平均しますか?

また、シェーダーの出現と、新しいOpenGLバージョンでの組み込みの法線属性と照明計算の削除により、この質問全体は、必要に応じて照明を行うことができ、従来の法線を必要としないため、とにかく時代遅れになります。

ちなみに、現時点では面ごとの法線を使用しているように聞こえます。つまり、面のすべての頂点が同じ法線を持っているということです。これにより、ハードエッジのある非常にファセット化されたモデルが作成され、インデックスとの併用もうまく機能しません。滑らかなモデルが必要な場合(わからない、本当にファセットの外観が必要な場合)、各頂点の隣接する面の面法線を平均して、頂点ごとの法線を計算する必要があります。これは実際には、より一般的なユースケースであり、面ごとの法線ではありません。

したがって、次のような擬似コードを実行できます。

for each vertex normal:
    intialize to zero vector

for each face:
    compute face normal using cross product
    add face normal to each vertex normal of this face

for each vertex normal:
    normalize

滑らかな頂点ごとの法線を生成します。実際のコードでも、これにより10〜20行のコードが生成されるはずですが、これはそれほど複雑ではありません。

于 2011-12-05T14:41:23.253 に答える