diff --git a/shaders/final.fsh b/shaders/final.fsh index b778bfe..c4209fe 100644 --- a/shaders/final.fsh +++ b/shaders/final.fsh @@ -1,130 +1,59 @@ #version 150 -// Minecrafts eingebaute Variablen für die Bildschirmgröße uniform float viewWidth; uniform float viewHeight; - uniform sampler2D colortex0; + in vec2 texCoord; out vec4 fragColor; +// Tune these to trade quality vs performance: +// RADIUS 36, STEP 1 → 5476 samples/pixel (original, ~9fps) +// RADIUS 36, STEP 3 → 676 samples/pixel (~8x faster) +// RADIUS 36, STEP 4 → 400 samples/pixel (~14x faster) +// RADIUS 16, STEP 2 → 324 samples/pixel (smaller brush, fast) +#define RADIUS 36 +#define STEP 3 + +vec3 kuwahara_region(vec2 uv, vec2 ts, int x0, int x1, int y0, int y1, out float outVariance) { + vec3 colorSum = vec3(0.0); + float lumaSum = 0.0; + float lumaSqSum = 0.0; + float count = 0.0; + + for (int i = x0; i <= x1; i += STEP) { + for (int j = y0; j <= y1; j += STEP) { + vec3 c = texture(colortex0, uv + vec2(float(i), float(j)) * ts).rgb; + float luma = dot(c, vec3(0.299, 0.587, 0.114)); + colorSum += c; + lumaSum += luma; + lumaSqSum += luma * luma; + count += 1.0; + } + } + + vec3 mean = colorSum / count; + float meanLuma = lumaSum / count; + float variance = (lumaSqSum / count) - (meanLuma * meanLuma); + outVariance = variance * variance; // square for harder selection + return mean; +} + void main() { - // Exakte Pixelgröße berechnen - vec2 texelSize = vec2(1.0 / viewWidth, 1.0 / viewHeight); + vec2 ts = vec2(1.0 / viewWidth, 1.0 / viewHeight); - // ========================================================================= - // QUADRANT 1: Oben-Rechts (Top-Right) - // ========================================================================= - float lumaSum_tr = 0.0; - float lumaSquaredSum_tr = 0.0; - vec3 colorSum_tr = vec3(0.0); + float v_tr, v_tl, v_bl, v_br; + vec3 mean_tr = kuwahara_region(texCoord, ts, 0, RADIUS, 0, RADIUS, v_tr); + vec3 mean_tl = kuwahara_region(texCoord, ts, -RADIUS, 0, 0, RADIUS, v_tl); + vec3 mean_bl = kuwahara_region(texCoord, ts, -RADIUS, 0, -RADIUS, 0, v_bl); + vec3 mean_br = kuwahara_region(texCoord, ts, 0, RADIUS, -RADIUS, 0, v_br); - for (int i = 0; i <= 36; i++) { - for (int j = 0; j <= 36; j++) { - vec2 offset = vec2(float(i), float(j)) * texelSize; - vec3 neighborColor = texture(colortex0, texCoord + offset).rgb; - float luma = dot(neighborColor, vec3(0.299, 0.587, 0.114)); - - colorSum_tr += neighborColor; - lumaSum_tr += luma; - lumaSquaredSum_tr += (luma * luma); - } - } - vec3 mean_tr = colorSum_tr / 1296.0; - float mean_luma_tr = lumaSum_tr / 1296.0; - float variance_tr = (lumaSquaredSum_tr / 1296.0) - (mean_luma_tr * mean_luma_tr); + vec3 finalColor = mean_tr; + float minVar = v_tr; - // ========================================================================= - // QUADRANT 2: Oben-Links (Top-Left) - // ========================================================================= - float lumaSum_tl = 0.0; - float lumaSquaredSum_tl = 0.0; - vec3 colorSum_tl = vec3(0.0); - - for (int i = -36; i <= 0; i++) { - for (int j = 0; j <= 36; j++) { - vec2 offset = vec2(float(i), float(j)) * texelSize; - vec3 neighborColor = texture(colortex0, texCoord + offset).rgb; - float luma = dot(neighborColor, vec3(0.299, 0.587, 0.114)); - - colorSum_tl += neighborColor; - lumaSum_tl += luma; - lumaSquaredSum_tl += (luma * luma); - } - } - vec3 mean_tl = colorSum_tl / 1296.0; - float mean_luma_tl = lumaSum_tl / 1296.0; - float variance_tl = (lumaSquaredSum_tl / 1296.0) - (mean_luma_tl * mean_luma_tl); - - // ========================================================================= - // QUADRANT 3: Unten-Links (Bottom-Left) - // ========================================================================= - float lumaSum_bl = 0.0; - float lumaSquaredSum_bl = 0.0; - vec3 colorSum_bl = vec3(0.0); - - for (int i = -36; i <= 0; i++) { - for (int j = -36; j <= 0; j++) { - vec2 offset = vec2(float(i), float(j)) * texelSize; - vec3 neighborColor = texture(colortex0, texCoord + offset).rgb; - float luma = dot(neighborColor, vec3(0.299, 0.587, 0.114)); - - colorSum_bl += neighborColor; - lumaSum_bl += luma; - lumaSquaredSum_bl += (luma * luma); - } - } - vec3 mean_bl = colorSum_bl / 1296.0; - float mean_luma_bl = lumaSum_bl / 1296.0; - float variance_bl = (lumaSquaredSum_bl / 1296.0) - (mean_luma_bl * mean_luma_bl); - - // ========================================================================= - // QUADRANT 4: Unten-Rechts (Bottom-Right) - // ========================================================================= - float lumaSum_br = 0.0; - float lumaSquaredSum_br = 0.0; - vec3 colorSum_br = vec3(0.0); - - for (int i = 0; i <= 36; i++) { - for (int j = -36; j <= 0; j++) { - vec2 offset = vec2(float(i), float(j)) * texelSize; - vec3 neighborColor = texture(colortex0, texCoord + offset).rgb; - float luma = dot(neighborColor, vec3(0.299, 0.587, 0.114)); - - colorSum_br += neighborColor; - lumaSum_br += luma; - lumaSquaredSum_br += (luma * luma); - } - } - vec3 mean_br = colorSum_br / 1296.0; - float mean_luma_br = lumaSum_br / 1296.0; - float variance_br = (lumaSquaredSum_br / 1296.0) - (mean_luma_br * mean_luma_br); - - // ========================================================================= - // FINALE AUSWAHL: Den Quadranten mit der NIEDRIGSTEN Varianz finden - // ========================================================================= -// 1. Varianzen direkt für den harten Effekt quadrieren - float v_tr = variance_tr * variance_tr; - float v_tl = variance_tl * variance_tl; - float v_bl = variance_bl * variance_bl; - float v_br = variance_br * variance_br; - - // 2. Sauberer Vergleich der quadrierten Werte - float minVariance = v_tr; - vec3 finalColor = mean_tr; - - if (v_tl < minVariance) { - minVariance = v_tl; - finalColor = mean_tl; - } - if (v_bl < minVariance) { - minVariance = v_bl; - finalColor = mean_bl; - } - if (v_br < minVariance) { - minVariance = v_br; - finalColor = mean_br; - } + if (v_tl < minVar) { minVar = v_tl; finalColor = mean_tl; } + if (v_bl < minVar) { minVar = v_bl; finalColor = mean_bl; } + if (v_br < minVar) { minVar = v_br; finalColor = mean_br; } fragColor = vec4(finalColor, 1.0); -} \ No newline at end of file +}