前提・実現したいこと
DirectX11でディレクションライトからポイントライトを実装していて、ポイントライトは実装できたが影の付き方がディレクションライトのままなので、影の付き方を直したいです。
該当のソースコード
HLSL
1// ピクセルシェーダ 2 3// グローバル 4cbuffer global : register(b0) { 5 matrix g_mtxWVP; // ワールド×ビュー×射影行列 6 matrix g_mtxWorld; // ワールド行列 7 matrix g_mtxTexture; // テクスチャ行列 8 float4 g_vCameraPos; // 視点座標(ワールド空間) 9 float4 g_vLightDir; // 光源方向(ワールド空間) 10 float4 g_vLightAmbient; // 環境光 11 float4 g_vLightDiffuse; // 拡散光 12 float4 g_vLightSpecular; // 鏡面反射光 13 14 float4 g_vLightPos; // ライト位置 15 float g_vLightRange; // ライト範囲 16 float4 g_vLightAtt; // ライト減衰 17}; 18 19// マテリアル 20cbuffer global2 : register(b1) { 21 float4 g_Ambient; // 環境色 22 float4 g_Diffuse; // 拡散色+アルファ 23 float4 g_Specular; // 鏡面反射色+強度 24 float4 g_Emissive; // 発光色 25 float4 g_Flags; // 拡散色テクスチャ有無, 発光色テクスチャ有無, 透過テクスチャ有無 26}; 27 28Texture2D g_texture : register(t0); // テクスチャ 29Texture2D g_texEmissive : register(t1); // 発光テクスチャ 30Texture2D g_texTransparent : register(t2); // 透過テクスチャ 31Texture2D g_texSpecular : register(t3); // 鏡面反射テクスチャ 32SamplerState g_sampler : register(s0); // サンプラ 33 34// パラメータ 35struct VS_OUTPUT { 36 float4 Pos : SV_Position; 37 float2 Tex : TEXCOORD0; 38 float3 Normal : TEXCOORD1; 39 float3 PosForPS : TEXCOORD2; 40 41 float4 WorldPos : POSITION; 42}; 43 44float4 main(VS_OUTPUT input) : SV_Target0 45{ 46 float3 Diff = g_Diffuse.rgb; 47 48 float Alpha = g_Diffuse.a; 49 50 // ここは関係ない処理だと思っていますが書き残しておきます。 51 if (g_Flags.x != 0.0f) { // テクスチャ有無 52 float4 TexDiff = g_texture.Sample(g_sampler, input.Tex); 53 Diff *= TexDiff.rgb; 54 Alpha *= TexDiff.a; 55 } 56 if (g_Flags.z != 0.0f) { // テクスチャ有無 57 float4 TexTran = g_texTransparent.Sample(g_sampler, input.Tex); 58 Alpha *= (TexTran.r * TexTran.g * TexTran.b * TexTran.a); 59 } 60 if (Alpha <= 0.0f) discard; // 完全透明なら描画しない 61 float3 Spec = g_Specular.rgb; 62 if (g_Flags.w != 0.0f) { // テクスチャ有無 63 float4 TexSpec = g_texSpecular.Sample(g_sampler, input.Tex); 64 Spec *= TexSpec.rgb; 65 } 66 67 // ここから 68 float3 lightToPixelVec = g_vLightPos - input.WorldPos; 69 // 光源位置と画素位置の距離を求める 70 float d = length(lightToPixelVec); 71 72 // ここがディレクションライトの処理のまま 73 if (g_vLightDir.x != 0.0f || g_vLightDir.y != 0.0f || g_vLightDir.z != 0.0f) { 74 // ポイントライトは光源ベクトルがいらないが変数Lを消すとハーフベクトルの計算に何を置き換えればいいのかわからない 75 float3 L = normalize(-g_vLightDir.xyz); // 光源へのベクトル 76 // 法線ベクトルはこのままでいいと思います。 77 float3 N = normalize(input.Normal); // 法線ベクトル 78 // 視点ベクトルの計算も変える必要があるがわからない 79 float3 V = normalize(g_vCameraPos.xyz - input.PosForPS);// 視点へのベクトル 80 // 変数Lを置き換えなければいけないが何に置き換えればいいのかわからない 81 float3 H = normalize(L + V); // ハーフベクトル 82 Diff = g_vLightAmbient.rgb * g_Ambient.rgb + 83 g_vLightDiffuse.rgb * Diff * saturate(dot(L, N)); // 拡散色 + 環境色 84 Spec = Spec * g_vLightSpecular.rgb * 85 pow(saturate(dot(N, H)), g_Specular.a); // 鏡面反射色 86 Diff += Spec; 87 } 88 89 // ここは関係ない処理だと思っていますが書き残しておきます。 90 float3 Emis = g_Emissive.rgb; 91 if (g_Flags.y != 0.0f) { // テクスチャ有無 92 float4 TexEmis = g_texEmissive.Sample(g_sampler, input.Tex); 93 Emis *= (TexEmis.rgb * TexEmis.a); 94 } 95 Diff += Emis; 96 97 // ここから 98 // ここからはポイントライトの処理ですが、ここはうまくいっていると思います。 99 float3 finalAmbient = Diff * g_Ambient; 100 if (d > g_vLightRange) 101 return float4(finalAmbient, Alpha); 102 lightToPixelVec /= d; 103 float howMuchLight = dot(lightToPixelVec, input.Normal); 104 float3 finalColor = Diff; 105 if (howMuchLight > 0.0f) 106 { 107 // ピクセルのfinalColorに光を追加する 108 finalColor += howMuchLight * Diff * g_vLightDiffuse; 109 // 光のフォールオフ係数を計算する 110 finalColor /= g_vLightAtt[0] + (g_vLightAtt[1] * d) + (g_vLightAtt[2] * (d * d)); 111 } 112 113 finalColor = saturate(finalColor + finalAmbient); 114 115 //return float4(Diff, Alpha); 116 return float4(finalColor, Alpha); 117}
試したこと
// ポイントライトの記事
https://www.braynzarsoft.net/viewtutorial/q16390-17-point-lights
// ライトの種類の記事
https://www.braynzarsoft.net/viewtutorial/q16390-simple-lighting
補足情報(FW/ツールのバージョンなど)
DirectX11
Visual Studio 2019 Community
Windows10
あなたの回答
tips
プレビュー