// LFS Pixel Shader : Car2 // Vertex shader output structures struct VS_OUTPUT_PRELIT { float4 oPos : POSITION; float oFog : FOG; float4 VCol : COLOR0; float2 oT0 : TEXCOORD0; }; struct VS_OUTPUT { float4 oPos : POSITION; float oFog : FOG; float2 oT0 : TEXCOORD0; float2 oT1 : TEXCOORD1; float3 VCol : COLOR0; // vertex colour float3 AmbientL : COLOR1; // ambient light colour float DirectL : TEXCOORD2; // direct light amount #ifdef SHINY float3 NormalEnv : TEXCOORD3; float3 EyeToVEnv : TEXCOORD4; #endif }; struct VS_OUTPUT_TINT { float4 oPos : POSITION; float oFog : FOG; float2 oT0 : TEXCOORD0; float3 VCol : COLOR0; // vertex colour }; // Global variables float4 light_dir_env : register(c4); //float4 lightmap_col : register(c5); sampler2D s_T0 : register(s0); // texture sampler2D s_T1 : register(s1); // lightmap #ifdef SHINY sampler2D s_T2 : register(s2); // envmap #endif // Main functions // PSHADER_CAR_SIMPLE_2 float4 ps_car_simple_2( in VS_OUTPUT_PRELIT In ) : COLOR // for prelit surfaces on cars, e.g. lights / dashboards / mirrors { float4 tex_col = tex2D(s_T0, In.oT0); return tex_col * In.VCol * float4(2.0f, 2.0f, 2.0f, 1.0f); // mul2x } // PSHADER_CAR_SOLID_SHINY // PSHADER_CAR_SOLID_MATT // PSHADER_CAR_ALPHA_SHINY // PSHADER_CAR_ALPHA_MATT float4 ps_main( in VS_OUTPUT In ) : COLOR { float4 ret; float4 texture_col = tex2D(s_T0, In.oT0); float4 lightmap_col = tex2D(s_T1, In.oT1); float3 diffuse_lighting = (lightmap_col.rgb * In.DirectL + In.AmbientL.rgb) * 2.0f; #ifdef ALPHA // D3DRS_SRCBLEND is D3DBLEND_ONE so that the environment map is not reduced by transparency // multiply the diffuse lighting by alpha here, to give it the same effect as D3DBLEND_SRCALPHA diffuse_lighting *= texture_col.a; #endif ret.rgb = diffuse_lighting * In.VCol * texture_col.rgb * 2.0f; // mul2x #ifdef SHINY #ifdef ALPHA const float facing_reflectivity = 0.08f; // reflectivity of glass (parallel to normal) #else const float facing_reflectivity = 0.04f; // reflectivity of paint (parallel to normal) #endif float3 normal_env = normalize(In.NormalEnv); float3 e_env = normalize(In.EyeToVEnv); // eye to vertex float E_dot_N = min(0.0f, dot(e_env, normal_env)); float3 env_dir = e_env - 2.0f * E_dot_N * normal_env; // reflection of e_env float4 envmap_col = tex2D(s_T2, env_dir.xy * float2(0.5f, 0.5f) + float2(0.5f, 0.5f)); float schlick = pow(1.0f + E_dot_N, 5); float reflectivity_mul = lerp(facing_reflectivity, 1.0f, schlick); // multiplied by bound(0, r4.z * 12, 1) to avoid downward reflection (environment map is a modified sky dome) // multiplied again by 4 because the environment map is rendered at quarter brightness float env_map_mul = reflectivity_mul * saturate(env_dir.z * 12.0f) * 4.0f; ret.rgb += envmap_col.rgb * env_map_mul; // add environment map #ifdef HIGHLIGHT_EXP // not defined when weather is overcast float x = max(0.0f, dot(light_dir_env.xyz, env_dir)); // detect highlight ret.rgb += lightmap_col.rgb * (pow(x, HIGHLIGHT_EXP) * HIGHLIGHT_MUL * reflectivity_mul); // add highlight #endif #ifdef ALPHA // reflectivity_mul is used here to reduce glass transparency at high angles of incidence ret.a = lerp(texture_col.a, 1.0f, reflectivity_mul); // destination pixel is multiplied by (1 - ret.a) #else ret.a = 1.0f; // SOLID so no need for the alpha value from the texture (ATEST cannot be shiny) #endif #else // NOT SHINY // if ALPHA is defined - transparent but not shiny, e.g. a dashboard overlay // if ALPHA is not defined it is usually SOLID but could be ATEST in which case the alpha value is needed ret.a = texture_col.a; #endif // SHINY return ret; } // PSHADER_CAR_ALPHA_TINT float4 ps_tint( in VS_OUTPUT_TINT In ) : COLOR // tinted glass is drawn in two passes - this is the first pass - currently unused { float4 texture_col = tex2D(s_T0, In.oT0); return float4(In.VCol * texture_col.rgb * 2.0f, 1.0f); // mul2x }