forked from aya/aya
159 lines
5.2 KiB
HLSL
159 lines
5.2 KiB
HLSL
#include "common.h"
|
|
|
|
struct Appdata
|
|
{
|
|
ATTR_INT4 Position : POSITION;
|
|
ATTR_INT3 Normal : NORMAL;
|
|
ATTR_INT4 Uv : TEXCOORD0;
|
|
#ifdef PIN_HQ
|
|
ATTR_INT4 EdgeDistances : TEXCOORD1;
|
|
ATTR_INT3 Tangent : TEXCOORD2;
|
|
#endif
|
|
};
|
|
|
|
struct VertexOutput
|
|
{
|
|
float4 HPosition : POSITION;
|
|
|
|
float4 UvHigh_EdgeDistance1 : TEXCOORD0;
|
|
float4 UvLow_EdgeDistance2 : TEXCOORD1;
|
|
|
|
float4 LightPosition_Fog : TEXCOORD2;
|
|
|
|
#ifdef PIN_HQ
|
|
float4 View_Depth : TEXCOORD3;
|
|
float4 Normal_Blend : TEXCOORD4;
|
|
float3 Tangent : TEXCOORD5;
|
|
#else
|
|
float4 Diffuse_Blend : COLOR0;
|
|
#endif
|
|
|
|
float3 PosLightSpace : TEXCOORD7;
|
|
};
|
|
|
|
WORLD_MATRIX(WorldMatrix);
|
|
|
|
VertexOutput MegaClusterVS(Appdata IN)
|
|
{
|
|
VertexOutput OUT = (VertexOutput)0;
|
|
|
|
// Decode vertex data
|
|
float3 Normal = (IN.Normal - 127.0) / 127.0;
|
|
float4 UV = IN.Uv / 2048.0;
|
|
|
|
// Transform position and normal to world space
|
|
// Note: world matrix does not contain rotation/scale for static geometry so we can avoid transforming normal
|
|
float3 posWorld = mul(WorldMatrix, IN.Position).xyz;
|
|
float3 normalWorld = Normal;
|
|
|
|
OUT.HPosition = mul(G(ViewProjection), float4(posWorld, 1));
|
|
|
|
float blend = OUT.HPosition.w / 200;
|
|
|
|
OUT.LightPosition_Fog = float4(lgridPrepareSample(lgridOffset(posWorld, normalWorld)), (G(FogParams).z - OUT.HPosition.w) * G(FogParams).w);
|
|
|
|
OUT.UvHigh_EdgeDistance1.xy = UV.xy;
|
|
OUT.UvLow_EdgeDistance2.xy = UV.zw;
|
|
|
|
#ifdef PIN_HQ
|
|
OUT.View_Depth = float4(posWorld, OUT.HPosition.w * G(FadeDistance_GlowFactor).y);
|
|
float4 edgeDistances = IN.EdgeDistances*G(FadeDistance_GlowFactor).z + 0.5 * OUT.View_Depth.w;
|
|
|
|
OUT.UvHigh_EdgeDistance1.zw = edgeDistances.xy;
|
|
OUT.UvLow_EdgeDistance2.zw = edgeDistances.zw;
|
|
|
|
OUT.View_Depth.xyz = G(CameraPosition).xyz - posWorld;
|
|
OUT.Normal_Blend = float4(Normal, blend);
|
|
// decode tangent
|
|
OUT.Tangent = (IN.Tangent - 127.0) / 127.0;
|
|
#else
|
|
// IF LQ shading is performed in VS
|
|
float ndotl = dot(normalWorld, -G(Lamp0Dir));
|
|
float3 diffuse = saturate(ndotl) * G(Lamp0Color) + max(-ndotl, 0) * G(Lamp1Color);
|
|
|
|
OUT.Diffuse_Blend = float4(diffuse, blend);
|
|
#endif
|
|
|
|
OUT.PosLightSpace = shadowPrepareSample(posWorld);
|
|
|
|
return OUT;
|
|
}
|
|
|
|
TEX_DECLARE2D(DiffuseHighMap, 0);
|
|
TEX_DECLARE2D(DiffuseLowMap, 1);
|
|
TEX_DECLARE2D(NormalMap, 2);
|
|
TEX_DECLARE2D(SpecularMap, 3);
|
|
LGRID_SAMPLER(LightMap, 4);
|
|
TEX_DECLARE2D(LightMapLookup, 5);
|
|
TEX_DECLARE2D(ShadowMap, 6);
|
|
|
|
void MegaClusterPS(VertexOutput IN,
|
|
#ifdef PIN_GBUFFER
|
|
out float4 oColor1: COLOR1,
|
|
#endif
|
|
out float4 oColor0: COLOR0)
|
|
{
|
|
float4 high = tex2D(DiffuseHighMap, IN.UvHigh_EdgeDistance1.xy);
|
|
float4 low = tex2D(DiffuseLowMap, IN.UvLow_EdgeDistance2.xy);
|
|
|
|
float4 light = lgridSample(TEXTURE(LightMap), TEXTURE(LightMapLookup), IN.LightPosition_Fog.xyz);
|
|
float shadow = shadowSample(TEXTURE(ShadowMap), IN.PosLightSpace, light.a);
|
|
|
|
#ifdef PIN_HQ
|
|
float3 albedo = lerp(high.rgb, low.rgb, saturate1(IN.Normal_Blend.a));
|
|
|
|
// sample normal map and specular map
|
|
float4 normalMapSample = tex2D(NormalMap, IN.UvHigh_EdgeDistance1.xy);
|
|
float4 specularMapSample = tex2D(SpecularMap, IN.UvHigh_EdgeDistance1.xy);
|
|
|
|
// compute bitangent and world space normal
|
|
float3 bitangent = cross(IN.Normal_Blend.xyz, IN.Tangent.xyz);
|
|
#ifdef CLASSIC
|
|
float3 nmap = float3(0,0,.5);
|
|
#else
|
|
float3 nmap = nmapUnpack(normalMapSample);
|
|
#endif
|
|
float3 normal = normalize(nmap.x * IN.Tangent.xyz + nmap.y * bitangent + nmap.z * IN.Normal_Blend.xyz);
|
|
|
|
float ndotl = dot(normal, -G(Lamp0Dir));
|
|
float3 diffuseIntensity = saturate0(ndotl) * G(Lamp0Color) + max(-ndotl, 0) * G(Lamp1Color);
|
|
float specularIntensity = step(0, ndotl) * specularMapSample.r;
|
|
float specularPower = specularMapSample.g * 255 + 0.01;
|
|
|
|
// Compute diffuse and specular and combine them
|
|
float3 diffuse = (G(AmbientColor) + diffuseIntensity * shadow + light.rgb) * albedo.rgb;
|
|
float3 specular = G(Lamp0Color) * (specularIntensity * shadow * (float)(half)pow(saturate(dot(normal, normalize(-G(Lamp0Dir) + normalize(IN.View_Depth.xyz)))), specularPower));
|
|
oColor0.rgb = diffuse + specular;
|
|
|
|
// apply outlines
|
|
float outlineFade = saturate1(IN.View_Depth.w * G(OutlineBrightness_ShadowInfo).x + G(OutlineBrightness_ShadowInfo).y);
|
|
float2 minIntermediate = min(IN.UvHigh_EdgeDistance1.wz, IN.UvLow_EdgeDistance2.wz);
|
|
float minEdgesPlus = min(minIntermediate.x, minIntermediate.y) / IN.View_Depth.w;
|
|
oColor0.rgb *= saturate1(outlineFade * (1.5 - minEdgesPlus) + minEdgesPlus);
|
|
|
|
oColor0.a = 1;
|
|
|
|
#else
|
|
float3 albedo = lerp(high.rgb, low.rgb, saturate1(IN.Diffuse_Blend.a));
|
|
|
|
// Compute diffuse term
|
|
float3 diffuse = (G(AmbientColor) + IN.Diffuse_Blend.rgb * shadow + light.rgb) * albedo.rgb;
|
|
|
|
// Combine
|
|
oColor0.rgb = diffuse;
|
|
oColor0.a = 1;
|
|
|
|
#endif
|
|
|
|
float fogAlpha = saturate(IN.LightPosition_Fog.w);
|
|
|
|
oColor0.rgb = lerp(G(FogColor), oColor0.rgb, fogAlpha);
|
|
#ifdef CLASSIC
|
|
oColor0.rgb = IN.UvHigh_EdgeDistance1.xyy;
|
|
oColor0.rgb = G(OutlineBrightness_ShadowInfo).xxx;
|
|
#endif
|
|
#ifdef PIN_GBUFFER
|
|
oColor1 = gbufferPack(IN.View_Depth.w*G(FadeDistance_GlowFactor).x, diffuse.rgb, 0, fogAlpha);
|
|
#endif
|
|
}
|