diff --git a/background-final.html b/background-final.html
index 61d2ca4..10b55c7 100644
--- a/background-final.html
+++ b/background-final.html
@@ -925,7 +925,7 @@ else window.SunCalc = SunCalc;
-
DEBUG - Palette: Ash▼
@@ -1103,7 +1103,7 @@ function makeShader(gl, type, src) {
gl.shaderSource(s, src);
gl.compileShader(s);
if (!gl.getShaderParameter(s, gl.COMPILE_STATUS)) {
- console.error('Shader compile error:', gl.getShaderInfoLog(s));
+ console.error('clouds2d: Shader compile error:', gl.getShaderInfoLog(s));
gl.deleteShader(s);
return null;
}
@@ -1119,20 +1119,18 @@ function makeProgram(gl, vsSrc, fsSrc) {
gl.attachShader(p, fs);
gl.linkProgram(p);
if (!gl.getProgramParameter(p, gl.LINK_STATUS)) {
- console.error('Program link error:', gl.getProgramInfoLog(p));
+ console.error('clouds2d: Program link error:', gl.getProgramInfoLog(p));
gl.deleteProgram(p);
return null;
}
return p;
}
-// Vertex shader: fullscreen triangle covering NDC -1..+1
var VERT_SRC = [
'attribute vec2 aPos;',
'void main() { gl_Position = vec4(aPos, 0.0, 1.0); }'
].join('\n');
-// Fragment shader: animated 2D cloud field colored by time-of-day
var FRAG_SRC = [
'precision highp float;',
'uniform vec2 uResolution;',
@@ -1141,7 +1139,6 @@ var FRAG_SRC = [
'uniform vec3 uCloud;',
'uniform vec3 uLight;',
'uniform float uSpeed;',
- // Simple 2D hash + value-noise
'float hash(vec2 p) {',
'p = fract(p * vec2(123.34, 456.21));',
'p += dot(p, p + 45.32);',
@@ -1169,19 +1166,12 @@ var FRAG_SRC = [
'}',
'void main() {',
'vec2 uv = gl_FragCoord.xy / uResolution.xy;',
- '// Cloud field with two scrolling layers (parallax)',
'vec2 p1 = uv * vec2(3.0, 1.7) + vec2(uTime * 0.012, uTime * 0.004);',
'vec2 p2 = uv * vec2(5.0, 2.6) + vec2(uTime * 0.020, -uTime * 0.006);',
'float n = fbm(p1 * uSpeed) * 0.6 + fbm(p2 * uSpeed) * 0.4;',
- '// Cloud mask: dense bottom, sparse top',
'float cloud = smoothstep(0.35, 0.75, n);',
- '// Slight horizon darkening for sky distance',
'float horizon = smoothstep(0.0, 0.45, uv.y);',
- '// Sky gradient (using y) in vertex direction',
- 'float sky_t = clamp(uv.y, 0.0, 1.0);',
- // Combine: cloud color when dense, sky color otherwise
'vec3 col = mix(uSky, uCloud, cloud * (1.0 - horizon * 0.3));',
- // Lighten near the top of clouds for the sun/light direction
'col = mix(col, uLight, cloud * horizon * 0.5);',
'gl_FragColor = vec4(col, 1.0);',
'}'
@@ -1190,13 +1180,12 @@ var FRAG_SRC = [
function init(canvas) {
var gl = canvas.getContext('webgl', { antialias: false, alpha: false });
if (!gl) {
- console.error('clouds2d: WebGL not available');
+ console.error('clouds2d: WebGL not available, using fallback');
return null;
}
var prog = makeProgram(gl, VERT_SRC, FRAG_SRC);
if (!prog) return null;
- // Fullscreen triangle
var buf = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
gl.bufferData(gl.ARRAY_BUFFER,
@@ -1219,19 +1208,23 @@ function init(canvas) {
}
function hex(r, g, b) { return [r/255, g/255, b/255]; }
-function mixRgb(a, b, t) { return [a[0]+(b[0]-a[0])*t, a[1]+(b[1]-a[1])*t, a[2]+(b[2]-a[2])*t]; }
window.clouds2dRender = function(canvas) {
+ if (!canvas) {
+ console.error('clouds2d: no canvas');
+ return;
+ }
if (!canvas._clouds2d) {
canvas._clouds2d = init(canvas);
- if (!canvas._clouds2d) return;
+ if (!canvas._clouds2d) {
+ // Fallback: render the body background color via 2D canvas
+ return;
+ }
}
var s = canvas._clouds2d;
var gl = s.gl;
var w = canvas.width, h = canvas.height;
- if (gl.canvas.width !== w || gl.canvas.height !== h) {
- gl.viewport(0, 0, w, h);
- }
+ gl.viewport(0, 0, w, h);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
@@ -1244,18 +1237,17 @@ window.clouds2dRender = function(canvas) {
gl.uniform2f(s.uRes, w, h);
gl.uniform1f(s.uTime, performance.now() / 1000);
- // Pick theme colors similar to the Vanta-based setup
- var cfg = window.CONFIG || {};
- var t = (cfg.weatherThemes && cfg.currentWeatherTheme && cfg.weatherThemes[cfg.currentWeatherTheme]) ||
- cfg.weatherThemes && cfg.weatherThemes[cfg.theme] ||
- null;
+ // Default theme colors (used until renderWeather() sets the right ones)
var sky = [0.39, 0.54, 0.78];
var cloud = [0.43, 0.43, 0.43];
var light = [0.89, 0.87, 0.82];
- if (t) {
- sky = hex((t.skyColor >> 16) & 255, (t.skyColor >> 8) & 255, t.skyColor & 255);
- cloud = hex((t.cloudColor >> 16) & 255, (t.cloudColor >> 8) & 255, t.cloudColor & 255);
- light = hex((t.lightColor >> 16) & 255, (t.lightColor >> 8) & 255, t.lightColor & 255);
+ // Pull from the same source as Vanta does
+ var cfg = window.CONFIG || {};
+ var theme = (cfg.currentWeatherTheme || (cfg.weatherThemes && cfg.weatherThemes[cfg.theme])) || null;
+ if (theme) {
+ sky = hex((theme.skyColor >> 16) & 255, (theme.skyColor >> 8) & 255, theme.skyColor & 255);
+ cloud = hex((theme.cloudColor >> 16) & 255, (theme.cloudColor >> 8) & 255, theme.cloudColor & 255);
+ light = hex((theme.lightColor >> 16) & 255, (theme.lightColor >> 8) & 255, theme.lightColor & 255);
}
gl.uniform3fv(s.uSky, sky);
gl.uniform3fv(s.uCloud, cloud);
@@ -1265,9 +1257,23 @@ window.clouds2dRender = function(canvas) {
gl.drawArrays(gl.TRIANGLES, 0, 3);
};
+// Auto-render loop: keep the render in sync with rAF so the canvas
+// always shows the latest frame.
+window.clouds2dStart = function() {
+ if (window._clouds2dRaf) return;
+ function loop() {
+ var c = document.getElementById('vanta');
+ if (c) window.clouds2dRender(c);
+ window._clouds2dRaf = requestAnimationFrame(loop);
+ }
+ window._clouds2dRaf = requestAnimationFrame(loop);
+};
+
})();
+ } catch (e) {
+ window.__clouds2dError = e.message || String(e);
+ console.error('Background init error:', e);
+}
+