// https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83 vec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); } // https://gist.github.com/patriciogonzalezvivo/670c22f3966e662d2f83 float snoise(vec2 v) { const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439); vec2 i = floor(v + dot(v, C.yy) ); vec2 x0 = v - i + dot(i, C.xx); vec2 i1; i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); vec4 x12 = x0.xyxy + C.xxzz; x12.xy -= i1; i = mod(i, 289.0); vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) + i.x + vec3(0.0, i1.x, 1.0 )); vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), dot(x12.zw,x12.zw)), 0.0); m = m*m ; m = m*m ; vec3 x = 2.0 * fract(p * C.www) - 1.0; vec3 h = abs(x) - 0.5; vec3 ox = floor(x + 0.5); vec3 a0 = x - ox; m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); vec3 g; g.x = a0.x * x0.x + h.x * x0.y; g.yz = a0.yz * x12.xz + h.yz * x12.yw; return 130.0 * dot(m, g); } // https://github.com/hughsk/glsl-hsv2rgb vec3 hsv2rgb(vec3 c) { vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www); return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); } vec3 hsv2rgb(float h, float s, float v) { return hsv2rgb(vec3(h / 360., s / 100., v / 100.)); } float lerp(float a, float b, float w) { return a * (1. - w) + b * w; } // Circular hue interpolation to avoid unwanted green tones float lerpHue(float a, float b, float w) { float diff = b - a; // Take the shortest path around the color wheel if (diff > 180.) { diff -= 360.; } else if (diff < -180.) { diff += 360.; } float result = a + diff * w; // Normalize to 0-360 range if (result < 0.) { result += 360.; } else if (result >= 360.) { result -= 360.; } return result; } float constrain(float v, float minValue, float maxValue) { return min(max(v, minValue), maxValue); } void main() { // Enhanced film noir color palette - blue base with red neon accents const float h0_min = 240.; // Deep blue shadows matching brick wall const float s0_min = 35.; // Increased saturation for richer blues const float v0_min = 1.; // Darker shadows for subtlety const float h0_max = 220.; // Cool blue-gray mid-tones const float s0_max = 45.; // Higher saturation for neon-like quality const float v0_max = 6.; // Reduced mid-tone brightness const float h1_min = 350.; // Red neon accent highlights (matching OPEN sign) const float s1_min = 70.; // High saturation for vibrant neon red const float v1_min = 16.; // Reduced brightness for subtlety const float h1_max = 10.; // Bright red-pink neon peaks const float s1_max = 85.; // Maximum saturation for intense neon glow const float v1_max = 28.; // Reduced highlight brightness // Secondary highlight colors (upper-right lamp area) const float h2_min = 200.; // Cool blue-cyan lamp base const float s2_min = 60.; // Moderate saturation for lamp glow const float v2_min = 14.; // Reduced lamp presence const float h2_max = 180.; // Bright cyan lamp peak const float s2_max = 75.; // High saturation for neon lamp effect const float v2_max = 24.; // Reduced lamp highlights // Slower, more atmospheric animation timing vec2 distortion = vec2( snoise(gl_FragCoord.xy / 200.0 + vec2(u_time * .15, u_time * .2)), snoise(gl_FragCoord.xy / 200.0 + vec2(3. + u_time * .2, 4. + u_time * .15)) ); vec2 distorted = gl_FragCoord.xy / 800. + distortion * 0.3; vec2 distortion_2 = vec2( snoise(distorted + vec2(u_time * -.005, u_time * -.008)), snoise(distorted + vec2(3. + u_time * -.008, 4. + u_time * -.15)) ); vec2 distorted_2 = gl_FragCoord.xy / 500. + distortion_2 * 0.25; float noiseValue = (snoise(distorted_2 + vec2(u_time * -0.02, u_time * 0.025)) + 1.) / 2.; // Primary highlight zone (center-based red neon) float d_center = constrain(1. - distance(gl_FragCoord.xy + ((distorted - vec2(1., 1.)) / 2.) * 800., u_resolution / 2.) / sqrt(u_resolution.x * u_resolution.x * 0.4 + u_resolution.y * u_resolution.y * 0.6), 0., 1.); d_center = pow(d_center, 2.5); // Secondary highlight zone (upper-right lamp area) vec2 lampPosition = vec2(u_resolution.x * 0.85, u_resolution.y * 0.75); float d_lamp = constrain(1. - distance(gl_FragCoord.xy + ((distorted - vec2(1., 1.)) / 2.) * 400., lampPosition) / (sqrt(u_resolution.x * u_resolution.x + u_resolution.y * u_resolution.y) * 0.3), 0., 1.); d_lamp = pow(d_lamp, 2.0); // Combine highlight zones - use maximum influence float d_combined = max(d_center, d_lamp); // Determine which highlight zone is dominant for color selection float lampInfluence = d_lamp / max(d_combined, 0.001); float centerInfluence = d_center / max(d_combined, 0.001); // Interpolate between shadow and highlight colors based on combined distance float h_min_base = lerpHue(h0_min, h1_min, d_combined); float s_min_base = lerp(s0_min, s1_min, d_combined); float v_min_base = lerp(v0_min, v1_min, d_combined); float h_max_base = lerpHue(h0_max, h1_max, d_combined); float s_max_base = lerp(s0_max, s1_max, d_combined); float v_max_base = lerp(v0_max, v1_max, d_combined); // Apply lamp influence to shift colors toward blue/cyan in lamp area float h_min_lamp = lerpHue(h0_min, h2_min, d_combined); float s_min_lamp = lerp(s0_min, s2_min, d_combined); float v_min_lamp = lerp(v0_min, v2_min, d_combined); float h_max_lamp = lerpHue(h0_max, h2_max, d_combined); float s_max_lamp = lerp(s0_max, s2_max, d_combined); float v_max_lamp = lerp(v0_max, v2_max, d_combined); // Blend between center (red) and lamp (blue) highlights based on influence float h_min_final = lerpHue(h_min_base, h_min_lamp, lampInfluence); float s_min_final = lerp(s_min_base, s_min_lamp, lampInfluence); float v_min_final = lerp(v_min_base, v_min_lamp, lampInfluence); float h_max_final = lerpHue(h_max_base, h_max_lamp, lampInfluence); float s_max_final = lerp(s_max_base, s_max_lamp, lampInfluence); float v_max_final = lerp(v_max_base, v_max_lamp, lampInfluence); vec3 color = hsv2rgb(lerpHue(h_min_final, h_max_final, noiseValue), lerp(s_min_final, s_max_final, noiseValue), lerp(v_min_final, v_max_final, noiseValue)); // Reduced opacity for subtle atmospheric effect while preserving readability float alpha = 0.30; gl_FragColor = vec4(color.r, color.g, color.b, alpha); }

So, uh, what's the plan here?

Qwirklabs is a software company building for the next wave of digital products. We craft the tools, then build the goods.

... and What's Brewing

Qwirklabs exists because we believe the people building the next wave of digital products deserve better tools than the siloed, clunky options often available. We're a compact team of tech enthusiasts who've experienced the pain of fragmented design-to-development pipelines firsthand.

That's why we're intensely focused on integrating sophisticated capabilities (like functional UI design, AI assistance, and 3D) into a single, collaborative environment. We're here to engineer solutions that empower creators, simplify complexity, and maybe make building awesome stuff a bit more fun.

The solution we're engineering is called Smoothie. Think of it as a powerful, modular toolkit designed to bring sophisticated capabilities and workflows into one accessible platform, like a game engine. But instead of forcing one giant system on you, its modular design lets you use the pieces you need. We're hard at work forging it in the lab, focused on delivering that unified power without the typical integration headaches. It's still brewing, but we're aiming to make building complex stuff feel surprisingly... smooth.

Curious about what we actually do and the tech we're building? There's a button that leads to all the juicy details.

explore our lab