@@ -344,16 +344,36 @@ VS_OUT FixedFuncVS( VS_IN In )
344
344
return Out;
345
345
}
346
346
347
- bool IsExperimentalShader () {
347
+ bool ShaderUsesTerrainInfoTexture () {
348
348
// The tile value basically says how often the texture gets repeated on the map.
349
349
// A value less than one doesn't make sense under normal conditions, so it is
350
350
// relatively save to use it as our switch.
351
+ // We use the upper layer slot to store the terrain info texture, so we don't need
352
+ // the tile value for anything else.
351
353
352
- // in order to trigger this you can set the albedo scale to be bigger than the map
353
- // size. Use the value 10000 to be safe for any map
354
+ // In order to trigger this you need to set the albedo scale to be bigger than the
355
+ // map size in the editor . Use the value 10000 to be safe for any map
354
356
return UpperAlbedoTile.x < 1.0 ;
355
357
}
356
358
359
+ bool ShaderUsesPbrRendering () {
360
+ // The tile value basically says how often the texture gets repeated on the map.
361
+ // A value less than one doesn't make sense under normal conditions, so it is
362
+ // relatively save to use it as our switch.
363
+ // We use the stratum 7 normal slot to store the roughness texture, so we don't need
364
+ // the tile value for anything else.
365
+
366
+ // In order to trigger this you need to set the normal scale to be bigger than the
367
+ // map size in the editor. Use the value 10000 to be safe for any map
368
+ return Stratum7NormalTile.x < 1.0 ;
369
+ }
370
+
371
+ bool MapUsesAdvancedWater () {
372
+ // LightingMultiplier is one of the few variables that is driven by the map,
373
+ // but accessible by the mesh shader.
374
+ return LightingMultiplier > 2.1 ;
375
+ }
376
+
357
377
// sample a texture that is another buffer the same size as the one
358
378
// we are rendering into and with the viewport setup the same way.
359
379
float4 SampleScreen (sampler inSampler, float4 inTex)
@@ -388,35 +408,29 @@ float ComputeShadow( float4 vShadowCoord )
388
408
return tex2D ( ShadowSampler, vShadowCoord ).g;
389
409
}
390
410
391
- // apply the water color
392
- float3 ApplyWaterColor (float terrainHeight, float waterDepth, float3 color)
411
+ float3 ApplyWaterColor (float3 viewDirection, float terrainHeight, float waterDepth, float3 color)
393
412
{
394
413
if (waterDepth > 0 ) {
395
414
// With this extra check we get rid of unwanted coloration on steep cliffs when zoomed in,
396
415
// but we prevent that terrain tesselation swallows too much of the water when zoomed out
397
416
float opacity = saturate (smoothstep (10 , 200 , CameraPosition.y - WaterElevation) + step (terrainHeight, WaterElevation));
398
- float4 waterColor = tex1D (WaterRampSampler, waterDepth);
399
- color = lerp (color.xyz, waterColor.rgb, waterColor.a * opacity);
400
- }
401
- return color;
402
- }
403
-
404
- float3 ApplyWaterColorExponentially (float3 viewDirection, float terrainHeight, float waterDepth, float3 color)
405
- {
406
- if (waterDepth > 0 ) {
407
- float opacity = saturate (smoothstep (10 , 200 , CameraPosition.y - WaterElevation) + step (terrainHeight, WaterElevation));
408
- float3 up = float3 (0 ,1 ,0 );
409
- // this is the length that the light travels underwater back to the camera
410
- float oneOverCosV = 1 / max (dot (up, normalize (viewDirection)), 0.0001 );
411
- // Light gets absorbed exponentially,
412
- // to simplify, we assume that the light enters vertically into the water.
413
- // We need to multiply by 2 to reach 98% absorption as the waterDepth can't go over 1.
414
- float waterAbsorption = 1 - saturate (exp (-waterDepth * 2 * (1 + oneOverCosV)));
415
- // darken the color first to simulate the light absorption on the way in and out
416
- color *= 1 - waterAbsorption * opacity;
417
- // lerp in the watercolor to simulate the scattered light from the dirty water
418
- float4 waterColor = tex1D (WaterRampSampler, waterAbsorption);
419
- color = lerp (color, waterColor.rgb, waterAbsorption * opacity);
417
+ if (MapUsesAdvancedWater ()) {
418
+ float3 up = float3 (0 ,1 ,0 );
419
+ // this is the length that the light travels underwater back to the camera
420
+ float oneOverCosV = 1 / max (dot (up, normalize (viewDirection)), 0.0001 );
421
+ // Light gets absorbed exponentially,
422
+ // to simplify, we assume that the light enters vertically into the water.
423
+ // We need to multiply by 2 to reach 98% absorption as the waterDepth can't go over 1.
424
+ float waterAbsorption = 1 - saturate (exp (-waterDepth * 2 * (1 + oneOverCosV)));
425
+ // darken the color first to simulate the light absorption on the way in and out
426
+ color *= 1 - waterAbsorption * opacity;
427
+ // lerp in the watercolor to simulate the scattered light from the dirty water
428
+ float4 waterColor = tex1D (WaterRampSampler, waterAbsorption);
429
+ color = lerp (color, waterColor.rgb, waterAbsorption * opacity);
430
+ } else {
431
+ float4 waterColor = tex1D (WaterRampSampler, waterDepth);
432
+ color = lerp (color, waterColor.rgb, waterColor.a * opacity);
433
+ }
420
434
}
421
435
return color;
422
436
}
@@ -427,10 +441,10 @@ float4 CalculateLighting( float3 inNormal, float3 worldTerrain, float3 inAlbedo,
427
441
float4 color = float4 ( 0 , 0 , 0 , 0 );
428
442
429
443
float shadow = ( inShadows && ( 1 == ShadowsEnabled ) ) ? ComputeShadow (shadowCoords) : 1 ;
430
- if (IsExperimentalShader ()) {
444
+ if (ShaderUsesTerrainInfoTexture ()) {
431
445
float3 position = TerrainScale * worldTerrain;
432
- float mapShadow = tex2D (UpperAlbedoSampler, position.xy).w;
433
- shadow = shadow * mapShadow ;
446
+ float terrainShadow = tex2D (UpperAlbedoSampler, position.xy).w;
447
+ shadow = shadow * terrainShadow ;
434
448
}
435
449
436
450
// calculate some specular
@@ -444,11 +458,7 @@ float4 CalculateLighting( float3 inNormal, float3 worldTerrain, float3 inAlbedo,
444
458
light = LightingMultiplier * light + ShadowFillColor * ( 1 - light );
445
459
color.rgb = light * inAlbedo;
446
460
447
- if (IsExperimentalShader ()) {
448
- color.rgb = ApplyWaterColorExponentially (-viewDirection, worldTerrain.z, waterDepth, color);
449
- } else {
450
- color.rgb = ApplyWaterColor (worldTerrain.z, waterDepth, color);
451
- }
461
+ color.rgb = ApplyWaterColor (-viewDirection, worldTerrain.z, waterDepth, color);
452
462
453
463
color.a = 0.01f + (specular*SpecularColor.w);
454
464
return color;
@@ -494,14 +504,14 @@ float GeometrySmith(float3 n, float nDotV, float3 l, float roughness)
494
504
return gs1 * gs2;
495
505
}
496
506
497
- float3 PBR (VS_OUTPUT inV, float4 position, float3 albedo, float3 n, float roughness, float waterDepth) {
507
+ float3 PBR (VS_OUTPUT inV, float3 albedo, float3 n, float roughness, float waterDepth) {
498
508
// See https://blog.selfshadow.com/publications/s2013-shading-course/
499
509
500
510
float shadow = 1 ;
501
511
if (ShadowsEnabled == 1 ) {
502
- float mapShadow = tex2D (UpperAlbedoSampler, position.xy ).w; // 1 where sun is, 0 where shadow is
512
+ float terrainShadow = tex2D (UpperAlbedoSampler, TerrainScale * inV.mTexWT ).w; // 1 where sun is, 0 where shadow is
503
513
shadow = tex2D (ShadowSampler, inV.mShadow.xy).g; // 1 where sun is, 0 where shadow is
504
- shadow *= mapShadow ;
514
+ shadow *= terrainShadow ;
505
515
}
506
516
507
517
float facingSpecular = 0.04 ;
@@ -839,7 +849,7 @@ float4 TerrainBasisPS( VS_OUTPUT inV ) : COLOR
839
849
float4 TerrainBasisPSBiCubic ( VS_OUTPUT inV ) : COLOR
840
850
{
841
851
float4 result;
842
- if (IsExperimentalShader ()) {
852
+ if (ShaderUsesTerrainInfoTexture ()) {
843
853
float4 position = TerrainScale * inV.mTexWT;
844
854
result = (float4 (1 , 1 , tex2D (UpperAlbedoSampler, position.xy).xy));
845
855
} else {
@@ -959,7 +969,7 @@ float4 TerrainAlbedoXP( VS_OUTPUT pixel) : COLOR
959
969
albedo.rgb = light * ( albedo.rgb + specular.rgb );
960
970
961
971
float waterDepth = tex2D (UtilitySamplerC,pixel.mTexWT*TerrainScale).g;
962
- albedo.rgb = ApplyWaterColor (pixel.mTexWT.z, waterDepth, albedo.rgb);
972
+ albedo.rgb = ApplyWaterColor (-pixel.mViewDirection, pixel.mTexWT.z, waterDepth, albedo.rgb);
963
973
964
974
return float4 (albedo.rgb, 0.01f );
965
975
}
@@ -1339,7 +1349,13 @@ float4 DecalsPS( VS_OUTPUT inV, uniform bool inShadows) : COLOR
1339
1349
1340
1350
float waterDepth = tex2Dproj (UtilitySamplerC, inV.mTexWT * TerrainScale).g;
1341
1351
1342
- float3 color = CalculateLighting (normal, inV.mTexWT.xyz, decalAlbedo.xyz, decalSpec.r, waterDepth, inV.mShadow, inShadows).xyz;
1352
+ float3 color;
1353
+ // We want the decals to behave consistently with the rest of the ground
1354
+ if (ShaderUsesPbrRendering ()) {
1355
+ color = PBR (inV, decalAlbedo.rgb, normal, 0.9 * (1 -decalSpec.r), waterDepth);
1356
+ } else {
1357
+ color = CalculateLighting (normal, inV.mTexWT.xyz, decalAlbedo.xyz, decalSpec.r, waterDepth, inV.mShadow, inShadows).xyz;
1358
+ }
1343
1359
1344
1360
return float4 (color.rgb, decalAlbedo.w * decalMask.w * DecalAlpha);
1345
1361
}
@@ -2021,11 +2037,11 @@ float4 TerrainPBRAlbedoPS ( VS_OUTPUT inV) : COLOR
2021
2037
float roughness = saturate (albedo.a * mask1.w * 2 + 0.01 );
2022
2038
2023
2039
float waterDepth = tex2D (UpperAlbedoSampler, position.xy).b;
2024
- float3 color = PBR (inV, position, albedo, normal, roughness, waterDepth);
2025
- color = ApplyWaterColorExponentially (-1 * inV.mViewDirection, inV.mTexWT.z, waterDepth, color);
2040
+ float3 color = PBR (inV, albedo, normal, roughness, waterDepth);
2041
+ color = ApplyWaterColor (-1 * inV.mViewDirection, inV.mTexWT.z, waterDepth, color);
2026
2042
2027
2043
return float4 (color, 0.01f );
2028
- // SpecularColor.ba, LowerNormalTile, Stratum7AlbedoTile and Stratum7NormalTile are unused now
2044
+ // SpecularColor.ba, LowerNormalTile and Stratum7AlbedoTile are unused now
2029
2045
// Candidates for configurable values are the rotation matrix values
2030
2046
}
2031
2047
@@ -2169,14 +2185,14 @@ float4 Terrain001AlbedoPS ( VS_OUTPUT inV, uniform bool halfRange ) : COLOR
2169
2185
2170
2186
// x = normals-x
2171
2187
// y = normals-z
2172
- // z = unused
2188
+ // z = water depth
2173
2189
// w = shadows
2174
- float4 utility = tex2D (UpperAlbedoSampler, coordinates.xy);
2175
- float mapShadow = utility .w;
2190
+ float4 terrainInfo = tex2D (UpperAlbedoSampler, coordinates.xy);
2191
+ float terrainShadow = terrainInfo .w;
2176
2192
2177
2193
// disable shadows when game settings tell us to
2178
2194
if (0 == ShadowsEnabled) {
2179
- mapShadow = 1.0f ;
2195
+ terrainShadow = 1.0f ;
2180
2196
}
2181
2197
2182
2198
// sample the albedo's
@@ -2203,7 +2219,7 @@ float4 Terrain001AlbedoPS ( VS_OUTPUT inV, uniform bool halfRange ) : COLOR
2203
2219
2204
2220
// compute the shadows, combining the baked and dynamic shadows
2205
2221
float shadow = tex2D (ShadowSampler, inV.mShadow.xy).g; // 1 where sun is, 0 where shadow is
2206
- shadow = shadow * mapShadow ;
2222
+ shadow = shadow * terrainShadow ;
2207
2223
2208
2224
// normalize the pre-computed normal
2209
2225
float3 normal = normalize (2 * SampleScreen (NormalSampler,inV.mTexSS).xyz - 1 );
@@ -2222,13 +2238,13 @@ float4 Terrain001AlbedoPS ( VS_OUTPUT inV, uniform bool halfRange ) : COLOR
2222
2238
2223
2239
// compute water ramp intensity
2224
2240
float waterDepth = tex2Dproj (UtilitySamplerC, coordinates).g;
2225
- albedo.rgb = ApplyWaterColorExponentially (-1 * inV.mViewDirection, inV.mTexWT.z, waterDepth, albedo.rgb);
2241
+ albedo.rgb = ApplyWaterColor (-1 * inV.mViewDirection, inV.mTexWT.z, waterDepth, albedo.rgb);
2226
2242
2227
2243
return float4 (albedo.rgb, 0.01f );
2228
2244
}
2229
2245
2230
2246
/* # Similar to TTerrainXP, but upperAlbedo is used for map-wide #
2231
- # textures and we use better water color calculations. #
2247
+ # textures. #
2232
2248
# It is designed to be a drop-in replacement for TTerrainXP. # */
2233
2249
technique Terrain001 <
2234
2250
string usage = "composite" ;
@@ -2395,14 +2411,14 @@ float4 Terrain003AlbedoPS ( VS_OUTPUT inV, uniform bool halfRange ) : COLOR
2395
2411
2396
2412
// x = normals-x
2397
2413
// y = normals-z
2398
- // z = unused
2414
+ // z = water depth
2399
2415
// w = shadows
2400
- float4 utility01 = tex2D (UpperAlbedoSampler, coordinates.xy);
2401
- float mapShadow = utility01 .w;
2416
+ float4 terrainInfo = tex2D (UpperAlbedoSampler, coordinates.xy);
2417
+ float terrainShadow = terrainInfo .w;
2402
2418
2403
2419
// disable shadows when game settings tell us to
2404
2420
if (0 == ShadowsEnabled) {
2405
- mapShadow = 1.0f ;
2421
+ terrainShadow = 1.0f ;
2406
2422
}
2407
2423
2408
2424
// x = specular
@@ -2437,7 +2453,7 @@ float4 Terrain003AlbedoPS ( VS_OUTPUT inV, uniform bool halfRange ) : COLOR
2437
2453
2438
2454
// compute the shadows, combining the baked and dynamic shadows
2439
2455
float shadow = tex2D (ShadowSampler, inV.mShadow.xy).g;
2440
- shadow = shadow * mapShadow ;
2456
+ shadow = shadow * terrainShadow ;
2441
2457
2442
2458
// normalize the pre-computed normal
2443
2459
float3 normal = normalize (2 * SampleScreen (NormalSampler,inV.mTexSS).xyz - 1 );
@@ -2456,7 +2472,7 @@ float4 Terrain003AlbedoPS ( VS_OUTPUT inV, uniform bool halfRange ) : COLOR
2456
2472
2457
2473
// compute water ramp intensity
2458
2474
float waterDepth = tex2D (UtilitySamplerC, coordinates).g;
2459
- albedo.rgb = ApplyWaterColorExponentially (-1 * inV.mViewDirection, inV.mTexWT.z, waterDepth, albedo.rgb);
2475
+ albedo.rgb = ApplyWaterColor (-1 * inV.mViewDirection, inV.mTexWT.z, waterDepth, albedo.rgb);
2460
2476
2461
2477
return float4 (albedo.rgb, 0.01f );
2462
2478
}
@@ -2615,8 +2631,8 @@ float4 Terrain101AlbedoPS ( VS_OUTPUT inV, uniform bool halfRange ) : COLOR
2615
2631
float roughness = saturate (albedo.a * mask1.w * 2 + 0.01 );
2616
2632
2617
2633
float waterDepth = tex2D (UpperAlbedoSampler, position.xy).b;
2618
- float3 color = PBR (inV, position, albedo, normal, roughness, waterDepth);
2619
- color = ApplyWaterColorExponentially (-1 * inV.mViewDirection, inV.mTexWT.z, waterDepth, color);
2634
+ float3 color = PBR (inV, albedo, normal, roughness, waterDepth);
2635
+ color = ApplyWaterColor (-1 * inV.mViewDirection, inV.mTexWT.z, waterDepth, color);
2620
2636
2621
2637
return float4 (color, 0.01f );
2622
2638
}
@@ -2800,8 +2816,8 @@ float4 Terrain301AlbedoPS ( VS_OUTPUT inV, uniform bool halfRange ) : COLOR
2800
2816
float roughness = saturate (albedo.a * mask1.w * 2 + 0.01 );
2801
2817
2802
2818
float waterDepth = tex2D (UpperAlbedoSampler, position.xy).b;
2803
- float3 color = PBR (inV, position, albedo, normal, roughness, waterDepth);
2804
- color = ApplyWaterColorExponentially (-1 * inV.mViewDirection, inV.mTexWT.z, waterDepth, color);
2819
+ float3 color = PBR (inV, albedo, normal, roughness, waterDepth);
2820
+ color = ApplyWaterColor (-1 * inV.mViewDirection, inV.mTexWT.z, waterDepth, color);
2805
2821
2806
2822
return float4 (color, 0.01f );
2807
2823
}
0 commit comments