268 lines
7.8 KiB
HLSL
268 lines
7.8 KiB
HLSL
#include "common.h"
|
|
|
|
struct Appdata
|
|
{
|
|
float4 Position : POSITION;
|
|
float3 Normal : NORMAL;
|
|
float2 Uv : TEXCOORD0;
|
|
float2 UvStuds : TEXCOORD1;
|
|
|
|
float4 Color : COLOR0;
|
|
|
|
// int4 produces better D3D asm, float4 produces better GLSL code
|
|
#ifdef GLSL
|
|
float4 Extra : COLOR1;
|
|
#else
|
|
int4 Extra : COLOR1;
|
|
#endif
|
|
|
|
#ifdef PIN_SURFACE
|
|
float3 Tangent : TEXCOORD2;
|
|
#endif
|
|
float4 EdgeDistances : TEXCOORD3;
|
|
};
|
|
|
|
struct VertexOutput
|
|
{
|
|
float4 HPosition : POSITION;
|
|
float4 Uv_EdgeDistance1 : TEXCOORD0;
|
|
float4 UvStuds_EdgeDistance2 : TEXCOORD1;
|
|
|
|
float4 Color : COLOR0;
|
|
float4 LightPosition_Fog : TEXCOORD2;
|
|
|
|
#if defined(PIN_HQ) || defined(PIN_REFLECTION)
|
|
float4 View_DepthMulFadeout : TEXCOORD3;
|
|
float4 Normal_SpecPower : TEXCOORD4;
|
|
#endif
|
|
|
|
#ifdef PIN_SURFACE
|
|
float3 Tangent : TEXCOORD5;
|
|
#else
|
|
float4 Diffuse_Specular : COLOR1;
|
|
#endif
|
|
|
|
float4 PosLightSpace_Reflectance: TEXCOORD6;
|
|
};
|
|
|
|
#ifdef PIN_SKINNED
|
|
uniform float4 WorldMatrixArray[MAX_BONE_COUNT * 3];
|
|
#endif
|
|
|
|
#ifdef PIN_DEBUG
|
|
uniform float4 DebugColor;
|
|
#endif
|
|
|
|
VertexOutput DefaultVS(Appdata IN)
|
|
{
|
|
VertexOutput OUT = (VertexOutput)0;
|
|
|
|
// Transform position and normal to world space
|
|
#ifdef PIN_SKINNED
|
|
int boneIndex = IN.Extra.r;
|
|
|
|
float4 worldRow0 = WorldMatrixArray[boneIndex * 3 + 0];
|
|
float4 worldRow1 = WorldMatrixArray[boneIndex * 3 + 1];
|
|
float4 worldRow2 = WorldMatrixArray[boneIndex * 3 + 2];
|
|
|
|
float3 posWorld = float3(dot(worldRow0, IN.Position), dot(worldRow1, IN.Position), dot(worldRow2, IN.Position));
|
|
float3 normalWorld = float3(dot(worldRow0.xyz, IN.Normal), dot(worldRow1.xyz, IN.Normal), dot(worldRow2.xyz, IN.Normal));
|
|
#else
|
|
float3 posWorld = IN.Position.xyz;
|
|
float3 normalWorld = IN.Normal;
|
|
#endif
|
|
|
|
// Decode diffuse/specular parameters; encoding depends on the skinned flag due to vertex declaration differences
|
|
#if defined(PIN_DEBUG)
|
|
float4 color = DebugColor;
|
|
#else
|
|
float4 color = IN.Color;
|
|
#endif
|
|
|
|
float specularIntensity = IN.Extra.g / 255.f;
|
|
float specularPower = IN.Extra.b;
|
|
|
|
float ndotl = dot(normalWorld, -G.Lamp0Dir);
|
|
|
|
#ifdef PIN_HQ
|
|
// We'll calculate specular in pixel shader
|
|
float2 lt = float2(saturate(ndotl), (ndotl > 0));
|
|
#else
|
|
// Using lit here improves performance on software vertex shader implementations
|
|
float2 lt = lit(ndotl, dot(normalize(-G.Lamp0Dir + normalize(G.CameraPosition - posWorld.xyz)), normalWorld), specularPower).yz;
|
|
#endif
|
|
|
|
OUT.HPosition = mul(G.ViewProjection, float4(posWorld, 1));
|
|
|
|
OUT.Uv_EdgeDistance1.xy = IN.Uv;
|
|
OUT.UvStuds_EdgeDistance2.xy = IN.UvStuds;
|
|
|
|
OUT.Color = color;
|
|
OUT.LightPosition_Fog = float4(lgridPrepareSample(lgridOffset(posWorld, normalWorld)), (G.FogParams.z - OUT.HPosition.w) * G.FogParams.w);
|
|
|
|
#if defined(PIN_HQ) || defined(PIN_REFLECTION)
|
|
OUT.View_DepthMulFadeout = float4(G.CameraPosition - posWorld, OUT.HPosition.w * G.FadeDistance.y);
|
|
float4 edgeDistances = IN.EdgeDistances*G.FadeDistance.z + 0.5 * OUT.View_DepthMulFadeout.w;
|
|
OUT.Uv_EdgeDistance1.zw = edgeDistances.xy;
|
|
OUT.UvStuds_EdgeDistance2.zw = edgeDistances.zw;
|
|
OUT.Normal_SpecPower = float4(normalWorld, specularPower);
|
|
OUT.PosLightSpace_Reflectance.w = IN.Extra.a / 255.f;
|
|
#endif
|
|
|
|
#ifdef PIN_SURFACE
|
|
#ifdef PIN_SKINNED
|
|
float3 tangent = float3(dot(worldRow0.xyz, IN.Tangent), dot(worldRow1.xyz, IN.Tangent), dot(worldRow2.xyz, IN.Tangent));
|
|
#else
|
|
float3 tangent = IN.Tangent;
|
|
#endif
|
|
|
|
OUT.Tangent = tangent;
|
|
#else
|
|
float3 diffuse = lt.x * G.Lamp0Color + max(-ndotl, 0) * G.Lamp1Color;
|
|
|
|
OUT.Diffuse_Specular = float4(diffuse, lt.y * specularIntensity);
|
|
#endif
|
|
|
|
OUT.PosLightSpace_Reflectance.xyz = getPosInLightSpace(posWorld);
|
|
|
|
return OUT;
|
|
}
|
|
|
|
#ifdef PIN_SURFACE
|
|
struct SurfaceInput
|
|
{
|
|
float4 Color;
|
|
float2 Uv;
|
|
float2 UvStuds;
|
|
|
|
#ifdef PIN_REFLECTION
|
|
float Reflectance;
|
|
#endif
|
|
};
|
|
|
|
struct Surface
|
|
{
|
|
float3 albedo;
|
|
float3 normal;
|
|
float specular;
|
|
float gloss;
|
|
float reflectance;
|
|
};
|
|
|
|
Surface surfaceShader(SurfaceInput IN, float fade);
|
|
|
|
Surface surfaceShaderExec(VertexOutput IN)
|
|
{
|
|
SurfaceInput SIN;
|
|
SIN.Color = IN.Color;
|
|
SIN.Uv = IN.Uv_EdgeDistance1.xy;
|
|
SIN.UvStuds = IN.UvStuds_EdgeDistance2.xy;
|
|
|
|
#ifdef PIN_REFLECTION
|
|
SIN.Reflectance = IN.PosLightSpace_Reflectance.w;
|
|
#endif
|
|
|
|
float fade = saturate0(1 - IN.View_DepthMulFadeout.w);
|
|
|
|
return surfaceShader(SIN, fade);
|
|
}
|
|
#endif
|
|
|
|
sampler2D StudsMap: register(s0);
|
|
LGRID_SAMPLER LightMap: register(s1);
|
|
sampler2D LightMapLookup: register(s2);
|
|
|
|
sampler2D DiffuseMap: register(s3);
|
|
sampler2D NormalMap: register(s4);
|
|
samplerCUBE EnvironmentMap: register(s5);
|
|
|
|
sampler2D SpecularMap: register(s6);
|
|
sampler2D NormalDetailMap: register(s7);
|
|
|
|
void DefaultPS(VertexOutput IN,
|
|
#ifdef PIN_GBUFFER
|
|
out float4 oColor1: COLOR1,
|
|
#endif
|
|
out float4 oColor0: COLOR0)
|
|
{
|
|
// Compute albedo term
|
|
#ifdef PIN_SURFACE
|
|
Surface surface = surfaceShaderExec(IN);
|
|
|
|
float4 albedo = float4(surface.albedo, IN.Color.a);
|
|
|
|
float3 bitangent = cross(IN.Normal_SpecPower.xyz, IN.Tangent.xyz);
|
|
float3 normal = normalize(surface.normal.x * IN.Tangent.xyz + surface.normal.y * bitangent + surface.normal.z * IN.Normal_SpecPower.xyz);
|
|
|
|
float ndotl = dot(normal, -G.Lamp0Dir);
|
|
|
|
float3 diffuseIntensity = saturate0(ndotl) * G.Lamp0Color + max(-ndotl, 0) * G.Lamp1Color;
|
|
float specularIntensity = step(0, ndotl) * surface.specular;
|
|
float specularPower = surface.gloss;
|
|
|
|
float reflectance = surface.reflectance;
|
|
#else
|
|
#ifdef PIN_PLASTIC
|
|
float4 studs = tex2D(StudsMap, IN.UvStuds_EdgeDistance2.xy);
|
|
float4 albedo = float4(IN.Color.rgb * 2 * studs.rgb, IN.Color.a);
|
|
#else
|
|
float4 albedo = tex2D(DiffuseMap, IN.Uv_EdgeDistance1.xy) * IN.Color;
|
|
#endif
|
|
|
|
#ifdef PIN_HQ
|
|
float3 normal = normalize(IN.Normal_SpecPower.xyz);
|
|
float specularPower = IN.Normal_SpecPower.w;
|
|
#elif defined(PIN_REFLECTION)
|
|
float3 normal = IN.Normal_SpecPower.xyz;
|
|
#endif
|
|
|
|
float3 diffuseIntensity = IN.Diffuse_Specular.xyz;
|
|
float specularIntensity = IN.Diffuse_Specular.w;
|
|
|
|
#ifdef PIN_REFLECTION
|
|
float reflectance = IN.PosLightSpace_Reflectance.w;
|
|
#endif
|
|
|
|
#endif
|
|
|
|
float4 light = lgridSample(LightMap, LightMapLookup, IN.LightPosition_Fog.xyz);
|
|
|
|
// Compute reflection term
|
|
#if defined(PIN_SURFACE) || defined(PIN_REFLECTION)
|
|
float3 reflection = texCUBE(EnvironmentMap, reflect(-IN.View_DepthMulFadeout.xyz, normal)).rgb;
|
|
|
|
albedo.rgb = lerp(albedo.rgb, reflection.rgb, reflectance);
|
|
#endif
|
|
|
|
float shadow = getBlobShadow(IN.PosLightSpace_Reflectance.xyz) * light.a;
|
|
|
|
// Compute diffuse term
|
|
float3 diffuse = (G.AmbientColor + diffuseIntensity * shadow + light.rgb) * albedo.rgb;
|
|
|
|
// Compute specular term
|
|
#ifdef PIN_HQ
|
|
float3 specular = G.Lamp0Color * (specularIntensity * shadow * (float)(half)pow(saturate(dot(normal, normalize(-G.Lamp0Dir + normalize(IN.View_DepthMulFadeout.xyz)))), specularPower));
|
|
#else
|
|
float3 specular = G.Lamp0Color * (specularIntensity * shadow);
|
|
#endif
|
|
|
|
// Combine
|
|
oColor0.rgb = diffuse.rgb + specular.rgb;
|
|
oColor0.a = albedo.a;
|
|
|
|
#ifdef PIN_HQ
|
|
float outlineFade = saturate1(IN.View_DepthMulFadeout.w * G.OutlineBrightness_ShadowInfo.x + G.OutlineBrightness_ShadowInfo.y);
|
|
float2 minIntermediate = min(IN.Uv_EdgeDistance1.wz, IN.UvStuds_EdgeDistance2.wz);
|
|
float minEdgesPlus = min(minIntermediate.x, minIntermediate.y) / IN.View_DepthMulFadeout.w;
|
|
oColor0.rgb *= saturate1(outlineFade *(1.5 - minEdgesPlus) + minEdgesPlus);
|
|
#endif
|
|
|
|
float fogAlpha = saturate(IN.LightPosition_Fog.w);
|
|
|
|
oColor0.rgb = lerp(G.FogColor, oColor0.rgb, fogAlpha);
|
|
|
|
#ifdef PIN_GBUFFER
|
|
oColor1 = gbufferPack(IN.View_DepthMulFadeout.w*G.FadeDistance.x, diffuse.rgb, specular.rgb, fogAlpha);
|
|
#endif
|
|
}
|