mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-10-17 02:49:19 +02:00
fix(shaders): parallax mapping reads its depth from a mip about four texels per pixel coarser, filtered bicubically where the hit is refined, so the relief no longer breaks into stalactites and the edges of stones no longer step along the texel grid of the compressed depth; it takes 16 to 64 layers by the angle of view and six steps of refinement, casts the shadows of the relief from the sun over the sun light and darkens the hollows deeper than the mean depth of the texture while lightening the tops, so the mean brightness of a surface stays the same
This commit is contained in:
@@ -36,6 +36,11 @@ float length2(vec3 v)
|
||||
return dot(v, v);
|
||||
}
|
||||
|
||||
#ifdef PARALLAX
|
||||
float parallax_occlusion = 0.0;
|
||||
float parallax_shadow = 0.0;
|
||||
#endif
|
||||
|
||||
float calc_shadow()
|
||||
{
|
||||
#if SHADOWMAP_ENABLED
|
||||
@@ -289,6 +294,9 @@ vec3 apply_lights(vec3 fragcolor, vec3 fragnormal, vec3 texturecolor, float refl
|
||||
// Sun, headlights and emission are added afterwards so they are NOT
|
||||
// attenuated by AMBIENT_SCALE - this only dims the indirect term.
|
||||
fragcolor *= AMBIENT_SCALE;
|
||||
#ifdef PARALLAX
|
||||
fragcolor *= 1.0 - parallax_occlusion;
|
||||
#endif
|
||||
|
||||
vec3 emissioncolor = vec3(emission);
|
||||
|
||||
@@ -331,6 +339,9 @@ vec3 apply_lights(vec3 fragcolor, vec3 fragnormal, vec3 texturecolor, float refl
|
||||
float shadow1 = 0.0;
|
||||
if (shadowtone < 1.0)
|
||||
shadow1 = (1.0 - shadowtone) * clamp(calc_shadow(), 0.0, 1.0);
|
||||
#ifdef PARALLAX
|
||||
shadow1 = max(shadow1, parallax_shadow);
|
||||
#endif
|
||||
|
||||
// Sun HDR scale -> SUN_DIFFUSE_SCALE (default 2.5). Controls how
|
||||
// bright sun-lit (unshaded) faces get. Lower this if surfaces in
|
||||
|
||||
@@ -1,28 +1,71 @@
|
||||
float ParallaxDepth(vec2 f_coord, float lod)
|
||||
{
|
||||
vec2 size = vec2(textureSize(normalmap, int(lod)));
|
||||
vec2 st = f_coord * size - 0.5;
|
||||
vec2 cell = floor(st);
|
||||
vec2 f = st - cell;
|
||||
vec2 w0 = (1.0 - f) * (1.0 - f) * (1.0 - f) / 6.0;
|
||||
vec2 w1 = (4.0 - 6.0 * f * f + 3.0 * f * f * f) / 6.0;
|
||||
vec2 w3 = f * f * f / 6.0;
|
||||
vec2 w2 = 1.0 - w0 - w1 - w3;
|
||||
vec2 g0 = w0 + w1;
|
||||
vec2 g1 = w2 + w3;
|
||||
vec2 h0 = (cell - 0.5 + w1 / g0) / size;
|
||||
vec2 h1 = (cell + 1.5 + w3 / g1) / size;
|
||||
return g0.y * (g0.x * textureLod(normalmap, h0, lod).b + g1.x * textureLod(normalmap, vec2(h1.x, h0.y), lod).b)
|
||||
+ g1.y * (g0.x * textureLod(normalmap, vec2(h0.x, h1.y), lod).b + g1.x * textureLod(normalmap, h1, lod).b);
|
||||
}
|
||||
|
||||
float ParallaxShadow(vec2 f_coord, float depth, float lod, float scale)
|
||||
{
|
||||
if (lights_count == 0U || depth <= 0.0) {
|
||||
return 0.0;
|
||||
}
|
||||
vec3 lightDir = normalize(transpose(f_tbn) * normalize(-lights[0].dir));
|
||||
if (lightDir.z <= 0.0) {
|
||||
return 0.0;
|
||||
}
|
||||
const int steps = 12;
|
||||
float layerDepth = depth / float(steps);
|
||||
vec2 deltaTexCoords = lightDir.xy / max(lightDir.z, 0.25) * scale * layerDepth;
|
||||
float shadow = 0.0;
|
||||
for (int i = 1; i <= steps; ++i)
|
||||
{
|
||||
float rayDepth = depth - layerDepth * float(i);
|
||||
float surface = ParallaxDepth(f_coord + deltaTexCoords * float(i), lod);
|
||||
shadow = max(shadow, (rayDepth - surface) * 12.0 * (1.0 - float(i) / float(steps + 1)));
|
||||
}
|
||||
return clamp(shadow, 0.0, 1.0);
|
||||
}
|
||||
|
||||
vec2 ParallaxMapping(vec2 f_coord, vec3 viewDir, float scale, float offset)
|
||||
{
|
||||
vec2 dx = dFdx(f_coord);
|
||||
vec2 dy = dFdy(f_coord);
|
||||
vec2 size = vec2(textureSize(normalmap, 0));
|
||||
float footprint = max(length(dFdx(f_coord) * size), length(dFdy(f_coord) * size));
|
||||
float lod = clamp(log2(max(footprint, 1e-4)) + 2.0, 0.0, log2(max(size.x, size.y)));
|
||||
float fade = (1.0 - smoothstep(60.0, 100.0, length(f_pos.xyz))) * smoothstep(0.0, 0.1, viewDir.z);
|
||||
if (fade <= 0.0) {
|
||||
return f_coord;
|
||||
}
|
||||
float meanDepth = textureLod(normalmap, f_coord, log2(max(size.x, size.y))).b;
|
||||
|
||||
#if EXTRAEFFECTS_ENABLED
|
||||
const float minLayers = 8.0;
|
||||
const float maxLayers = 32.0;
|
||||
const float minLayers = 16.0;
|
||||
const float maxLayers = 64.0;
|
||||
float numLayers = mix(maxLayers, minLayers, clamp(viewDir.z, 0.0, 1.0));
|
||||
float layerDepth = 1.0 / numLayers;
|
||||
vec2 deltaTexCoords = viewDir.xy * scale * fade / numLayers;
|
||||
vec2 currentTexCoords = f_coord;
|
||||
float currentLayerDepth = 0.0;
|
||||
float currentDepthMapValue = textureGrad(normalmap, currentTexCoords, dx, dy).b;
|
||||
for (int i = 0; i < 40 && currentLayerDepth < currentDepthMapValue; ++i)
|
||||
float currentDepthMapValue = textureLod(normalmap, currentTexCoords, lod).b;
|
||||
for (int i = 0; i < 100 && currentLayerDepth < currentDepthMapValue; ++i)
|
||||
{
|
||||
currentTexCoords -= deltaTexCoords;
|
||||
currentLayerDepth += layerDepth;
|
||||
currentDepthMapValue = textureGrad(normalmap, currentTexCoords, dx, dy).b;
|
||||
currentDepthMapValue = textureLod(normalmap, currentTexCoords, lod).b;
|
||||
}
|
||||
for (int i = 0; i < 5; ++i)
|
||||
currentDepthMapValue = ParallaxDepth(currentTexCoords, lod);
|
||||
for (int i = 0; i < 6; ++i)
|
||||
{
|
||||
deltaTexCoords *= 0.5;
|
||||
layerDepth *= 0.5;
|
||||
@@ -34,11 +77,14 @@ vec2 ParallaxMapping(vec2 f_coord, vec3 viewDir, float scale, float offset)
|
||||
currentTexCoords += deltaTexCoords;
|
||||
currentLayerDepth -= layerDepth;
|
||||
}
|
||||
currentDepthMapValue = textureGrad(normalmap, currentTexCoords, dx, dy).b;
|
||||
currentDepthMapValue = ParallaxDepth(currentTexCoords, lod);
|
||||
}
|
||||
parallax_occlusion = clamp(0.8 * (currentLayerDepth - meanDepth), -0.3, 0.6) * fade;
|
||||
parallax_shadow = ParallaxShadow(currentTexCoords, currentLayerDepth, lod, scale * fade) * fade;
|
||||
return currentTexCoords;
|
||||
#else
|
||||
float height = textureGrad(normalmap, f_coord, dx, dy).b;
|
||||
float height = ParallaxDepth(f_coord, lod);
|
||||
parallax_occlusion = clamp(0.8 * (height - meanDepth), -0.3, 0.6) * fade;
|
||||
vec2 p = viewDir.xy / max(viewDir.z, 0.2) * (height * (scale - offset) * 0.2 * fade);
|
||||
return f_coord - p;
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user