float4x4 viewProj : register(c31); float4 resolution : register(c0); float3 lightDir : register(c1); sampler2D waveSampler : register(s0); sampler3D randomSampler : register(s1); sampler1D dif : register(s2); sampler1D spec : register(s3); sampler2D shadowSampler : register(s4); sampler2D depthSampler : register(s5); samplerCUBE envSampler : register(s6); static float3 lightSources[] = { float3(19.6f, 8.9f, 2.0f), float3(40.3f, 0.7f, 26.1f), float3(22.5f, -6.2f, -9.2f), float3(-15.9f, 6.8f, -23.9f), float3(-5.2f, 8.9f, -29.2f), float3(10.1f, 11.4f, -13.6f) }; static float4 lightColors[] = { 8.0 * float4(0.7f, 0.6f, 1.0f, 1.0f), 8.0 * float4(0.7f, 0.6f, 1.0f, 1.0f), 8.0 * float4(0.7f, 0.6f, 1.0f, 1.0f), 8.0 * float4(0.7f, 0.6f, 1.0f, 1.0f), 8.0 * float4(0.7f, 0.6f, 1.0f, 1.0f), 8.0 * float4(0.7f, 0.6f, 1.0f, 1.0f) }; static float lightRanges[] = { 3.0f / 2.6f, 3.0f / 3.5f, 3.0f / 5.3f, 3.0f / 1.0f, 3.0f / 1.2f, 3.0f / 1.6f }; static int lightCount = 6; struct psIn { float4 c : COLOR0; float2 t : TEXCOORD0; float3 n : TEXCOORD1; float3 v : TEXCOORD2; float4 s : TEXCOORD3; float3 w : TEXCOORD4; }; float4 tex2D_3D(uniform sampler2D smplr, in float3 t, in float3 n) { float4 front = tex2D(smplr, t.xy); float4 side = tex2D(smplr, t.zy); float4 floor = tex2D(smplr, t.xz); return lerp( lerp(side, front, abs(n.z)), floor, abs(n.y) ); } float4 ps_main(psIn i, uniform bool bCrystalLight) : color0 { // Shadow AA float2 sc = i.s.xy / i.s.w; float aa = abs( tex2D(depthSampler, sc).x - i.s.z ); float2 ddaa = float2(ddx(aa), ddy(aa)); float2 aaetc = sign(-ddaa) * resolution.zw; sc += aaetc * saturate(4.f * aa); float3 t = i.w / 128; float3 n = normalize(i.n); float3 v = normalize(i.v); // Composition float iceAmount = 0.68f; float rock = smoothstep(iceAmount - 0.05f, iceAmount, tex2D_3D(waveSampler, 0.6f * t, n).a); float rockBlend = smoothstep( -0.7f, 1.0f, rock ); float transition = 1.0f - abs( 2.0f * rock - 1.0f ); // Surface float3 vSurfacePoint = i.w - n * rock; float3 vSurfacePointDDX = ddx(vSurfacePoint), vSurfacePointDDY = ddy(vSurfacePoint); float3 vSurfaceNormal = normalize( cross(vSurfacePointDDX, vSurfacePointDDY) ); float3 vFlatSurfaceNormal = vSurfaceNormal - n * dot(n, vSurfaceNormal); float4 fShadow = float4(0.2f, 0.4f, 0.6f, 0.8f) + float4(0.8f, 0.6f, 0.4f, 0.2f) * tex2D(shadowSampler, sc).x; float3 tc = (i.w - v) * 8; float3 vCellCoord1 = tc + 1.5f * tex3D(randomSampler, tc / 48).xyz; float3 vCellCoord2 = 1.25f * tc + 3.0f * tex3D(randomSampler, tc / 32).xyz; float3 vCellCoord1Frac = frac(vCellCoord1) * 2.0f - 1.0f; float3 vCellCoord2Frac = frac(vCellCoord2) * 2.0f - 1.0f; vCellCoord1 = floor(vCellCoord1) + sign(vCellCoord1Frac) * pow( abs(vCellCoord1Frac), 8 ) * 0.5f + 0.5f; vCellCoord2 = floor(vCellCoord2) + sign(vCellCoord2Frac) * pow( abs(vCellCoord2Frac), 8 ) * 0.5f + 0.5f; float3 vCellNormal1 = normalize( tex3D(randomSampler, vCellCoord1 / 32).xyz * 2.0f - 1.0f ); float3 vCellNormal2 = normalize( tex3D(randomSampler, vCellCoord2 / 32).xyz * 2.0f - 1.0f ); float3 vFlatCellNormal1 = vCellNormal1 - n * dot(n, vCellNormal1); float3 vFlatCellNormal2 = vCellNormal2 - n * dot(n, vCellNormal2); float3 rockN = tex2D_3D(waveSampler, t, n).xyz * (0.5 - abs( cos( (t.x + 0.1 * tex2D_3D(waveSampler, t * 2, n).a) * 20 ) ) ); float3 roughN = tex2D_3D(waveSampler, t * 10, n).xyz * 0.3 + tex2D_3D(waveSampler, t * 100, n).xyz * 0.4; float3 fIceNormal = normalize( n + 0.2f * roughN + transition * vFlatSurfaceNormal ); float3 fIceNormalEx = normalize(fIceNormal - 0.7f * n * dot(fIceNormal, n)); float3 fRockNormal = normalize( n + 0.4f * (roughN + rockN) ); float3 fRockNormalEx = normalize(fRockNormal - 0.6f * n * dot(fRockNormal, n)); float3 fIceCellNormal1 = normalize(fIceNormalEx - 0.1f * vFlatCellNormal1); float3 fIceCellNormal2 = vCellNormal2; // normalize(fIceNormalEx - 0.7f * vFlatCellNormal2); float2 fLight = float2( dot(fIceNormal, -lightDir), dot(fRockNormal, -lightDir) ); float2 fRimLight = 1.0f - abs(fLight); // * saturate( dot(lightDir, v) ); fLight = min(fShadow.y * fLight, fLight); // Occlude only direct lighting (back-shadowing artifacts otherwise) fLight = saturate( 0.2f * saturate(1.0f + 2.0f * fLight) + 0.8f * saturate(fLight) ); // Ambient, Diffuse fRimLight *= fShadow.w; float3 h = normalize( v + -lightDir ); float4 hdn = float4( abs( dot( h, fIceNormalEx ) ), dot( h, fRockNormalEx ), dot( h, fIceCellNormal1 ), dot( h, fIceCellNormal2 ) ); float4 fSpecularity = fShadow.ywww * pow( saturate( hdn ), float4(8.0f, 4.0f, 4.0f, 8.0f) ); float4 fIceCrystalLight = 0.0f; float4 fRockCrystalLight = 0.0f; if(bCrystalLight) { for (int l = 0; l < lightCount; l++) { float3 toW = (i.w - lightSources[l]) * lightRanges[l]; float3 dirToW = normalize(toW); float2 lgt = 1.0f / ( 1.0f + dot(toW, toW) ); lgt *= saturate( float2( dot(-dirToW, fIceNormal) , dot(-dirToW, fRockNormal) ) ); fIceCrystalLight += lgt.x * lightColors[l]; fRockCrystalLight += lgt.y * lightColors[l]; } } // Ice float fIceSpecBoost = 0.4f * saturate( 0.5f - 0.5f * dot(lightDir, v) ); // return float2(fIceSpecBoost, 1).xxxy; float fIceSpecularity = dot( fSpecularity.xzw, float3(0.35f, 0.35f, 0.4f + fIceSpecBoost) ); // float3(0.35f, 0.35f, 0.5f) float4 fIceSpecLighting = 0.4f * tex1D(spec, 0.85f + 0.15f * fIceSpecularity) * fIceSpecularity; float4 fIceLighting = tex1D(dif, fLight.x) + fIceCrystalLight; float4 fIceRimLighting = tex1D(dif, fRimLight.x); float fIceRimFresnel = pow( saturate( 1.0f - dot(fIceNormal, v) ), 8 ) * saturate( 0.5f + 0.5f * dot(lightDir, v) ); float fIceFresnel = 0.5f + dot(0.5f / 3, float3( dot(v, fIceNormalEx), dot(v, fIceCellNormal1), dot(v, fIceCellNormal2) )); float fPlaneIceFresnel = 0.5f + 0.5f * dot(v, n); fIceFresnel = lerp(fPlaneIceFresnel, max(fIceFresnel, fPlaneIceFresnel), 0.5f); fIceFresnel = pow(fIceFresnel, 4); float4 fIceColor = lerp( float4(0.665f, 0.738f, 0.901f, 1.0f), float4(0.965f, 0.938f, 0.901f, 1.0f), fIceFresnel ); fIceSpecLighting *= fIceColor; fIceColor *= fIceLighting; fIceColor += float4(0.905f, 0.908f, 0.901f, 1.0f) * fIceRimFresnel * fIceRimLighting; fIceColor.w *= saturate( 1.0f - dot( float2(0.3f, 0.7f), fSpecularity.zw ) ); // Rock float4 fRockLighting = tex1D(dif, fLight.y) + fRockCrystalLight + 0.2f * tex1D(spec, 0.75f + 0.25f * fSpecularity.y) * fSpecularity.y; float4 fRockColor = float4(0.45f, 0.4f, 0.5f, 1.0f); fRockColor *= fRockLighting; // Compose float4 fColor = lerp( fIceColor, fRockColor, saturate(rockBlend) ); // saturate(rock) fColor += fIceSpecLighting * (rock < 0.5f); return fColor; } static float3 g_fLightFilterColor = float3(0.3f, 0.45f, 0.5f); float4 ps_main_isle(psIn i) : color0 { // Shadow AA float2 sc = i.s.xy / i.s.w; float aa = abs( tex2D(depthSampler, sc).x - i.s.z ); float2 ddaa = float2(ddx(aa), ddy(aa)); float2 aaetc = sign(-ddaa) * resolution.zw; sc += aaetc * saturate(4.f * aa); float3 t = i.w / 128; float3 n = normalize(i.n); float3 v = normalize(i.v); // Composition float shore = 0.4f * (i.w.y - 5) + tex2D_3D(waveSampler, t * 3, n).a; // shore = max(0.02, smoothstep(0.0, 1.5, shore) * (smoothstep(0.6, 0.7, n.y)) * 0.5); shore = saturate(1.0f - shore); float rock = (1 - smoothstep(0.6, 0.8, n.y)) * smoothstep(0.5, 0.7, tex2D_3D(waveSampler, t * 2, n).a); rock += (1 - smoothstep(0.4, 0.8, n.y)) * smoothstep(0.35, 0.45, tex2D_3D(waveSampler, t * 2, n).a); rock = rock / 2 + shore; float rockBlend = smoothstep( -0.7f, 1.0f, rock ); float transition = saturate( 1.0f - 5.0f * abs( 2.0f * rock - 1.0f ) ); // Surface float3 vSurfacePoint = i.w - n * rock; float3 vSurfacePointDDX = ddx(vSurfacePoint), vSurfacePointDDY = ddy(vSurfacePoint); float3 vSurfaceNormal = normalize( cross(vSurfacePointDDX, vSurfacePointDDY) ); float3 vFlatSurfaceNormal = vSurfaceNormal - n * dot(n, vSurfaceNormal); float4 fShadow = float4(0.2f, 0.4f, 0.6f, 0.8f) + float4(0.8f, 0.6f, 0.4f, 0.2f) * tex2D(shadowSampler, sc).x; float3 tc = (i.w - v) * 8; float3 vCellCoord1 = tc + 1.5f * tex3D(randomSampler, tc / 48).xyz; float3 vCellCoord2 = 1.25f * tc + 3.0f * tex3D(randomSampler, tc / 32).xyz; float3 vCellCoord1Frac = frac(vCellCoord1) * 2.0f - 1.0f; float3 vCellCoord2Frac = frac(vCellCoord2) * 2.0f - 1.0f; vCellCoord1 = floor(vCellCoord1) + sign(vCellCoord1Frac) * pow( abs(vCellCoord1Frac), 8 ) * 0.5f + 0.5f; vCellCoord2 = floor(vCellCoord2) + sign(vCellCoord2Frac) * pow( abs(vCellCoord2Frac), 8 ) * 0.5f + 0.5f; float3 vCellNormal1 = normalize( tex3D(randomSampler, vCellCoord1 / 32).xyz * 2.0f - 1.0f ); float3 vCellNormal2 = normalize( tex3D(randomSampler, vCellCoord2 / 32).xyz * 2.0f - 1.0f ); float3 vFlatCellNormal1 = vCellNormal1 - n * dot(n, vCellNormal1); float3 vFlatCellNormal2 = vCellNormal2 - n * dot(n, vCellNormal2); float3 rockN = tex2D_3D(waveSampler, t, n).xyz * (0.5 - abs( cos( (t.x + 0.1 * tex2D_3D(waveSampler, t * 2, n).a) * 20 ) ) ); float3 roughN = tex2D_3D(waveSampler, t * 10, n).xyz * 0.3 + tex2D_3D(waveSampler, t * 100, n).xyz * 0.4; float3 fIceNormal = normalize( n + 0.2f * roughN + transition * vFlatSurfaceNormal ); float3 fIceNormalEx = normalize(fIceNormal - 0.7f * n * dot(fIceNormal, n)); float3 fRockNormal = normalize( n + 0.4f * (roughN + rockN) ); float3 fRockNormalEx = normalize(fRockNormal - 0.6f * n * dot(fRockNormal, n)); float3 fIceCellNormal1 = normalize(fIceNormalEx - 0.1f * vFlatCellNormal1); float3 fIceCellNormal2 = vCellNormal2; // normalize(fIceNormalEx - 0.7f * vFlatCellNormal2); float2 fLight = float2( dot(fIceNormal, -lightDir), dot(fRockNormal, -lightDir) ); float2 fRimLight = 1.0f - abs(fLight); // * saturate( dot(lightDir, v) ); fLight = min(fShadow.y * fLight, fLight); // Occlude only direct lighting (back-shadowing artifacts otherwise) fLight = saturate( 0.2f * saturate(1.0f + 2.0f * fLight) + 0.8f * saturate(fLight) ); // Ambient, Diffuse fRimLight *= fShadow.w; float3 h = normalize( v + -lightDir ); float4 hdn = float4( abs( dot( h, fIceNormalEx ) ), dot( h, fRockNormalEx ), dot( h, fIceCellNormal1 ), dot( h, fIceCellNormal2 ) ); float4 fSpecularity = fShadow.ywww * pow( saturate( hdn ), float4(8.0f, 4.0f, 4.0f, 8.0f) ); // Ice float fIceSpecBoost = 0.4f * saturate( 0.5f - 0.5f * dot(lightDir, v) ); // return float2(fIceSpecBoost, 1).xxxy; float fIceSpecularity = dot( fSpecularity.xzw, float3(0.35f, 0.35f, 0.4f + fIceSpecBoost) ); // float3(0.35f, 0.35f, 0.5f) float4 fIceSpecLighting = 0.4f * tex1D(spec, 0.85f + 0.15f * fIceSpecularity) * fIceSpecularity; float4 fIceLighting = tex1D(dif, fLight.x); float4 fIceRimLighting = tex1D(dif, fRimLight.x); float fIceRimFresnel = pow( saturate( 1.0f - dot(fIceNormal, v) ), 8 ) * saturate( 0.5f + 0.5f * dot(lightDir, v) ); float fIceFresnel = 0.5f + dot(0.5f / 3, float3( dot(v, fIceNormalEx), dot(v, fIceCellNormal1), dot(v, fIceCellNormal2) )); float fPlaneIceFresnel = 0.5f + 0.5f * dot(v, n); fIceFresnel = lerp(fPlaneIceFresnel, max(fIceFresnel, fPlaneIceFresnel), 0.5f); fIceFresnel = pow(fIceFresnel, 4); float4 fIceColor = lerp( float4(0.665f, 0.738f, 0.901f, 1.0f), float4(0.965f, 0.938f, 0.901f, 1.0f), fIceFresnel ); fIceSpecLighting *= fIceColor; fIceColor *= fIceLighting; fIceColor += float4(0.905f, 0.908f, 0.901f, 1.0f) * fIceRimFresnel * fIceRimLighting; fIceColor.w *= saturate( 1.0f - dot( float2(0.3f, 0.7f), fSpecularity.zw ) ); // Rock float4 fRockLighting = tex1D(dif, fLight.y) + 0.2f * tex1D(spec, 0.75f + 0.25f * fSpecularity.y) * fSpecularity.y; float4 fRockColor = float4(0.45f, 0.4f, 0.5f, 1.0f); fRockColor *= fRockLighting; // Compose float4 fColor = lerp( fIceColor, fRockColor, saturate(rockBlend) ); // saturate(rock) fColor += fIceSpecLighting * (rock < 0.5f); // Fade edge fColor.xyz *= pow(g_fLightFilterColor, max(-15 - i.w.y, 0) * 0.2f); return fColor; } float4 ps_main_old(psIn i) : color0 { return ps_main_isle(i); // Shadow AA float2 sc = i.s.xy / i.s.w; float aa = abs( tex2D(depthSampler, sc).x - i.s.z ); float2 ddaa = float2(ddx(aa), ddy(aa)); float2 aaetc = sign(-ddaa) * resolution.zw; sc += aaetc * saturate(4.f * aa); float fShadow = 0.2f + 0.8f * tex2D(shadowSampler, sc); float3 n = normalize(i.n); float3 t = i.w / 128; float shore = i.w.y - 5 + tex2D_3D(waveSampler, t * 3, n).a; shore = 0.2 + max(0.02, smoothstep(0.0, 1.5, shore) * (smoothstep(0.6, 0.7, n.y)) * 0.5); float rock = 1-((1-smoothstep(0.6, 0.7, n.y)) * smoothstep(0.5, 0.7, tex2D_3D(waveSampler, t * 2, n).a)); return shore; float3 pn = n; pn += shore * tex2D_3D(waveSampler, t, n).xyz * (0.5-abs(cos((t.x + 0.1 * tex2D_3D(waveSampler, t * 2, n).a) * 20))); pn += shore * tex2D_3D(waveSampler, t * 10, n).xyz * 0.3; pn += shore * tex2D_3D(waveSampler, t * 100, n).xyz * 0.4; pn = normalize(pn); float3 pnn = normalize(pn - 0.9f * n * dot(pn, n)); float fIceSpecularity = 0.003f * pow( texCUBE(envSampler, reflect(-i.v, pnn)).g, 16.0f) * fShadow; float fSnowSpecularity = 0.3f * saturate( pow( texCUBE(envSampler, reflect(-i.v, pnn)).g, 6.0f) * fShadow ); float fLight = dot( pn, -lightDir); fLight = min(fShadow * fLight, fLight); // Occlude only direct lighting (back-shadowing artifacts otherwise) fLight = saturate( 0.2f * saturate(1.0f + 2.0f * fLight) + 0.8f * saturate(fLight) ); // Ambient, Diffuse float light = tex1D( dif, 0.3f * (1 - min(0.3, pow(dot(pn, n), 8))) + 0.7f * fLight ); float4 reflection = texCUBE(envSampler, reflect(-i.v, pn)); float4 fColor = lerp(i.c, light * float4(0.15, 0.2, 0.25, 0.0) + 0.4 * rock * smoothstep(-0.5, 0.5, pn.y), (1.0 - shore)); return float4(fColor.xyz, 1.0f); // Lighting fColor.xyz *= light; fColor += lerp(fSnowSpecularity, fIceSpecularity, rock * (1.0 - shore)); return float4(fColor.xyz, 1.0f); } float4 ps_terrain(psIn i) : color0 { return ps_main_old(i); }; float4 ps_cave(psIn i) : color0 { return ps_main(i, true); }; float4 ps_cave_ground(psIn i) : color0 { return ps_main(i, false); };