三角形で構成された最新のOpenGL(つまりシェーダー)のコーンに少し苦労していましたが、驚くほど簡単な解決策を見つけました!私はそれが現在受け入れられている答えで提案されているものよりもはるかに良くて単純だと思います。
円錐の表面を形成する三角形の配列(明らかにそれぞれに3つの頂点があります)があります。これは本当に簡単なので、底面(円形のベース)は気にしませんでした。すべての作業で、次の単純な頂点構造を使用します。
position: vec3
(最後の要素として1.0fを追加することにより、シェーダーでvec4に自動的に変換されました)
normal_vector: vec3
(光の方向の内積の計算に使用されたため、シェーダーではvec3として保持されていました)
color: vec3
(透明度は使用しませんでした)
私の頂点シェーダーでは、頂点の位置を変換するだけで(投影とモデルビュー行列を乗算)、法線ベクトルも変換していました(モデルビュー行列の変換された逆行列を乗算します)。次に、変換された位置、法線ベクトル、および変換されていない色がフラグメントシェーダーに渡され、光の方向と法線ベクトルの内積が計算され、この数値に色が乗算されました。
私がしたことから始めましょう、そして不十分であるとわかりました:
試行#1:各円錐面(三角形)は一定の法線ベクトルを使用していました。つまり、1つの三角形のすべての頂点が同じ法線ベクトルを持っていました。これは単純ですが、スムーズな照明は実現しませんでした。三角形のすべてのフラグメントが同じ法線ベクトルを持っていたため、各面の色は一定でした。間違い。
試行#2:各頂点の法線ベクトルを個別に計算しました。これは、円錐の円形の底面の頂点では簡単でしたが、円錐の先端には何を使用する必要がありますか?三角形全体の法線ベクトルを使用しました(つまり、attempt#と同じ値)。円錐の基部に近い部分では滑らかな照明がありましたが、先端の近くでは滑らかではなかったので、これはより良い方法でした。間違い。
しかし、それから私は解決策を見つけました:
試行#3 :ゼロベクトルvec3(0.0f、0.0f、0.0f)に等しい円錐先端の頂点に法線ベクトルを割り当てたことを除いて、試行#2と同じようにすべてを実行しました。これがトリックの鍵です!次に、このゼロ法線ベクトルがフラグメントシェーダーに渡されます(つまり、頂点シェーダーとフラグメントシェーダーの間で、他の2つの頂点の法線ベクトルで自動的に補間されます)。もちろん、フラグメント(!)シェーダーのベクトルは一定のサイズ(ドット積に必要)ではないため、正規化する必要があります。だから私はそれを正規化します-もちろん、これは法線ベクトルのサイズがゼロである円錐の先端では不可能です。しかし、それは他のすべての点で機能します。以上です。
覚えておくべき重要なことが1つあります。それは、フラグメントシェーダーで法線ベクトルのみを正規化できることです。確かに、C ++でゼロサイズのベクトルを正規化しようとすると、エラーが発生します。したがって、何らかの理由でフラグメントシェーダーに入る前に正規化が必要な場合は、サイズがゼロの法線ベクトルを除外するようにしてください(つまり、円錐の先端を除外しないと、エラーが発生します)。
これにより、円錐の先端のポイントを除くすべてのポイントで円錐の滑らかなシェーディングが生成されます。しかし、その点は重要ではありません(1ピクセルを気にする人は...)、または特別な方法で処理できます。もう1つの利点は、非常に単純なシェーダーでも使用できることです。唯一の変更は、頂点シェーダーではなく、フラグメントシェーダーで、またはそれ以前でさえ、法線ベクトルを正規化することです。