mirror of
https://github.com/comfyanonymous/ComfyUI.git
synced 2026-02-02 01:30:18 +08:00
shader nit iteration
This commit is contained in:
parent
0050b66a0b
commit
292a5918f4
@ -8,14 +8,15 @@ uniform float u_float1; // Contrast slider -100..100
|
||||
in vec2 v_texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
const float EPSILON = 1e-5;
|
||||
const float MID_GRAY = 0.18; // 18% reflectance
|
||||
|
||||
// sRGB gamma 2.2 approximation
|
||||
vec3 srgbToLinear(vec3 c) {
|
||||
return pow(c, vec3(2.2));
|
||||
return pow(max(c, 0.0), vec3(2.2));
|
||||
}
|
||||
|
||||
vec3 linearToSrgb(vec3 c) {
|
||||
return pow(c, vec3(1.0/2.2));
|
||||
return pow(max(c, 0.0), vec3(1.0/2.2));
|
||||
}
|
||||
|
||||
float mapBrightness(float b) {
|
||||
@ -32,15 +33,9 @@ void main() {
|
||||
float brightness = mapBrightness(u_float0);
|
||||
float contrast = mapContrast(u_float1);
|
||||
|
||||
// Early exit if no adjustment
|
||||
if (abs(brightness) < EPSILON && abs(contrast - 1.0) < EPSILON) {
|
||||
fragColor = orig;
|
||||
return;
|
||||
}
|
||||
|
||||
vec3 lin = srgbToLinear(orig.rgb);
|
||||
|
||||
lin = (lin - 0.5) * contrast + brightness + 0.5;
|
||||
lin = (lin - MID_GRAY) * contrast + brightness + MID_GRAY;
|
||||
|
||||
// Convert back to sRGB
|
||||
vec3 result = linearToSrgb(clamp(lin, 0.0, 1.0));
|
||||
|
||||
@ -14,21 +14,26 @@ const int MODE_BARREL = 2;
|
||||
const int MODE_SWIRL = 3;
|
||||
const int MODE_DIAGONAL = 4;
|
||||
|
||||
const float AMOUNT_SCALE = 0.0005;
|
||||
const float RADIAL_MULT = 4.0;
|
||||
const float BARREL_MULT = 8.0;
|
||||
const float INV_SQRT2 = 0.70710678118;
|
||||
|
||||
void main() {
|
||||
vec2 uv = v_texCoord;
|
||||
vec4 original = texture(u_image0, uv);
|
||||
|
||||
float amount = u_float0 * 0.0005;
|
||||
float amount = u_float0 * AMOUNT_SCALE;
|
||||
|
||||
if (amount == 0.0) {
|
||||
if (amount < 0.000001) {
|
||||
fragColor = original;
|
||||
return;
|
||||
}
|
||||
|
||||
vec2 centered = uv - 0.5;
|
||||
float r = length(centered);
|
||||
vec2 dir = normalize(centered + 0.001);
|
||||
vec2 offset;
|
||||
vec2 dir = r > 0.0001 ? centered / r : vec2(0.0);
|
||||
vec2 offset = vec2(0.0);
|
||||
|
||||
if (u_int0 == MODE_LINEAR) {
|
||||
// Horizontal shift
|
||||
@ -36,20 +41,20 @@ void main() {
|
||||
}
|
||||
else if (u_int0 == MODE_RADIAL) {
|
||||
// Outward from center, stronger at edges
|
||||
offset = dir * r * amount * 4.0;
|
||||
offset = dir * r * amount * RADIAL_MULT;
|
||||
}
|
||||
else if (u_int0 == MODE_BARREL) {
|
||||
// Lens distortion simulation (r² falloff)
|
||||
offset = dir * r * r * amount * 8.0;
|
||||
offset = dir * r * r * amount * BARREL_MULT;
|
||||
}
|
||||
else if (u_int0 == MODE_SWIRL) {
|
||||
// Perpendicular to radial (rotational aberration)
|
||||
vec2 perp = vec2(-dir.y, dir.x);
|
||||
offset = perp * r * amount * 4.0;
|
||||
offset = perp * r * amount * RADIAL_MULT;
|
||||
}
|
||||
else if (u_int0 == MODE_DIAGONAL) {
|
||||
// 45° offset
|
||||
offset = vec2(amount, amount) * 0.707;
|
||||
offset = vec2(amount, amount) * INV_SQRT2;
|
||||
}
|
||||
|
||||
float red = texture(u_image0, uv + offset).r;
|
||||
|
||||
@ -10,31 +10,43 @@ uniform float u_float3; // saturation (-100 to 100)
|
||||
in vec2 v_texCoord;
|
||||
out vec4 fragColor;
|
||||
|
||||
const float INPUT_SCALE = 0.01;
|
||||
const float TEMP_TINT_PRIMARY = 0.3;
|
||||
const float TEMP_TINT_SECONDARY = 0.15;
|
||||
const float VIBRANCE_BOOST = 2.0;
|
||||
const float SATURATION_BOOST = 2.0;
|
||||
const float SKIN_PROTECTION = 0.5;
|
||||
const float EPSILON = 0.001;
|
||||
const vec3 LUMA_WEIGHTS = vec3(0.299, 0.587, 0.114);
|
||||
|
||||
void main() {
|
||||
vec4 tex = texture(u_image0, v_texCoord);
|
||||
vec3 color = tex.rgb;
|
||||
|
||||
// Scale inputs: -100/100 → -1/1
|
||||
float temperature = u_float0 * 0.01;
|
||||
float tint = u_float1 * 0.01;
|
||||
float vibrance = u_float2 * 0.01;
|
||||
float saturation = u_float3 * 0.01;
|
||||
float temperature = u_float0 * INPUT_SCALE;
|
||||
float tint = u_float1 * INPUT_SCALE;
|
||||
float vibrance = u_float2 * INPUT_SCALE;
|
||||
float saturation = u_float3 * INPUT_SCALE;
|
||||
|
||||
// Temperature (warm/cool): positive = warm, negative = cool
|
||||
color.r = clamp(color.r + temperature * 0.3, 0.0, 1.0);
|
||||
color.b = clamp(color.b - temperature * 0.3, 0.0, 1.0);
|
||||
color.r += temperature * TEMP_TINT_PRIMARY;
|
||||
color.b -= temperature * TEMP_TINT_PRIMARY;
|
||||
|
||||
// Tint (green/magenta): positive = green, negative = magenta
|
||||
color.g = clamp(color.g + tint * 0.3, 0.0, 1.0);
|
||||
color.r = clamp(color.r - tint * 0.15, 0.0, 1.0);
|
||||
color.b = clamp(color.b - tint * 0.15, 0.0, 1.0);
|
||||
color.g += tint * TEMP_TINT_PRIMARY;
|
||||
color.r -= tint * TEMP_TINT_SECONDARY;
|
||||
color.b -= tint * TEMP_TINT_SECONDARY;
|
||||
|
||||
// Vibrance Pro with skin protection
|
||||
// Single clamp after temperature/tint
|
||||
color = clamp(color, 0.0, 1.0);
|
||||
|
||||
// Vibrance with skin protection
|
||||
if (vibrance != 0.0) {
|
||||
float maxC = max(color.r, max(color.g, color.b));
|
||||
float minC = min(color.r, min(color.g, color.b));
|
||||
float sat = maxC - minC;
|
||||
float gray = dot(color, vec3(0.299, 0.587, 0.114));
|
||||
float gray = dot(color, LUMA_WEIGHTS);
|
||||
|
||||
if (vibrance < 0.0) {
|
||||
// Desaturate: -100 → gray
|
||||
@ -43,24 +55,22 @@ void main() {
|
||||
// Boost less saturated colors more
|
||||
float vibranceAmt = vibrance * (1.0 - sat);
|
||||
|
||||
// Skin tone protection (hardcoded 0.5)
|
||||
float skinTone = 0.0;
|
||||
if (color.r > color.g && color.g > color.b) {
|
||||
float warmth = (color.r - color.b) / max(maxC, 0.001);
|
||||
skinTone = warmth * sat * (1.0 - sat);
|
||||
}
|
||||
vibranceAmt *= (1.0 - skinTone * 0.5);
|
||||
// Branchless skin tone protection
|
||||
float isWarmTone = step(color.b, color.g) * step(color.g, color.r);
|
||||
float warmth = (color.r - color.b) / max(maxC, EPSILON);
|
||||
float skinTone = isWarmTone * warmth * sat * (1.0 - sat);
|
||||
vibranceAmt *= (1.0 - skinTone * SKIN_PROTECTION);
|
||||
|
||||
color = mix(vec3(gray), color, 1.0 + vibranceAmt * 2.0);
|
||||
color = mix(vec3(gray), color, 1.0 + vibranceAmt * VIBRANCE_BOOST);
|
||||
}
|
||||
}
|
||||
|
||||
// Saturation
|
||||
if (saturation != 0.0) {
|
||||
float gray = dot(color, vec3(0.299, 0.587, 0.114));
|
||||
float gray = dot(color, LUMA_WEIGHTS);
|
||||
float satMix = saturation < 0.0
|
||||
? 1.0 + saturation // -100 → gray
|
||||
: 1.0 + saturation * 2.0; // +100 → 3x boost
|
||||
? 1.0 + saturation // -100 → gray
|
||||
: 1.0 + saturation * SATURATION_BOOST; // +100 → 3x boost
|
||||
color = mix(vec3(gray), color, satMix);
|
||||
}
|
||||
|
||||
|
||||
@ -86,7 +86,7 @@ void main() {
|
||||
float luma = dot(color.rgb, vec3(0.2126, 0.7152, 0.0722));
|
||||
|
||||
// Grain UV (resolution-independent)
|
||||
vec2 grainUV = v_texCoord * u_resolution / max(u_float1, 0.001);
|
||||
vec2 grainUV = v_texCoord * u_resolution / max(u_float1, 0.01);
|
||||
uvec2 grainPixel = uvec2(grainUV);
|
||||
|
||||
float g;
|
||||
@ -120,5 +120,5 @@ void main() {
|
||||
vec3 grainColor = mix(vec3(g), grainRGB, clamp(u_float2, 0.0, 1.0));
|
||||
|
||||
color.rgb += grainColor * strength * lumWeight;
|
||||
fragColor0 = vec4(color.rgb, color.a);
|
||||
fragColor0 = vec4(clamp(color.rgb, 0.0, 1.0), color.a);
|
||||
}
|
||||
|
||||
@ -76,6 +76,7 @@ void main() {
|
||||
float t1 = threshold + 0.15;
|
||||
|
||||
vec2 texelSize = 1.0 / u_resolution;
|
||||
float aspect = u_resolution.x / u_resolution.y;
|
||||
float radius2 = radius * radius;
|
||||
|
||||
float sampleScale = clamp(radius * 0.75, 0.35, 1.0);
|
||||
@ -103,7 +104,7 @@ void main() {
|
||||
float fi = float(i);
|
||||
float dist = sqrt(fi / float(samples)) * radius * radiusJitter;
|
||||
|
||||
vec2 offset = dir * dist * texelSize;
|
||||
vec2 offset = dir * dist * texelSize * vec2(1.0, aspect);
|
||||
vec3 c = texture(u_image0, v_texCoord + offset).rgb;
|
||||
float mask = smoothstep(t0, t1, dot(c, LUMA));
|
||||
|
||||
@ -120,7 +121,7 @@ void main() {
|
||||
);
|
||||
}
|
||||
|
||||
glow *= intensity / totalWeight;
|
||||
glow *= intensity / max(totalWeight, 0.001);
|
||||
|
||||
if (u_int1 > 0) {
|
||||
glow *= hexToRgb(u_int1);
|
||||
|
||||
@ -106,23 +106,8 @@ vec3 rgb2hsb(vec3 c) {
|
||||
}
|
||||
|
||||
vec3 hsb2rgb(vec3 hsb) {
|
||||
float h = hsb.x * 6.0;
|
||||
float s = hsb.y;
|
||||
float b = hsb.z;
|
||||
|
||||
float c = b * s;
|
||||
float x = c * (1.0 - abs(mod(h, 2.0) - 1.0));
|
||||
float m = b - c;
|
||||
|
||||
vec3 rgb;
|
||||
if (h < 1.0) rgb = vec3(c, x, 0.0);
|
||||
else if (h < 2.0) rgb = vec3(x, c, 0.0);
|
||||
else if (h < 3.0) rgb = vec3(0.0, c, x);
|
||||
else if (h < 4.0) rgb = vec3(0.0, x, c);
|
||||
else if (h < 5.0) rgb = vec3(x, 0.0, c);
|
||||
else rgb = vec3(c, 0.0, x);
|
||||
|
||||
return rgb + m;
|
||||
vec3 rgb = clamp(abs(mod(hsb.x * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);
|
||||
return hsb.z * mix(vec3(1.0), rgb, hsb.y);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
@ -149,16 +134,6 @@ float getHueWeight(float hue, float center, float overlap) {
|
||||
float getModeWeight(float hue, int mode, float overlap) {
|
||||
if (mode == MODE_MASTER || mode == MODE_COLORIZE) return 1.0;
|
||||
|
||||
float centers[6];
|
||||
centers[0] = 0.0;
|
||||
centers[1] = 1.0/6.0;
|
||||
centers[2] = 2.0/6.0;
|
||||
centers[3] = 3.0/6.0;
|
||||
centers[4] = 4.0/6.0;
|
||||
centers[5] = 5.0/6.0;
|
||||
|
||||
int idx = mode - 1;
|
||||
|
||||
if (mode == MODE_RED) {
|
||||
return max(
|
||||
getHueWeight(hue, 0.0, overlap),
|
||||
@ -166,7 +141,8 @@ float getModeWeight(float hue, int mode, float overlap) {
|
||||
);
|
||||
}
|
||||
|
||||
return getHueWeight(hue, centers[idx], overlap);
|
||||
float center = float(mode - 1) / 6.0;
|
||||
return getHueWeight(hue, center, overlap);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
||||
@ -25,60 +25,66 @@ float gaussian(float x, float sigma) {
|
||||
void main() {
|
||||
vec2 texelSize = 1.0 / u_resolution;
|
||||
float radius = max(u_float0, 0.0);
|
||||
|
||||
// Radial (angular) blur
|
||||
|
||||
// Radial (angular) blur with incremental rotation
|
||||
if (u_int0 == BLUR_RADIAL) {
|
||||
vec2 center = vec2(0.5);
|
||||
vec2 dir = v_texCoord - center;
|
||||
float dist = length(dir);
|
||||
|
||||
// Avoid division by zero
|
||||
|
||||
if (dist < 1e-4) {
|
||||
fragColor0 = texture(u_image0, v_texCoord);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
vec4 sum = vec4(0.0);
|
||||
float totalWeight = 0.0;
|
||||
float angleStep = radius * RADIAL_STRENGTH;
|
||||
|
||||
|
||||
dir /= dist;
|
||||
|
||||
|
||||
float cosStep = cos(angleStep);
|
||||
float sinStep = sin(angleStep);
|
||||
|
||||
float negAngle = -float(RADIAL_SAMPLES) * angleStep;
|
||||
vec2 rotDir = vec2(
|
||||
dir.x * cos(negAngle) - dir.y * sin(negAngle),
|
||||
dir.x * sin(negAngle) + dir.y * cos(negAngle)
|
||||
);
|
||||
|
||||
for (int i = -RADIAL_SAMPLES; i <= RADIAL_SAMPLES; i++) {
|
||||
float a = float(i) * angleStep;
|
||||
float s = sin(a);
|
||||
float c = cos(a);
|
||||
vec2 rotatedDir = vec2(
|
||||
dir.x * c - dir.y * s,
|
||||
dir.x * s + dir.y * c
|
||||
);
|
||||
vec2 uv = center + rotatedDir * dist;
|
||||
vec2 uv = center + rotDir * dist;
|
||||
float w = 1.0 - abs(float(i)) / float(RADIAL_SAMPLES);
|
||||
sum += texture(u_image0, uv) * w;
|
||||
totalWeight += w;
|
||||
|
||||
rotDir = vec2(
|
||||
rotDir.x * cosStep - rotDir.y * sinStep,
|
||||
rotDir.x * sinStep + rotDir.y * cosStep
|
||||
);
|
||||
}
|
||||
|
||||
fragColor0 = sum / totalWeight;
|
||||
|
||||
fragColor0 = sum / max(totalWeight, 0.001);
|
||||
return;
|
||||
}
|
||||
|
||||
// Gaussian / Box blur
|
||||
|
||||
// Gaussian / Box blur (grid sampling)
|
||||
int samples = int(ceil(radius));
|
||||
|
||||
|
||||
if (samples == 0) {
|
||||
fragColor0 = texture(u_image0, v_texCoord);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
vec4 color = vec4(0.0);
|
||||
float totalWeight = 0.0;
|
||||
float sigma = radius / 2.0;
|
||||
|
||||
|
||||
for (int x = -samples; x <= samples; x++) {
|
||||
for (int y = -samples; y <= samples; y++) {
|
||||
vec2 offset = vec2(float(x), float(y)) * texelSize;
|
||||
vec4 sample_color = texture(u_image0, v_texCoord + offset);
|
||||
|
||||
|
||||
float weight;
|
||||
if (u_int0 == BLUR_GAUSSIAN) {
|
||||
float dist = length(vec2(float(x), float(y)));
|
||||
@ -87,11 +93,11 @@ void main() {
|
||||
// BLUR_BOX
|
||||
weight = 1.0;
|
||||
}
|
||||
|
||||
|
||||
color += sample_color * weight;
|
||||
totalWeight += weight;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fragColor0 = color / totalWeight;
|
||||
}
|
||||
|
||||
@ -3,9 +3,9 @@ precision highp float;
|
||||
|
||||
uniform sampler2D u_image0;
|
||||
uniform vec2 u_resolution;
|
||||
uniform float u_float0; // amount [0.0 – 3.0] typical: 0.5–1.5
|
||||
uniform float u_float1; // radius [0.5 – 10.0] blur radius in pixels
|
||||
uniform float u_float2; // threshold [0.0 – 0.1] min difference to sharpen
|
||||
uniform float u_float0; // amount [0.0 - 3.0] typical: 0.5-1.5
|
||||
uniform float u_float1; // radius [0.5 - 10.0] blur radius in pixels
|
||||
uniform float u_float2; // threshold [0.0 - 0.1] min difference to sharpen
|
||||
|
||||
in vec2 v_texCoord;
|
||||
layout(location = 0) out vec4 fragColor0;
|
||||
@ -23,27 +23,21 @@ void main() {
|
||||
float radius = max(u_float1, 0.5);
|
||||
float amount = u_float0;
|
||||
float threshold = u_float2;
|
||||
|
||||
|
||||
vec4 original = texture(u_image0, v_texCoord);
|
||||
|
||||
|
||||
// Gaussian blur for the "unsharp" mask
|
||||
int samples = int(ceil(radius));
|
||||
float sigma = radius / 2.0;
|
||||
|
||||
|
||||
vec4 blurred = vec4(0.0);
|
||||
float totalWeight = 0.0;
|
||||
|
||||
|
||||
for (int x = -samples; x <= samples; x++) {
|
||||
for (int y = -samples; y <= samples; y++) {
|
||||
vec2 offset = vec2(float(x), float(y)) * texel;
|
||||
vec2 sampleCoord = v_texCoord + offset;
|
||||
|
||||
// Boundary check - skip out-of-bounds samples
|
||||
if (sampleCoord.x < 0.0 || sampleCoord.x > 1.0 ||
|
||||
sampleCoord.y < 0.0 || sampleCoord.y > 1.0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
float dist = length(vec2(float(x), float(y)));
|
||||
float weight = gaussian(dist, sigma);
|
||||
blurred += texture(u_image0, sampleCoord) * weight;
|
||||
@ -51,18 +45,17 @@ void main() {
|
||||
}
|
||||
}
|
||||
blurred /= totalWeight;
|
||||
|
||||
|
||||
// Unsharp mask = original - blurred
|
||||
vec3 mask = original.rgb - blurred.rgb;
|
||||
|
||||
// Luminance-based threshold (Photoshop-style)
|
||||
|
||||
// Luminance-based threshold with smooth falloff
|
||||
float lumaDelta = abs(getLuminance(original.rgb) - getLuminance(blurred.rgb));
|
||||
if (lumaDelta < threshold) {
|
||||
mask = vec3(0.0);
|
||||
}
|
||||
|
||||
float thresholdScale = smoothstep(0.0, threshold, lumaDelta);
|
||||
mask *= thresholdScale;
|
||||
|
||||
// Sharpen: original + mask * amount
|
||||
vec3 sharpened = original.rgb + mask * amount;
|
||||
|
||||
|
||||
fragColor0 = vec4(clamp(sharpened, 0.0, 1.0), original.a);
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue
Block a user