作成した単純なキューブを使用して、法線マッピングを実装しようとしています。このチュートリアルhttps://learnopengl.com/Advanced-Lighting/Normal-Mappingに従いましたが、チュートリアルでは 2D オブジェクトを使用しているため、3D オブジェクトを描画するときに法線マッピングをどのように行うべきかを実際には理解できません。
特に、私の立方体はほぼ正しく点灯しているように見えますが、本来あるべき動作をしていないと思われるものがあります。私は、緑のベクトルの法線と赤のベクトルの接線を出力するジオメトリ シェーダーを使用しています。ここでは、私の作品のスクリーンショットを 3 つ投稿します。
直火
側面点灯
ここでは、法線と接線を別の方法で実際に計算してみました。(かなり間違っています)
最初の画像では、キューブの法線と接線を一度に 1 つの面で計算します。これは顔に対してはうまくいくようですが、キューブを回転させると、adiacent 面の照明が間違っていると思います。2 番目の画像でわかるように、完全に欠落しているわけではありません。
3 番目の画像では、すべての法線と接線を頂点ごとに合計してみましたが、そうする必要があると思いますが、照明が少なすぎるため、結果はかなり間違っているようです。
最後に、私の質問は、法線と接線をどのように計算するかです。面ごとの計算を検討するか、すべての相対面の頂点ごとにベクトルを合計する必要がありますか?
編集 -
法線と接線を頂点シェーダーに渡し、TBN マトリックスを設定しています。しかし、最初の画像でわかるように、私の立方体を面ごとに描いていますが、直接見ている面 (十分に照らされている面) に隣接する面が正しく照らされていないようで、その理由はわかりません。「面ごと」の法線と接線を正しく計算していないと思いました。一般的にオブジェクトをカウントする法線と接線を計算することが正しい方法であると考えました。TBN マトリックスを設定するために 2 番目の画像 (緑の法線、赤の接線) に表示されているように法線と接線を計算するのが正しい場合、右の面が十分に照らされていないように見えるのはなぜですか?
編集2 -
頂点シェーダー:
void main(){
texture_coordinates = textcoord;
fragment_position = vec3(model * vec4(position,1.0));
mat3 normalMatrix = transpose(inverse(mat3(model)));
vec3 T = normalize(normalMatrix * tangent);
vec3 N = normalize(normalMatrix * normal);
T = normalize(T - dot(T, N) * N);
vec3 B = cross(N, T);
mat3 TBN = transpose(mat3(T,B,N));
view_position = TBN * viewPos; // camera position
light_position = TBN * lightPos; // light position
fragment_position = TBN * fragment_position;
gl_Position = projection * view * model * vec4(position,1.0);
}
VS で TBN マトリックスを設定し、すべてのライト、フラグメント、およびビュー ベクトルを接線空間に変換します。そうすることで、フラグメント シェーダーで他の計算を行う必要がなくなります。
フラグメント シェーダー:
void main() {
vec3 Normal = texture(TextSamplerNormals,texture_coordinates).rgb; // extract normal
Normal = normalize(Normal * 2.0 - 1.0); // correct range
material_color = texture2D(TextSampler,texture_coordinates.st); // diffuse map
vec3 I_amb = AmbientLight.color * AmbientLight.intensity;
vec3 lightDir = normalize(light_position - fragment_position);
vec3 I_dif = vec3(0,0,0);
float DiffusiveFactor = max(dot(lightDir,Normal),0.0);
vec3 I_spe = vec3(0,0,0);
float SpecularFactor = 0.0;
if (DiffusiveFactor>0.0) {
I_dif = DiffusiveLight.color * DiffusiveLight.intensity * DiffusiveFactor;
vec3 vertex_to_eye = normalize(view_position - fragment_position);
vec3 light_reflect = reflect(-lightDir,Normal);
light_reflect = normalize(light_reflect);
SpecularFactor = pow(max(dot(vertex_to_eye,light_reflect),0.0),SpecularLight.power);
if (SpecularFactor>0.0) {
I_spe = DiffusiveLight.color * SpecularLight.intensity * SpecularFactor;
}
}
color = vec4(material_color.rgb * (I_amb + I_dif + I_spe),material_color.a);
}