forked from aya/aya
175 lines
4.9 KiB
HLSL
175 lines
4.9 KiB
HLSL
#include "common.h"
|
|
|
|
struct Appdata
|
|
{
|
|
ATTR_INT4 Position : POSITION;
|
|
|
|
ATTR_INT4 Normal : NORMAL;
|
|
|
|
ATTR_INT4 Material0 : TEXCOORD0;
|
|
ATTR_INT4 Material1 : TEXCOORD1;
|
|
};
|
|
|
|
struct VertexOutput
|
|
{
|
|
float4 HPosition : POSITION;
|
|
|
|
float3 Weights: COLOR0;
|
|
|
|
float4 Uv0: TEXCOORD0;
|
|
float4 Uv1: TEXCOORD1;
|
|
float4 Uv2: TEXCOORD2;
|
|
|
|
float4 LightPosition_Fog : TEXCOORD3;
|
|
float3 PosLightSpace : TEXCOORD4;
|
|
|
|
#ifdef PIN_HQ
|
|
float3 Normal: TEXCOORD5;
|
|
float4 View_Depth: TEXCOORD6;
|
|
|
|
float3 Tangents: COLOR1;
|
|
#else
|
|
float3 Diffuse: COLOR1;
|
|
#endif
|
|
};
|
|
|
|
WORLD_MATRIX_ARRAY(WorldMatrixArray, 72);
|
|
|
|
uniform float4 LayerScale;
|
|
|
|
float4 getUV(float3 position, ATTR_INT material, ATTR_INT projection, float seed)
|
|
{
|
|
float3 u = WorldMatrixArray[1 + int(projection)].xyz;
|
|
float3 v = WorldMatrixArray[19 + int(projection)].xyz;
|
|
|
|
float4 m = WorldMatrixArray[37 + int(material)];
|
|
|
|
float2 uv = float2(dot(position, u), dot(position, v)) * m.x + m.y * float2(seed, floor(seed * 2.6651441f));
|
|
|
|
return float4(uv, m.zw);
|
|
}
|
|
|
|
VertexOutput TerrainVS(Appdata IN)
|
|
{
|
|
VertexOutput OUT = (VertexOutput)0;
|
|
|
|
float3 posWorld = IN.Position.xyz * WorldMatrixArray[0].w + WorldMatrixArray[0].xyz;
|
|
float3 normalWorld = IN.Normal.xyz * (1.0 / 127.0) - 1.0;
|
|
|
|
OUT.HPosition = mul(G(ViewProjection), float4(posWorld, 1));
|
|
|
|
OUT.LightPosition_Fog = float4(lgridPrepareSample(lgridOffset(posWorld, normalWorld)), (G(FogParams).z - OUT.HPosition.w) * G(FogParams).w);
|
|
|
|
OUT.PosLightSpace = shadowPrepareSample(posWorld);
|
|
|
|
OUT.Uv0 = getUV(posWorld, IN.Material0.x, IN.Material1.x, IN.Normal.w);
|
|
OUT.Uv1 = getUV(posWorld, IN.Material0.y, IN.Material1.y, IN.Material0.w);
|
|
OUT.Uv2 = getUV(posWorld, IN.Material0.z, IN.Material1.z, IN.Material1.w);
|
|
|
|
#if defined(GLSLES) && !defined(GL3) // iPad2 workaround
|
|
OUT.Weights = abs(IN.Position.www - float3(0, 1, 2)) < 0.1;
|
|
#else
|
|
OUT.Weights = IN.Position.www == float3(0, 1, 2);
|
|
#endif
|
|
|
|
#ifdef PIN_HQ
|
|
OUT.Normal = normalWorld;
|
|
OUT.View_Depth = float4(G(CameraPosition) - posWorld, OUT.HPosition.w);
|
|
OUT.Tangents = float3(IN.Material1.xyz) > 7.5; // side vs top
|
|
#else
|
|
float ndotl = dot(normalWorld, -G(Lamp0Dir));
|
|
float3 diffuse = max(ndotl, 0) * G(Lamp0Color) + max(-ndotl, 0) * G(Lamp1Color);
|
|
|
|
OUT.Diffuse = diffuse;
|
|
#endif
|
|
|
|
return OUT;
|
|
}
|
|
|
|
TEX_DECLARE2D(AlbedoMap, 0);
|
|
TEX_DECLARE2D(NormalMap, 1);
|
|
TEX_DECLARE2D(SpecularMap, 2);
|
|
TEX_DECLARECUBE(EnvMap, 3);
|
|
LGRID_SAMPLER(LightMap, 4);
|
|
TEX_DECLARE2D(LightMapLookup, 5);
|
|
TEX_DECLARE2D(ShadowMap, 6);
|
|
|
|
float4 sampleMap(TEXTURE_IN_2D(s), float4 uv)
|
|
{
|
|
#ifdef PIN_HQ
|
|
float2 uvs = uv.xy * LayerScale.xy;
|
|
|
|
return tex2Dgrad(s, frac(uv.xy) * LayerScale.xy + uv.zw, ddx(uvs), ddy(uvs));
|
|
#else
|
|
return tex2D(s, frac(uv.xy) * LayerScale.xy + uv.zw);
|
|
#endif
|
|
}
|
|
|
|
float4 sampleBlend(TEXTURE_IN_2D(s), float4 uv0, float4 uv1, float4 uv2, float3 w)
|
|
{
|
|
return
|
|
sampleMap(TEXTURE(s), uv0) * w.x +
|
|
sampleMap(TEXTURE(s), uv1) * w.y +
|
|
sampleMap(TEXTURE(s), uv2) * w.z;
|
|
}
|
|
|
|
float3 sampleNormal(TEXTURE_IN_2D(s), float4 uv0, float4 uv1, float4 uv2, float3 w, float3 normal, float3 tsel)
|
|
{
|
|
return terrainNormal(sampleMap(TEXTURE(s), uv0), sampleMap(TEXTURE(s), uv1), sampleMap(TEXTURE(s), uv2), w, normal, tsel);
|
|
}
|
|
|
|
void TerrainPS(VertexOutput IN,
|
|
#ifdef PIN_GBUFFER
|
|
out float4 oColor1: COLOR1,
|
|
#endif
|
|
out float4 oColor0: COLOR0)
|
|
{
|
|
float4 light = lgridSample(TEXTURE(LightMap), TEXTURE(LightMapLookup), IN.LightPosition_Fog.xyz);
|
|
float shadow = shadowSample(TEXTURE(ShadowMap), IN.PosLightSpace, light.a);
|
|
|
|
float3 w = IN.Weights.xyz;
|
|
|
|
float4 albedo = sampleBlend(TEXTURE(AlbedoMap), IN.Uv0, IN.Uv1, IN.Uv2, w);
|
|
|
|
#ifdef PIN_HQ
|
|
float fade = saturate0(1 - IN.View_Depth.w * G(FadeDistance_GlowFactor).y);
|
|
|
|
#ifndef PIN_GBUFFER
|
|
float3 normal = IN.Normal;
|
|
#else
|
|
float3 normal = sampleNormal(TEXTURE(NormalMap), IN.Uv0, IN.Uv1, IN.Uv2, w, IN.Normal, IN.Tangents);
|
|
#endif
|
|
|
|
float4 params = sampleBlend(TEXTURE(SpecularMap), IN.Uv0, IN.Uv1, IN.Uv2, w);
|
|
|
|
float ndotl = dot(normal, -G(Lamp0Dir));
|
|
|
|
// Compute diffuse term
|
|
float3 diffuse = (G(AmbientColor) + (saturate(ndotl) * G(Lamp0Color) + max(-ndotl, 0) * G(Lamp1Color)) * shadow + light.rgb + params.b * 2) * albedo.rgb;
|
|
|
|
// Compute specular term
|
|
float specularIntensity = step(0, ndotl) * params.r * fade;
|
|
float specularPower = params.g * 128 + 0.01;
|
|
|
|
float3 specular = G(Lamp0Color) * (specularIntensity * shadow * (float)(half)pow(saturate(dot(normal, normalize(-G(Lamp0Dir) + normalize(IN.View_Depth.xyz)))), specularPower));
|
|
#else
|
|
// Compute diffuse term
|
|
float3 diffuse = (G(AmbientColor) + IN.Diffuse * shadow + light.rgb) * albedo.rgb;
|
|
|
|
// Compute specular term
|
|
float3 specular = 0;
|
|
#endif
|
|
|
|
// Combine
|
|
oColor0.rgb = diffuse + specular;
|
|
oColor0.a = 1;
|
|
|
|
float fogAlpha = saturate(IN.LightPosition_Fog.w);
|
|
|
|
oColor0.rgb = lerp(G(FogColor), oColor0.rgb, fogAlpha);
|
|
|
|
#ifdef PIN_GBUFFER
|
|
oColor1 = gbufferPack(IN.View_Depth.w, diffuse.rgb, specular.rgb, fogAlpha);
|
|
#endif
|
|
}
|