2 Commits

Author SHA1 Message Date
Cametendo
63aad06b6b Working kuwahara 2026-06-01 11:45:22 +02:00
Cametendo
aa4c1926c6 Made low-fps shader 2026-06-01 11:13:01 +02:00

View File

@@ -1,130 +1,59 @@
#version 150 #version 150
// Minecrafts eingebaute Variablen für die Bildschirmgröße
uniform float viewWidth; uniform float viewWidth;
uniform float viewHeight; uniform float viewHeight;
uniform sampler2D colortex0; uniform sampler2D colortex0;
in vec2 texCoord; in vec2 texCoord;
out vec4 fragColor; 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() { void main() {
// Exakte Pixelgröße berechnen vec2 ts = vec2(1.0 / viewWidth, 1.0 / viewHeight);
vec2 texelSize = vec2(1.0 / viewWidth, 1.0 / viewHeight);
// ========================================================================= float v_tr, v_tl, v_bl, v_br;
// QUADRANT 1: Oben-Rechts (Top-Right) 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);
float lumaSum_tr = 0.0; vec3 mean_bl = kuwahara_region(texCoord, ts, -RADIUS, 0, -RADIUS, 0, v_bl);
float lumaSquaredSum_tr = 0.0; vec3 mean_br = kuwahara_region(texCoord, ts, 0, RADIUS, -RADIUS, 0, v_br);
vec3 colorSum_tr = vec3(0.0);
for (int i = 0; i <= 16; i++) {
for (int j = 0; j <= 16; 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 / 256.0;
float mean_luma_tr = lumaSum_tr / 256.0;
float variance_tr = (lumaSquaredSum_tr / 256.0) - (mean_luma_tr * mean_luma_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 = -16; i <= 0; i++) {
for (int j = 0; j <= 16; 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 / 256.0;
float mean_luma_tl = lumaSum_tl / 256.0;
float variance_tl = (lumaSquaredSum_tl / 256.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 = -16; i <= 0; i++) {
for (int j = -16; 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 / 256.0;
float mean_luma_bl = lumaSum_bl / 256.0;
float variance_bl = (lumaSquaredSum_bl / 256.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 <= 16; i++) {
for (int j = -16; 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 / 256.0;
float mean_luma_br = lumaSum_br / 256.0;
float variance_br = (lumaSquaredSum_br / 256.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; vec3 finalColor = mean_tr;
float minVar = v_tr;
if (v_tl < minVariance) { if (v_tl < minVar) { minVar = v_tl; finalColor = mean_tl; }
minVariance = v_tl; if (v_bl < minVar) { minVar = v_bl; finalColor = mean_bl; }
finalColor = mean_tl; if (v_br < minVar) { minVar = v_br; finalColor = mean_br; }
}
if (v_bl < minVariance) {
minVariance = v_bl;
finalColor = mean_bl;
}
if (v_br < minVariance) {
minVariance = v_br;
finalColor = mean_br;
}
fragColor = vec4(finalColor, 1.0); fragColor = vec4(finalColor, 1.0);
} }