From d50ad2475c45de0bcf14a2476b194de7322a35f7 Mon Sep 17 00:00:00 2001 From: UjinT34 <41110182+UjinT34@users.noreply.github.com> Date: Sat, 18 Apr 2026 13:35:16 +0300 Subject: renderer: simplify shadows (#14047) --- src/render/shaders/glsl/rounding.glsl | 6 +++- src/render/shaders/glsl/shadow.frag | 3 +- src/render/shaders/glsl/shadow.glsl | 55 ++++++++++++++++++++++++++++------- 3 files changed, 52 insertions(+), 12 deletions(-) (limited to 'src/render/shaders') diff --git a/src/render/shaders/glsl/rounding.glsl b/src/render/shaders/glsl/rounding.glsl index 61a0bb9c..64c6bcb9 100644 --- a/src/render/shaders/glsl/rounding.glsl +++ b/src/render/shaders/glsl/rounding.glsl @@ -4,6 +4,10 @@ #define M_PI 3.1415926535897932384626433832795 #define SMOOTHING_CONSTANT (M_PI / 5.34665792551) +float distanceWithRounding(vec2 coords, float roundingPower) { + return pow(pow(coords.x, roundingPower) + pow(coords.y, roundingPower), 1.0 / roundingPower); +} + vec4 rounding(vec4 color, float radius, float roundingPower, vec2 topLeft, vec2 fullSize) { vec2 pixCoord = vec2(gl_FragCoord); pixCoord -= topLeft + fullSize * 0.5; @@ -12,7 +16,7 @@ vec4 rounding(vec4 color, float radius, float roundingPower, vec2 topLeft, vec2 pixCoord += vec2(1.0, 1.0) / fullSize; // center the pix don't make it top-left if (pixCoord.x + pixCoord.y > radius) { - float dist = pow(pow(pixCoord.x, roundingPower) + pow(pixCoord.y, roundingPower), 1.0 / roundingPower); + float dist = distanceWithRounding(pixCoord, roundingPower); if (dist > radius + SMOOTHING_CONSTANT) discard; diff --git a/src/render/shaders/glsl/shadow.frag b/src/render/shaders/glsl/shadow.frag index 5ba3d879..19f87348 100644 --- a/src/render/shaders/glsl/shadow.frag +++ b/src/render/shaders/glsl/shadow.frag @@ -19,6 +19,7 @@ uniform float radius; uniform float roundingPower; uniform float range; uniform float shadowPower; +uniform float thick; #if USE_CM #include "cm_helpers.glsl" @@ -38,7 +39,7 @@ void main() { #else fragColor = #endif - getShadow(pixColor, v_texcoord, radius, roundingPower, topLeft, fullSize, range, shadowPower, bottomRight + getShadow(pixColor, v_texcoord, radius, roundingPower, topLeft, fullSize, range, shadowPower, bottomRight, thick #if USE_CM , sourceTF, targetTF, convertMatrix, srcTFRange, dstTFRange diff --git a/src/render/shaders/glsl/shadow.glsl b/src/render/shaders/glsl/shadow.glsl index 265dba00..6bc92572 100644 --- a/src/render/shaders/glsl/shadow.glsl +++ b/src/render/shaders/glsl/shadow.glsl @@ -6,6 +6,7 @@ #define SHADOW_GLSL #include "cm_helpers.glsl" +#include "rounding.glsl" float pixAlphaRoundedDistance(float distanceToCorner, float radius, float range, float shadowPower) { if (distanceToCorner > radius) { @@ -28,7 +29,8 @@ vec4[2] #else vec4 #endif - getShadow(vec4 pixColor, vec2 v_texcoord, float radius, float roundingPower, vec2 topLeft, vec2 fullSize, float range, float shadowPower, vec2 bottomRight + getShadow(vec4 pixColor, vec2 v_texcoord, float borderRadius, float roundingPower, vec2 topLeft, vec2 fullSize, float range, float shadowPower, vec2 bottomRight, + float decoWidth #if USE_CM , int sourceTF, int targetTF, mat3 convertMatrix, vec2 srcTFRange, vec2 dstTFRange @@ -51,6 +53,7 @@ vec4 #endif #endif ) { + float radius = range + borderRadius; float originalAlpha = pixColor[3]; bool done = false; @@ -58,29 +61,50 @@ vec4 vec2 pixCoord = fullSize * v_texcoord; // ok, now we check the distance to a border. - + // corners if (pixCoord[0] < topLeft[0]) { if (pixCoord[1] < topLeft[1]) { // top left - pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - topLeft, roundingPower), radius, range, shadowPower); - done = true; + float distance = distanceWithRounding(vec2(topLeft.x - pixCoord.x, topLeft.y - pixCoord.y), roundingPower); + if (borderRadius > 0.0 && distance < decoWidth) { + pixColor[3] = 0.0; + } else { + pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - topLeft, roundingPower), radius, range, shadowPower); + } + done = true; } else if (pixCoord[1] > bottomRight[1]) { // bottom left - pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - vec2(topLeft[0], bottomRight[1]), roundingPower), radius, range, shadowPower); - done = true; + float distance = distanceWithRounding(vec2(topLeft.x - pixCoord.x, pixCoord.y - bottomRight.y), roundingPower); + if (borderRadius > 0.0 && distance < decoWidth) { + pixColor[3] = 0.0; + } else { + pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - vec2(topLeft[0], bottomRight[1]), roundingPower), radius, range, shadowPower); + } + done = true; } } else if (pixCoord[0] > bottomRight[0]) { if (pixCoord[1] < topLeft[1]) { // top right - pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - vec2(bottomRight[0], topLeft[1]), roundingPower), radius, range, shadowPower); - done = true; + float distance = distanceWithRounding(vec2(pixCoord.x - bottomRight.x, topLeft.y - pixCoord.y), roundingPower); + if (borderRadius > 0.0 && distance < decoWidth) { + pixColor[3] = 0.0; + } else { + pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - vec2(bottomRight[0], topLeft[1]), roundingPower), radius, range, shadowPower); + } + done = true; } else if (pixCoord[1] > bottomRight[1]) { // bottom right - pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - bottomRight, roundingPower), radius, range, shadowPower); - done = true; + float distance = distanceWithRounding(vec2(pixCoord.x - bottomRight.x, pixCoord.y - bottomRight.y), roundingPower); + if (borderRadius > 0.0 && distance < decoWidth) { + pixColor[3] = 0.0; + } else { + pixColor[3] = pixColor[3] * pixAlphaRoundedDistance(modifiedLength(pixCoord - bottomRight, roundingPower), radius, range, shadowPower); + } + done = true; } } + // edges if (!done) { // distance to all straight bb borders float distanceT = pixCoord[1]; @@ -92,13 +116,24 @@ vec4 float smallest = min(min(distanceT, distanceB), min(distanceL, distanceR)); if (smallest < range) { + // between border and max shadow distance pixColor[3] = pixColor[3] * pow((smallest / range), shadowPower); + } else { + // inside border or window + pixColor[3] = 0.0; } } if (pixColor[3] == 0.0) { discard; +#if USE_MIRROR + vec4[2] pixColors; + pixColors[0] = pixColor; + pixColors[1] = pixColor; + return pixColors; +#else return pixColor; +#endif } // premultiply -- cgit v1.2.3