#define IS_FX_FILE #include "../../../Ext/xelib/Include/xelib/System/Draw/modeDef.h" #define MAX_CASCADE (3) #define SHADOW_MAP_SIZE (1024) float g_LP_minUV = (1.0f / SHADOW_MAP_SIZE); float g_LP_maxUV = (1.0f - ( 1.0f / SHADOW_MAP_SIZE )); float MAX_CASCADE_F = 3.0f; float x_pitch = (1.0f/SHADOW_MAP_SIZE)/3.0f; float y_pitch = (1.0f/SHADOW_MAP_SIZE); cbuffer cb1 { float4x4 g_LP_VewMtx; // ワールド→ビュー float4 g_LP_PosCam; // カメラ位置 }; cbuffer cb2 { float4x4 g_LP_VP; // ビュープロジェクション変換 float4x4 g_LP_LightModelMtx; // ライトモデルの行列 }; // スポットライト用シャドーマップ cbuffer cb3 { float4x4 g_LP_Shadow_wvp; // シャドーマップの射影行列 float g_LP_ShadowMapOffset; }; // グローバルライト用カスケードシャドウマップ cbuffer cb4 { float4x4 g_LP_CascadeShadow_wv; // カスケードシャドウのビュー変換行列 float4 g_LP_vCascadeScale[MAX_CASCADE]; float4 g_LP_vCascadeOffset[MAX_CASCADE]; float g_LP_CascadeShadowMapOffset[MAX_CASCADE]; float g_LP_shadow_gain; float4 g_LP_shadow_color; float g_LP_shadow_lambert_flag; //反対面の影の減衰を行うかどうか }; float g_LP_caustic_rate; float g_LP_caustic_size = 0.01000f; float g_LP_caustic_blend = 1.0f; /* // ※※※※※※※※※※※※※※※※※ // ディレクショナルライト // ※※※ 16バイトアライメント ※※※ struct StDirectionalLight { float4 g_LP_light_diffuse; // ディヒューズカラー float4 g_LP_light_specular; // スペキュラカラー float4 g_LP_light_ambient; // アンビエントカラー float4 g_LP_light_direction; // 方向 float4 g_LP_light_ground; // 地面色 float4 g_LP_RimLightDirection; float g_LP_rim_power; float g_LP_rim_range; float g_LP_rim_bright; float g_LP_light_constant_attenuation; // 一定減衰率 bool g_LP_hemisphere; // ヘミスフィア bool g_LP_halfLambert; // ハーフランバート bool g_LP_Dummy00; bool g_LP_Dummy01; }; cbuffer cb_LP_DirectionalLightBuff { StDirectionalLight g_DirLight[ 2 ]; }; */ // ライト(nsEffect::stLightParam) #define DIRECTIONAL_NUM (8) cbuffer cbDirLightParam { ///< メインディレクショナル float4 g_LP_light_diffuse[ DIRECTIONAL_NUM ]; // ディヒューズカラー float4 g_LP_light_specular[ DIRECTIONAL_NUM ]; // スペキュラカラー float4 g_LP_light_ambient[ DIRECTIONAL_NUM ]; // アンビエントカラー float4 g_LP_light_direction[ DIRECTIONAL_NUM ]; // 方向 float4 g_LP_light_ground[ DIRECTIONAL_NUM ]; // 地面色 float g_LP_light_constant_attenuation[ DIRECTIONAL_NUM ]; // 一定減衰率 bool g_LP_hemisphere[ DIRECTIONAL_NUM ]; // ヘミスフィア bool g_LP_halfLambert[ DIRECTIONAL_NUM ]; // ハーフランバート float4 g_LP_RimLightDirection[ DIRECTIONAL_NUM ]; float g_LP_rim_power[ DIRECTIONAL_NUM ]; float g_LP_rim_range[ DIRECTIONAL_NUM ]; float g_LP_rim_bright[ DIRECTIONAL_NUM ]; }; cbuffer cbSpotLightParam { float4 g_LP_light_position; // 座標 float g_LP_light_linear_attenuation; // 一次減衰率 float g_LP_light_quadratic_attenuation; // 二次減衰率 float g_LP_light_range; // 範囲 float g_LP_light_theta; // スポットライトの内部コーンの角度 float g_LP_light_phi; // スポットライトの外部コーンの角度 float g_LP_light_falloff; // スポットライトの内部コーンから外部コーンの減衰 float g_LP_light_dist_rate; }; cbuffer cbSpotLightParam2 { float4 g_LP_light_right; }; Texture2D g_LP_texDiff; // ディフューズ Texture2D g_LP_texAmb; // アンビエント Texture2D g_LP_texNorm; // 法線 Texture2D g_LP_texPos; // 位置 Texture2D g_LP_texDepth; // 深度 Texture2D g_LP_texRef; // 反射強度 Texture2D g_LP_texSpe; // スペキュラマップ //TextureCube texEnvCubeMap; // キューブマップ //texture2D g_texture_proj_shadow; Texture2D g_texLightSphere; Texture2D g_texDepthBuffer; Texture2D g_LP_texParabEnvMap; Texture2D g_LP_texCaustic; Texture2D g_LP_texFireWorks_00; Texture2D g_LP_texFireWorks_01; Texture2D g_LP_texFireWorks_02; float g_LP_brightFireWorks_00; float g_LP_brightFireWorks_01; float g_LP_brightFireWorks_02; float g_LP_brightFireWorksOffsetX; float4 g_LP_lookDir; SamplerState PointSampler { Filter = MIN_MAG_MIP_POINT; AddressU = Clamp; AddressV = Clamp; }; SamplerState PointWrapSampler { Filter = MIN_MAG_MIP_POINT; AddressU = Wrap; AddressV = Wrap; }; SamplerState PointClampSampler { Filter = MIN_MAG_MIP_POINT; AddressU = Border; AddressV = Border; BorderColor = float4( 0.0f, 0.0f, 0.0f, 0.0f ); }; SamplerState LinearSampler { Filter = MIN_MAG_MIP_LINEAR; AddressU = Clamp; AddressV = Clamp; }; SamplerState CubeSampler { Filter = MIN_MAG_MIP_LINEAR; AddressU = Clamp; AddressV = Clamp; }; SamplerState samShadow { //Filter = MIN_MAG_MIP_LINEAR; Filter = ANISOTROPIC; AddressU = Border; AddressV = Border; BorderColor = float4(1,1,1,1); }; SamplerComparisonState samShadowCmp { //Filter = COMPARISON_MIN_MAG_LINEAR_MIP_POINT; //Filter = COMPARISON_ANISOTROPIC; Filter = COMPARISON_MIN_MAG_MIP_LINEAR; //AddressU = Clamp; //AddressV = Clamp; //AddressW = Clamp; AddressU = Border; AddressV = Border; AddressW = Border; BorderColor = float4(1,1,1,1); ComparisonFunc= LESS; }; DepthStencilState DisableDepth { DepthEnable = FALSE; DepthWriteMask = ZERO; }; DepthStencilState StencilEqOne { DEPTHENABLE = FALSE; DEPTHWRITEMASK = ZERO; STENCILENABLE = TRUE; STENCILREADMASK = 0x0F; STENCILWRITEMASK = 0x00; FRONTFACESTENCILFAIL = KEEP; FRONTFACESTENCILDEPTHFAIL = KEEP; FRONTFACESTENCILPASS = KEEP; FRONTFACESTENCILFUNC = LESS_EQUAL;//GREATER_EQUAL; BACKFACESTENCILFAIL =KEEP; BACKFACESTENCILDEPTHFAIL = KEEP; BACKFACESTENCILPASS =KEEP; BACKFACESTENCILFUNC = LESS_EQUAL;//GREATER_EQUAL; }; BlendState AddBlend { BlendEnable[0] = TRUE; BlendEnable[1] = TRUE; SrcBlend = ONE; DestBlend = ONE; BlendOp = ADD; }; // 両面描画 RasterizerState CullNone { CULLMODE = NONE; }; // 裏面描画 RasterizerState CullFront { CULLMODE = FRONT; }; // 関数 // パラボラ環境マップアクセス // 反射ベクトルを入力 float4 texDP( float3 vec) { vec = normalize(vec); bool front = (vec.z >= 0); if ( !front ) vec.xz = -vec.xz; float2 uv; uv = vec.xy / (1+vec.z); uv.y = -uv.y; uv = uv * 0.5 + 0.5; uv.x *= 0.5f; // テクスチャは横2倍 if ( !front ) { // 後方テクスチャは2枚目(右半分) uv.x += 0.5; } return g_LP_texParabEnvMap.Sample( LinearSampler, uv ); } static const float4 vCascadeColorsMultiplier[8] = { float4 ( 1.5f, 0.0f, 0.0f, 1.0f ), float4 ( 0.0f, 1.5f, 0.0f, 1.0f ), float4 ( 0.0f, 0.0f, 5.5f, 1.0f ), float4 ( 1.5f, 0.0f, 5.5f, 1.0f ), float4 ( 1.5f, 1.5f, 0.0f, 1.0f ), float4 ( 1.0f, 1.0f, 1.0f, 1.0f ), float4 ( 0.0f, 1.0f, 5.5f, 1.0f ), float4 ( 0.5f, 3.5f, 0.75f, 1.0f ) }; //=================================================================================================== // 共通 //=================================================================================================== struct VS_Input { float4 Pos : POSITION; float2 Tex : TEXCOORD0; }; struct VS_Output { float4 Pos : SV_POSITION; // Transformed position float2 Tex : TEXCOORD0; }; VS_Output QuadVS( VS_Input Input ) { VS_Output Output; Output.Pos = Input.Pos; Output.Tex = Input.Tex; return Output; } // シェーダー挙動制御 int g_LP_light_path_mode; bool g_LP_shadowEnable; ///------------------------------------------------------------------------------------------------------------------------------------------- /// ライティング /// スペキュラとディフューズを足して、浮動小数点バッファに書き出すバージョン float4 DR_DIRLIGHT_PS( VS_Output Input, uniform int mode, uniform bool useShadow, uniform bool useCubeMap) : SV_TARGET { float4 pos = g_LP_texPos.Sample( PointSampler, Input.Tex ); if(pos.a == 0) discard;///< Gパスで描かれたところ以外は描画しない float4 output = 0; // ライト float4 ambient_result; // = float4(0,0,0,0); float4 diffuse_result; // = float4(0,0,0,0); float4 specular_result; // = float4(0,0,0,0); // テクスチャからマテリアル情報を取り出す float4 MatDiff = g_LP_texDiff.Sample( PointSampler, Input.Tex ); float4 MatAmb = g_LP_texAmb.Sample( PointSampler, Input.Tex ); float4 MatSpec = g_LP_texSpe.Sample( PointSampler, Input.Tex ); float4 MatRef = g_LP_texRef.Sample( PointSampler, Input.Tex ); float Reflect = MatRef.r; float MatShine= MatAmb.a * 0xFF; float4 norm = g_LP_texNorm.Sample( PointSampler, Input.Tex ); //float4 emissive = texEmissive.Sample( PointSampler, Input.Tex ) * g_EmissiveGain; int lightNo = MatDiff.a * 0xFF; ///< ライト番号取り出し int lightNo_Sub = lightNo + 1; // UNORM→SNORM変換 norm = (norm*2)-1; ///< コースティック計算 float2 caustic_uv = float2( pos.x, pos.z ) * g_LP_caustic_size; float4 caustic = g_LP_texCaustic.Sample( PointWrapSampler, caustic_uv ); float3 norm_up = float3( 0.0f, 1.0f, 0.0f ); float rate = max( 0.0f, dot( norm.xyz, norm_up.xyz ) ); caustic *= rate; caustic *= g_LP_caustic_rate; caustic *= g_LP_caustic_blend; ///< 花火の照返し計算 float2 fireworks_00_uv = float2( pos.x, pos.z )*0.0002f; fireworks_00_uv.x += g_LP_brightFireWorksOffsetX; fireworks_00_uv.y += 0.5f;///< 太鼓だと右にズレてくる float4 fireworks_00 = g_LP_texFireWorks_00.Sample( PointClampSampler, fireworks_00_uv ); fireworks_00 *= g_LP_brightFireWorks_00; fireworks_00 *= ( 1.0f - max( 0.0f, dot( norm.xyz, g_LP_lookDir.xyz ) ) ); float3 normal_down = float3( 0.0f, -1.0f, 0.0f ); fireworks_00 *= ( 1.0f - max( 0.0f, dot( norm.xyz, normal_down.xyz ) ) );///< 下方向も消す //////////////////////////// // アンビエント メイン if(!g_LP_hemisphere[ lightNo ]){ ambient_result = g_LP_light_ambient[ lightNo ] * MatAmb; }else{ // 半球ライティングは、空色と地面色を補完 float rate = (dot(norm.xyz, float3(0,1,0))+1) * 0.5f; ambient_result = MatAmb * lerp( g_LP_light_ground[ lightNo ], g_LP_light_ambient[ lightNo ], rate ); } //////////////////////////// // アンビエント サブ if(!g_LP_hemisphere[ lightNo_Sub ]){ ambient_result += g_LP_light_ambient[ lightNo_Sub ] * MatAmb; }else{ // 半球ライティングは、空色と地面色を補完 float rate = (dot(norm.xyz, float3(0,1,0))+1) * 0.5f; ambient_result += MatAmb * lerp( g_LP_light_ground[ lightNo_Sub ], g_LP_light_ambient[ lightNo_Sub ], rate ); } //////////////////////////// // ディフューズ メイン float3 light_dir = -normalize( g_LP_light_direction[ lightNo ].xyz ); // ライト計算、反射計算はグローバル座標系で行う // 入ってくるのが光の方向なので、光源に向かう方向に反転 // ランバート float lightDot = dot( light_dir, norm.xyz ); float lambert = max( 0, lightDot ); // ハーフランバート if ( g_LP_halfLambert[ lightNo ] ) { lambert = lambert * 0.5f + 0.5f; lambert = lambert * lambert; } // ディフューズカラーはランバートモデル diffuse_result = MatDiff * g_LP_light_diffuse[ lightNo ] * lambert; // / g_LP_light_constant_attenuation[ lightNo ]; //////////////////////////// // ディフューズ サブ { float3 light_dir = -normalize( g_LP_light_direction[ lightNo_Sub ].xyz ); // ライト計算、反射計算はグローバル座標系で行う // 入ってくるのが光の方向なので、光源に向かう方向に反転 // ランバート float lightDot = dot( light_dir, norm.xyz ); float lambert = max( 0, lightDot ); // ハーフランバート if ( g_LP_halfLambert[ lightNo_Sub ] ) { lambert = lambert * 0.5f + 0.5f; lambert = lambert * lambert; } // ディフューズカラーはランバートモデル diffuse_result += MatDiff * g_LP_light_diffuse[ lightNo_Sub ] * lambert;// / g_LP_light_constant_attenuation[ lightNo_Sub ]; } //////////////////////////// // スペキュラ // 視線、取り敢えず位置をそのまま使ってみる // →精度低い、要検証 float3 eye = normalize(pos.xyz - g_LP_PosCam.xyz); float3 ref = normalize( reflect( light_dir, norm.xyz ) ); float phong = saturate( dot( ref, eye ) ); float spe = g_LP_light_specular[ lightNo ] * max( pow( phong, MatShine ), 0.0 ); // スペキュラライトはフォンモデル specular_result = spe * MatSpec; // / g_LP_light_constant_attenuation[ lightNo ]; //////////////////////////// // 環境マップの反射もここで行う。グローバルライトみたいなもんだ。 float3 eyeRef = reflect( eye, norm.xyz ); float4 envMap; // 放物マップ使用時は、反射ベクトルはビュー空間に変換 eyeRef = normalize(mul( float4(eyeRef, 0), g_LP_VewMtx).xyz); envMap = texDP(eyeRef); float3 Rim = float3( 0.0f, 0.0f, 0.0f ); if( MatRef.b != 0.0f ) { ///< リムライト //float3 pixVec = g_LP_RimLightDirection[ lightNo ].xyz; float val = dot( norm, -eye ); if ( val < 0.0f ) val = 0.0f; float rt = 1.0f - val; if( rt > g_LP_rim_range[ lightNo ] ) { rt = (rt-g_LP_rim_range[ lightNo ]);///< 比率変換 Rim = g_LP_rim_power[ lightNo ] *pow( rt, g_LP_rim_bright[ lightNo ] ); } if ( MatRef.b < 0.6f )///< 闇リム { Rim *= -1.0f; } } //////////////////////////// // 深度バッファシャドー float shdepth = 0.0f; int iCurrentCascadeIndex = 0; if( MatRef.a != 1 ) { if(useShadow) { float4 shadowMapUV = 0.0f; bool cascadeFound = false; float4 shadowViewPos = mul( pos, g_LP_CascadeShadow_wv); for(int i=0; i g_LP_minUV && max(shadowMapUV.x, shadowMapUV.y) < g_LP_maxUV ){ cascadeFound = true; iCurrentCascadeIndex = i; } } // 横並びシャドーマップ if(cascadeFound){ shadowMapUV.x /= MAX_CASCADE; shadowMapUV.x += (iCurrentCascadeIndex / MAX_CASCADE_F); shadowMapUV.z -= g_LP_CascadeShadowMapOffset[iCurrentCascadeIndex]; for( int yy=-1; yy<=1; yy++ ) { for( int xx=-1; xx<=1; xx++ ) { float2 ofs = float2( x_pitch*xx, y_pitch*yy ); shdepth += 1.0f - g_texDepthBuffer.SampleCmpLevelZero( samShadowCmp, shadowMapUV.xy+ofs, shadowMapUV.z ); } } //shdepth *= 0.04f; shdepth *= 0.111f; // 影にランバートを掛けることによって、光源の逆側をそれ異常暗くしない if(g_LP_shadow_lambert_flag <= 0.0){ lambert = 1.0; } shdepth *= lambert * g_LP_shadow_gain; } //output = ((diffuse_result + specular_result) + ambient_result + envMap*Reflect) * vCascadeColorsMultiplier[iCurrentCascadeIndex];// - shadow; //output.a = 1.0f; //return output; { //float4 sh_uv = mul( pos, g_LP_Shadow_wvp); //// ディレクショナルライトなのでwで割る必要なし //sh_uv.xyz /= sh_uv.w; //sh_uv.x= sh_uv.x * 0.5f + 0.5f; //sh_uv.y= -sh_uv.y * 0.5f + 0.5f; //sh_uv.z -= g_LP_ShadowMapOffset; //shdepth= g_texDepthBuffer.SampleCmpLevelZero( samShadowCmp, sh_uv.xy, sh_uv.z ); } } } //envMap = float4(1,0,1,1); // 投影シャドウ反映 //float4 shadow_uv = mul( pos, g_matrix_shadow_wvp); //shadow_uv.x = 0.5*shadow_uv.x / shadow_uv.w + 0.5f; //shadow_uv.y = -0.5*shadow_uv.y / shadow_uv.w + 0.5f; //float4 shadow_color = float4(saturate(shadow_uv).xy,0,1); //float shadow = 1 - (g_texture_proj_shadow.Sample( samShadow, shadow_uv.xy).r); // 出力 switch(mode){ case DR_MODE_LIGHT_AMBIENT: output = ambient_result; break; case DR_MODE_LIGHT_DIFF: output = diffuse_result; break; case DR_MODE_LIGHT_SPECULAR: output = specular_result; break; case DR_MODE_ENVIRONMENT: output = envMap; break; case DR_MODE_EMISSIVE_RESULT: // エミッションはGパスでライトバッファに出力済み //output = shadow_color; // discard; break; case DR_MODE_SHADOW: output = (diffuse_result + specular_result) * shdepth + ambient_result + envMap*Reflect;// - shadow; output *= vCascadeColorsMultiplier[iCurrentCascadeIndex]; break; default: //output = (diffuse_result + specular_result) * (1.0f - shdepth) + ambient_result + envMap * Reflect; output.r = (diffuse_result.r + specular_result.r) * (1.0f - shdepth * ( 1.0f - g_LP_shadow_color.r ) ) + ambient_result.r + envMap.r * Reflect; output.g = (diffuse_result.g + specular_result.g) * (1.0f - shdepth * ( 1.0f - g_LP_shadow_color.g ) ) + ambient_result.g + envMap.g * Reflect; output.b = (diffuse_result.b + specular_result.b) * (1.0f - shdepth * ( 1.0f - g_LP_shadow_color.b ) ) + ambient_result.b + envMap.b * Reflect; //output = (diffuse_result + specular_result) * (1.0f - shdepth) + ambient_result + Reflect;// - shadow; break; } output += (caustic*0.5f); output += fireworks_00; output.rgb += Rim.rgb; output.rgb = max( output.rgb, 0.0f ); output.a = 1.0f; return output; } PixelShader ps[] = { CompileShader( ps_4_0, DR_DIRLIGHT_PS(0, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(1, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(2, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(3, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(4, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(5, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(6, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(7, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(8, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(9, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(10, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(11, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(12, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(13, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(14, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(15, false, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(0, true, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(1, true, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(2, true, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(3, true, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(4, true, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(5, true, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(6, true, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(7, true, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(8, true, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(9, true, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(10, true, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(11, true, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(12, true, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(13, true, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(14, true, false) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(15, true, false) ), }; PixelShader ps2[] = { CompileShader( ps_4_0, DR_DIRLIGHT_PS(0, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(1, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(2, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(3, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(4, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(5, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(6, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(7, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(8, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(9, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(10, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(11, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(12, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(13, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(14, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(15, false, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(0, true, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(1, true, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(2, true, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(3, true, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(4, true, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(5, true, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(6, true, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(7, true, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(8, true, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(9, true, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(10, true, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(11, true, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(12, true, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(13, true, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(14, true, true) ), CompileShader( ps_4_0, DR_DIRLIGHT_PS(15, true, true) ), }; // int ps_index = DR_MODE_NUM * (g_LP_hemisphere[ lightNo ] ? 1 : 0) + g_LP_light_path_mode // マップかどうかを判別するマスク DepthStencilState DisableDepthAndStencilMapEqual { DepthEnable = FALSE; DepthWriteMask = ZERO; STENCILENABLE = TRUE; STENCILREADMASK = OBJ_STENCIL_ID_MASK; // マップと道をマスク FRONTFACESTENCILFUNC = EQUAL; BACKFACESTENCILFUNC = EQUAL; }; // マップかどうかを判別するマスク DepthStencilState DisableDepthAndStencilMapNotEqual { DepthEnable = FALSE; DepthWriteMask = ZERO; STENCILENABLE = TRUE; STENCILREADMASK = OBJ_STENCIL_ID_MASK; // マップと道をマスク FRONTFACESTENCILFUNC = NOT_EQUAL; BACKFACESTENCILFUNC = NOT_EQUAL; }; technique10 DirectionalLightMultiMap { // マップ以外は放物面マップで描く pass p0 { SetVertexShader( CompileShader( vs_4_0, QuadVS() ) ); SetGeometryShader( NULL ); SetPixelShader( ps[DR_MODE_NUM * (g_LP_shadowEnable ? 1 : 0) + g_LP_light_path_mode] ); SetDepthStencilState( DisableDepthAndStencilMapNotEqual, OBJ_STENCIL_ID_MAP ); SetBlendState( AddBlend, float4(0,0,0,0), 0xFFFFFFFF ); } // マップ(道路以外)はキューブマップで描く pass p1 { SetVertexShader( CompileShader( vs_4_0, QuadVS() ) ); SetGeometryShader( NULL ); SetPixelShader( ps2[DR_MODE_NUM * (g_LP_shadowEnable ? 1 : 0) + g_LP_light_path_mode] ); SetDepthStencilState( DisableDepthAndStencilMapEqual, OBJ_STENCIL_ID_MAP ); SetBlendState( AddBlend, float4(0,0,0,0), 0xFFFFFFFF ); } } technique10 DirectionalLightCubeMap { // 常にキューブマップで描く pass p1 { SetVertexShader( CompileShader( vs_4_0, QuadVS() ) ); SetGeometryShader( NULL ); SetPixelShader( ps2[DR_MODE_NUM * (g_LP_shadowEnable ? 1 : 0) + g_LP_light_path_mode] ); SetDepthStencilState( DisableDepth, 0 ); SetBlendState( AddBlend, float4(0,0,0,0), 0xFFFFFFFF ); } } VS_Output LightModelVS( VS_Input Input ) { VS_Output Output; Input.Pos.w = 1.0f; Output.Pos = mul(mul(Input.Pos,g_LP_LightModelMtx), g_LP_VP) ; return Output; } ///------------------------------------------------------------------------------------------------------------------------------------------- /// ライティング(スポットライト) /// スペキュラとディフューズを足して、浮動小数点バッファに書き出すバージョン float4 DR_SPOTLIGHT_PS( VS_Output Input, uniform int mode,uniform bool useTex, uniform bool useShadow ) : SV_TARGET { int lightNo = 0; //return float4(0,0.25,0.25,1); // テクスチャサンプリング位置をInput.Posで決める。 // 入力バッファが全て出力バッファと同じサイズであること前提 int3 texelPos = int3(Input.Pos.xy, 0); float4 pos = g_LP_texPos.Load( texelPos ); if(pos.a == 0) discard; pos.a = 1.0f; // 光源→対象 float3 light_vec = pos.xyz - g_LP_light_position.xyz; // 光源からの距離 float distance = length(light_vec); if( g_LP_light_range < distance) discard; light_vec = normalize(light_vec); // スポットライト中心からの角度 float3 light_dir = normalize(g_LP_light_direction[ lightNo ].xyz); // ライト計算、反射計算はグローバル座標系で行う float dir_rate = saturate(( dot(light_dir, light_vec) - g_LP_light_phi ) / ( g_LP_light_theta - g_LP_light_phi )); if(dir_rate <= 0) discard; // ライト float4 ambient_result; float4 diffuse_result; float4 specular_result; // テクスチャからマテリアル情報を取り出す float4 MatDiff = g_LP_texDiff.Load( texelPos ); float4 MatAmb = g_LP_texAmb.Load( texelPos ); float4 MatSpec = g_LP_texSpe.Load( texelPos ); float4 MatRef = g_LP_texRef.Load( texelPos ); float Reflect = MatRef.r; float MatShine= MatAmb.a * 0xFF; float4 norm = g_LP_texNorm.Load( texelPos ); //float4 emissive = texEmissive.Sample( PointSampler, Input.Tex ) * g_EmissiveGain; // UNORM→SNORM変換 norm = (norm*2)-1; // ここに来ている時点で、スポットライト内部 // 以下方向ライトと同じ //////////////////////////// // アンビエント // アンビエントカラーはそのまま足す ambient_result = g_LP_light_ambient[ lightNo ] * MatAmb; //////////////////////////// // ディフューズ light_dir *= -1; // 光源に向かう方向に反転 // ランバート float lambert = max( 0, dot( -light_vec, norm.xyz ) ); // ハーフランバート //float lambert = dot( light_dir, norm.xyz ) * 0.5f + 0.5f; //lambert = lambert * lambert; // ディフューズカラーはランバートモデル // 減衰率 //float att_rate = ( // g_LP_light_constant_attenuation[ lightNo ] + // g_LP_light_linear_attenuation * dist_rate + // g_LP_light_quadratic_attenuation * dist_rate * dist_rate ); //float att_rate = ( // g_LP_light_constant_attenuation[ lightNo ] + // g_LP_light_linear_attenuation * distance + // g_LP_light_quadratic_attenuation * distance * distance ); float att_rate = g_LP_light_constant_attenuation[ lightNo ] / pow(1.0 - pow( distance * g_LP_light_dist_rate, g_LP_light_linear_attenuation), g_LP_light_quadratic_attenuation); //{ // return float4(dir_rate/att_rate,0,0,1); //} // テクスチャライト float4 light_tex = (1,1,1,1); if(useTex) { float3 light_up = cross(g_LP_light_right.xyz, light_dir); float right = dot(light_vec, g_LP_light_right.xyz); float up = dot(light_vec, light_up); float front = dot(light_vec, light_dir); float a = front / g_LP_light_phi; float radius = sqrt(pow(a,2) - pow(front,2)); float2 uv; uv.x = (right/radius/2 + 0.5); uv.y = (up/radius/2 + 0.5); //{ // return float4(u,v,0,1); //} light_tex = g_texLightSphere.Sample( LinearSampler, uv ); } // 深度バッファシャドー float shdepth = 1.0f; if( MatRef.a != 1 ) { if(useShadow) { float4 sh_uv = mul( pos, g_LP_Shadow_wvp); sh_uv.xyz /= sh_uv.w; sh_uv.x= sh_uv.x * 0.5f + 0.5f; sh_uv.y= -sh_uv.y * 0.5f + 0.5f; // sh_uv.z-= 0.00004f; // 適当 sh_uv.z -= g_LP_ShadowMapOffset; shdepth= g_texDepthBuffer.SampleCmpLevelZero( samShadowCmp, sh_uv.xy, sh_uv.z ); //return float4( shdepth, 0, 0, 1); } } diffuse_result = g_LP_light_diffuse[ lightNo ] * lambert; //diffuse_result = saturate(diffuse_result) * MatDiff; diffuse_result = diffuse_result * MatDiff ; //////////////////////////// // スペキュラ float3 eye = normalize(pos.xyz - g_LP_PosCam.xyz); float3 ref = normalize( reflect( -light_vec, norm.xyz ) ); float phong = saturate( dot( ref, eye ) ); float4 spe = g_LP_light_specular[ lightNo ] * max( pow( abs(phong), MatShine ), 0.0 ); // スペキュラライトはフォンモデル specular_result = spe * MatSpec; float4 output = 0; // 出力 //switch(mode){ // case DR_MODE_LIGHT_AMBIENT: // output = diffuse_result; // break; // case DR_MODE_LIGHT_DIFF: // output = ambient_result; // break; // case DR_MODE_LIGHT_SPECULAR: // output = specular_result; // break; // case DR_MODE_ENVIRONMENT: // output = envMap; // break; // case DR_MODE_EMISSIVE_RESULT: // // エミッションはGパスでライトバッファに出力済み // discard; // break; // default: // output = diffuse_result + ambient_result + specular_result + envMap*Reflect; // break; //} // アンビエントには影が影響しないようにする output = ((diffuse_result + specular_result)* shdepth + ambient_result) * dir_rate / att_rate * light_tex; output.a = 1.0f; return output; } PixelShader SpotLightPS[] = { CompileShader( ps_4_0, DR_SPOTLIGHT_PS(0, false, false) ), CompileShader( ps_4_0, DR_SPOTLIGHT_PS(0, false, true) ), CompileShader( ps_4_0, DR_SPOTLIGHT_PS(0, true, false) ), CompileShader( ps_4_0, DR_SPOTLIGHT_PS(0, true, true) ), }; int g_LP_light_mode; // フルスクリーンクアッドでスポットライト処理 technique10 SpotLightFullScreen { pass p0 { SetVertexShader( CompileShader( vs_4_0, QuadVS() ) ); SetGeometryShader( NULL ); SetPixelShader( SpotLightPS[g_LP_light_mode] ); SetDepthStencilState( DisableDepth, 1 ); SetBlendState( AddBlend, float4(0,0,0,0), 0xFFFFFFFF ); } } // ステンシルバッファが1の場所のみスポットライト処理 technique10 SpotLightFullScreenMask { pass p0 { SetVertexShader( CompileShader( vs_4_0, QuadVS() ) ); SetGeometryShader( NULL ); SetPixelShader( SpotLightPS[g_LP_light_mode] ); SetDepthStencilState( StencilEqOne, 1 ); SetBlendState( AddBlend, float4(0,0,0,0), 0xFFFFFFFF ); } } // ライトモデルの領域のみスポットライト処理 technique10 SpotLightModel { pass p0 { SetVertexShader( CompileShader( vs_4_0, LightModelVS() ) ); SetGeometryShader( NULL ); SetPixelShader( SpotLightPS[g_LP_light_mode] ); SetRasterizerState(CullFront); SetDepthStencilState( DisableDepth, 0 ); SetBlendState( AddBlend, float4(0,0,0,0), 0xFFFFFFFF ); } } // ライトモデルの領域の更にステンシルバッファが1の部分にスポットライト処理 technique10 SpotLightModelMask { pass p0 { SetVertexShader( CompileShader( vs_4_0, LightModelVS() ) ); SetGeometryShader( NULL ); SetPixelShader( SpotLightPS[g_LP_light_mode] ); SetRasterizerState(CullFront); SetDepthStencilState( StencilEqOne, 1 ); SetBlendState( AddBlend, float4(0,0,0,0), 0xFFFFFFFF ); } } // ステンシルバッファにシャドーボリュームを書き込む // Z不合格オモテ面は+1 // Z不合格裏面は-1 DepthStencilState DepthFill { DEPTHENABLE = TRUE; DEPTHWRITEMASK = ZERO; DEPTHFUNC = LESS; STENCILENABLE = TRUE; STENCILREADMASK = 0x0F; STENCILWRITEMASK = 0x0F; FRONTFACESTENCILFAIL = KEEP; FRONTFACESTENCILDEPTHFAIL = INCR; FRONTFACESTENCILPASS = KEEP; FRONTFACESTENCILFUNC = ALWAYS; BACKFACESTENCILFAIL =KEEP; BACKFACESTENCILDEPTHFAIL = DECR; BACKFACESTENCILPASS =KEEP; BACKFACESTENCILFUNC = ALWAYS; }; float4 DR_SPOTLIGHT_DEPTHFILL( VS_Output Input) : SV_TARGET { return 0; } // ライトモデルでステンシルにマスク technique10 SpotLightWriteStencil { pass p0 { SetVertexShader( CompileShader( vs_4_0, LightModelVS() ) ); SetGeometryShader( NULL ); SetPixelShader( CompileShader( ps_4_0, DR_SPOTLIGHT_DEPTHFILL()) ); SetRasterizerState(CullNone); SetDepthStencilState( DepthFill, 0 ); SetBlendState( AddBlend, float4(0,0,0,0), 0xFFFFFFFF ); } } ///------------------------------------------------------------------------------------------------------------------------------------------- /// ライティング(ポイントライト) /// スペキュラとディフューズを足して、浮動小数点バッファに書き出すバージョン float4 DR_POINTLIGHT_PS( VS_Output Input, uniform int mode,uniform bool useTex, uniform bool useShadow ) : SV_TARGET { int lightNo = 0; //return float4(0,0.25,0.25,1); // テクスチャサンプリング位置をInput.Posで決める。 // 入力バッファが全て出力バッファと同じサイズであること前提 int3 texelPos = int3(Input.Pos.xy, 0); float4 pos = g_LP_texPos.Load( texelPos ); if(pos.a == 0) discard; pos.a = 1.0f; // 光源→対象 float3 light_vec = pos.xyz - g_LP_light_position.xyz; // 光源からの距離 float distance = length(light_vec); if( g_LP_light_range < distance) discard; light_vec = normalize(light_vec); // スポットライト中心からの角度 float3 light_dir = light_vec;//normalize(g_LP_light_direction[ lightNo ].xyz); // ライト計算、反射計算はグローバル座標系で行う // ライト float4 ambient_result; float4 diffuse_result; float4 specular_result; // テクスチャからマテリアル情報を取り出す float4 MatDiff = g_LP_texDiff.Load( texelPos ); float4 MatAmb = g_LP_texAmb.Load( texelPos ); float4 MatSpec = g_LP_texSpe.Load( texelPos ); float4 MatRef = g_LP_texRef.Load( texelPos ); float Reflect = MatRef.r; float MatShine= MatAmb.a * 0xFF; float4 norm = g_LP_texNorm.Load( texelPos ); //float4 emissive = texEmissive.Sample( PointSampler, Input.Tex ) * g_EmissiveGain; // UNORM→SNORM変換 norm = (norm*2)-1; // ここに来ている時点で、ライト内部 // 以下方向ライトと同じ //////////////////////////// // アンビエント // アンビエントカラーはそのまま足す ambient_result = g_LP_light_ambient[ lightNo ] * MatAmb; //////////////////////////// // ディフューズ light_dir *= -1; // 光源に向かう方向に反転 // ランバート float lambert = max( 0, dot( -light_vec, norm.xyz ) ); float att_rate = g_LP_light_constant_attenuation[ lightNo ] / pow(1.0 - pow( distance * g_LP_light_dist_rate, g_LP_light_linear_attenuation), g_LP_light_quadratic_attenuation); // テクスチャライト float4 light_tex = (1,1,1,1); if(useTex) { float3 light_up = cross(g_LP_light_right.xyz, light_dir); float right = dot(light_vec, g_LP_light_right.xyz); float up = dot(light_vec, light_up); float front = dot(light_vec, light_dir); float a = front / g_LP_light_phi; float radius = sqrt(pow(a,2) - pow(front,2)); float2 uv; uv.x = (right/radius/2 + 0.5); uv.y = (up/radius/2 + 0.5); light_tex = g_texLightSphere.Sample( LinearSampler, uv ); } diffuse_result = g_LP_light_diffuse[ lightNo ] * lambert; //diffuse_result = saturate(diffuse_result) * MatDiff; diffuse_result = diffuse_result * MatDiff ; //////////////////////////// // スペキュラ float3 eye = normalize(pos.xyz - g_LP_PosCam.xyz); float3 ref = normalize( reflect( -light_vec, norm.xyz ) ); float phong = saturate( dot( ref, eye ) ); float4 spe = g_LP_light_specular[ lightNo ] * max( pow( abs(phong), MatShine ), 0.0 ); // スペキュラライトはフォンモデル specular_result = spe * MatSpec; float4 output = 0; // 出力 // アンビエントには影が影響しないようにする output = ((diffuse_result + specular_result) + ambient_result) / att_rate * light_tex; output.a = 1.0f; return output; } PixelShader PointLightPS[] = { CompileShader( ps_4_0, DR_POINTLIGHT_PS(0, false, false) ), CompileShader( ps_4_0, DR_POINTLIGHT_PS(0, false, true) ), CompileShader( ps_4_0, DR_POINTLIGHT_PS(0, true, false) ), CompileShader( ps_4_0, DR_POINTLIGHT_PS(0, true, true) ), }; // フルスクリーンクアッドでポイントライト処理 technique10 PointLightFullScreen { pass p0 { SetVertexShader( CompileShader( vs_4_0, QuadVS() ) ); SetGeometryShader( NULL ); SetPixelShader( PointLightPS[g_LP_light_mode] ); SetDepthStencilState( DisableDepth, 1 ); SetBlendState( AddBlend, float4(0,0,0,0), 0xFFFFFFFF ); } } // ステンシルバッファが1の場所のみポイントライト処理 technique10 PointLightFullScreenMask { pass p0 { SetVertexShader( CompileShader( vs_4_0, QuadVS() ) ); SetGeometryShader( NULL ); SetPixelShader( PointLightPS[g_LP_light_mode] ); SetDepthStencilState( StencilEqOne, 1 ); SetBlendState( AddBlend, float4(0,0,0,0), 0xFFFFFFFF ); } } // ライトモデルの領域のみポイントライト処理 technique10 PointLightModel { pass p0 { SetVertexShader( CompileShader( vs_4_0, LightModelVS() ) ); SetGeometryShader( NULL ); SetPixelShader( PointLightPS[g_LP_light_mode] ); SetRasterizerState(CullFront); SetDepthStencilState( DisableDepth, 0 ); SetBlendState( AddBlend, float4(0,0,0,0), 0xFFFFFFFF ); } } // ライトモデルの領域の更にステンシルバッファが1の部分にポイントライト処理 technique10 PointLightModelMask { pass p0 { SetVertexShader( CompileShader( vs_4_0, LightModelVS() ) ); SetGeometryShader( NULL ); SetPixelShader( PointLightPS[g_LP_light_mode] ); SetRasterizerState(CullFront); SetDepthStencilState( StencilEqOne, 1 ); SetBlendState( AddBlend, float4(0,0,0,0), 0xFFFFFFFF ); } } float4 DR_POINTLIGHT_DEPTHFILL( VS_Output Input) : SV_TARGET { return 0; } // ライトモデルでステンシルにマスク technique10 PointLightWriteStencil { pass p0 { SetVertexShader( CompileShader( vs_4_0, LightModelVS() ) ); SetGeometryShader( NULL ); SetPixelShader( CompileShader( ps_4_0, DR_POINTLIGHT_DEPTHFILL()) ); SetRasterizerState(CullNone); SetDepthStencilState( DepthFill, 0 ); SetBlendState( AddBlend, float4(0,0,0,0), 0xFFFFFFFF ); } }