#ifdef GL_ES
precision mediump float; // Set floating point precision to medium on mobile/WebGL ES
#endif
// Input uniforms provided by the rendering system
uniform vec2 u_resolution; // Canvas size in pixels
uniform vec2 u_mouse; // Mouse position in pixels
uniform float u_time; // Time in seconds since shader started
uniform sampler2D u_webcam; // Webcam texture sampler
uniform vec2 u_webcam_size; // Webcam resolution in pixels
uniform float u_dpi; // Controls the density of the halftone pattern
uniform int u_color_theme; // Color mode (1=color, 2=grayscale, other=white)
uniform float u_pattern_density;
uniform bool u_invert_pattern; // Whether to invert the halftone pattern (0=normal, 1=inverted)
void main() {
// Convert fragment coordinate to normalized [0,1] UV space
vec2 uv = gl_FragCoord.xy / u_resolution.xy;
// Prepare UV coordinates for halftone pattern
vec2 halftoneUv = uv;
halftoneUv = halftoneUv * 2.0 - 1.0; // Convert to [-1,1] range
// Scale halftone pattern based on aspect ratio
// halftoneUv.x = isCroppedHor ? halftoneUv.x * u_resolution.x / u_resolution.y : halftoneUv.x;
// halftoneUv.y = isCroppedHor ? halftoneUv.y : halftoneUv.y * u_resolution.y / u_resolution.x;
halftoneUv.x = halftoneUv.x * u_resolution.x / u_resolution.y;
halftoneUv.y = halftoneUv.y;
// Create a repeating grid for the halftone pattern
// float posOffX = isCroppedHor ? 0. : mod(u_dpi, 2.) / 2.; // Offset X for even/odd DPI
// float posOffY = isCroppedHor ? mod(u_dpi, 2.) / 2. : 0.; // Offset Y for even/odd DPI
float posOffX = 0.; // Offset X for even/odd DPI
float posOffY = mod(u_dpi, 2.) / 2.; // Offset Y for even/odd DPI
// Divide space into grid cells
halftoneUv.x = fract(halftoneUv.x * u_dpi / 2. + posOffX);
halftoneUv.y = fract(halftoneUv.y * u_dpi / 2. + posOffY);
// Remap each grid cell to [-1,1] range
halftoneUv = halftoneUv * 2.0 - 1.0;
// Set parameters for the halftone effect
float blur = u_dpi * 0.005; // Edge blur amount for the circles (scales with DPI)
// Calculate circle radius based on brightness and modulation
// Higher brightness = larger circles when modulation is less than 1
float rad = u_pattern_density;
// Create a circle in each grid cell
float d1 = length(halftoneUv); // Distance from center of cell
// Apply smoothstep to create a soft-edged circle
d1 = smoothstep(rad - blur, rad + blur, d1);
// Apply pattern inversion if selected
d1 = u_invert_pattern ? d1 : (1. - d1);
// Apply halftone pattern to the color
vec3 color1 = vec3(1., 0., 0.);
color1 = color1 * d1;
// Create a circle in each grid cell
vec2 center = vec2(0.5, 0.5);
float signX = sign(uv.x - center.x);
float signY = sign(uv.y - center.y);
vec2 foo = vec2(length(vec2(uv.x, center.x) - center.x) * 1. * signX, length(vec2(center.y, uv.y) - center.y) * 1. * signY);
float nSin = sin(u_time) / 2. + 0.5;
float d2 = length(halftoneUv - (foo - nSin * foo)); // Distance from center of cell
// Apply smoothstep to create a soft-edged circle
d2 = smoothstep(rad - blur, rad + blur, d2);
// Apply pattern inversion if selected
d2 = u_invert_pattern ? d2 : (1. - d2);
vec3 color2 = vec3(0., 1., 0.);
color2 = color2 * d2;
vec3 color3 = vec3(0., 0., 1.);
color3 = color3 * d2;
// Output final color with original alpha
gl_FragColor = vec4((color1 + color2 + color3), 1.0);
}