PageSourceSearch

https://scalz.ai/luminous/preview/nebula.js?v=orbital-19

js scalz.ai collected 2026-10-05 12:37:16 UTC 6,449 bytes, 117 lines download raw bytes

1(() => {
2  "use strict";
3  const canvas = document.querySelector(".nebula-flow");
4  const hero = document.querySelector("#hero");
5  const source = document.querySelector(".hero-environment > img");
6  const reduced = matchMedia("(prefers-reduced-motion: reduce)");
7  const compact = matchMedia("(max-width: 980px)");
8  if (!canvas || !source || !hero || navigator.connection?.saveData) return;
9  const gl = canvas.getContext("webgl", { alpha: true, antialias: false, depth: false, powerPreference: "low-power", premultipliedAlpha: false });
10  if (!gl) return;
11
12  const vertexSource = `attribute vec2 a_position;
13    varying vec2 v_uv;
14    void main(){v_uv=vec2((a_position.x+1.0)*0.5,(1.0-a_position.y)*0.5);gl_Position=vec4(a_position,0.0,1.0);}`;
15  const fragmentSource = `precision mediump float;
16    varying vec2 v_uv;
17    uniform sampler2D u_image;
18    uniform vec2 u_cover;
19    uniform float u_time;
20    uniform vec3 u_shock;
21    void main(){
22      vec2 uv=(v_uv-0.5)*u_cover+0.5;
23      vec4 still=texture2D(u_image,uv);
24      float mask=smoothstep(0.32,0.63,uv.x)*(1.0-smoothstep(0.38,0.575,uv.y));
25      mask*=smoothstep(0.015,0.13,still.g-still.r);
26      float t=u_time;
27      // Follow the luminous texture already painted into the rim.
28      float rim=mask*smoothstep(0.10,0.27,still.g-still.r)*smoothstep(0.57,0.9,still.g);
29      vec2 radial=normalize(vec2((uv.x-0.70)*2.35,(uv.y+0.07)*0.82));
30      vec2 tangent=vec2(-radial.y,radial.x);
31      float current=sin(uv.y*29.0+uv.x*11.0-t*1.3);
32      float filament=sin(uv.y*83.0-uv.x*26.0+t*2.1);
33      vec2 flow=vec2(sin(uv.y*10.0+t*0.19)+0.5*cos(uv.x*14.0-t*0.11),
34                    cos(uv.x*9.0+t*0.13)+0.45*sin(uv.y*16.0-t*0.17));
35      flow*=0.0065*mask;
36      flow+=tangent*(current*0.007+filament*0.002)*rim;
37      flow+=radial*sin(uv.y*43.0+t*1.7)*0.0025*rim;
38      vec2 delta=uv-u_shock.xy;
39      float wave=exp(-pow((length(delta)-u_shock.z*0.064)*68.0,2.0))*exp(-u_shock.z*0.85);
40      flow+=normalize(delta+vec2(0.0001))*wave*0.008*mask;
41      vec3 cloud=texture2D(u_image,uv+flow).rgb;
42      float light=sin(uv.x*7.0+uv.y*5.0-t*0.25)*0.022;
43      cloud+=vec3(0.05,0.7,0.72)*light*mask;
44      float surge=pow(0.5+0.5*sin(uv.y*17.0+uv.x*8.0-t*1.1),4.0);
45      cloud+=vec3(0.22,0.75,0.70)*rim*(0.035+surge*0.17+filament*0.024);
46      gl_FragColor=vec4(cloud,mask*0.94);
47    }`;
48
49  function compile(type, code) {
50    const shader = gl.createShader(type);
51    gl.shaderSource(shader, code); gl.compileShader(shader);
52    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { gl.deleteShader(shader); return null; }
53    return shader;
54  }
55  const vs = compile(gl.VERTEX_SHADER, vertexSource);
56  const fs = compile(gl.FRAGMENT_SHADER, fragmentSource);
57  if (!vs || !fs) return;
58  const program = gl.createProgram();
59  gl.attachShader(program, vs); gl.attachShader(program, fs); gl.linkProgram(program);
60  gl.deleteShader(vs); gl.deleteShader(fs);
61  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) return;
62  gl.useProgram(program);
63  const buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
64  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,-1,1,-1,-1,1,1,1]), gl.STATIC_DRAW);
65  const position = gl.getAttribLocation(program, "a_position");
66  gl.enableVertexAttribArray(position); gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0);
67  const coverUniform = gl.getUniformLocation(program, "u_cover");
68  const timeUniform = gl.getUniformLocation(program, "u_time");
69  const shockUniform = gl.getUniformLocation(program, "u_shock");
70  const texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, texture);
71  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
72  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
73  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
74  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
75  gl.uniform1i(gl.getUniformLocation(program, "u_image"), 0);
76  let ready = false, visible = true, enabled = !reduced.matches;
77  let raf = 0, last = 0, clock = 0, rendered = 0, lost = false;
78  let shock = { x: .8, y: .2, born: -100 };
79  window.addEventListener("scalz:atmosphere-entry", e => { shock = { x: e.detail.x, y: e.detail.y, born: clock }; });
80
81  function resize() {
82    const { width, height } = hero.getBoundingClientRect();
83    const scale = Math.min(1.25, devicePixelRatio || 1, 1800 / Math.max(width, height));
84    canvas.width = Math.max(1, Math.round(width * scale));
85    canvas.height = Math.max(1, Math.round(height * scale));
86    gl.viewport(0, 0, canvas.width, canvas.height);
87    const imageRatio = 1.5, screenRatio = width / height;
88    gl.uniform2f(coverUniform, Math.min(1, screenRatio / imageRatio), Math.min(1, imageRatio / screenRatio));
89  }
90  function frame(now) {
91    if (!ready || !enabled || !visible || document.hidden || reduced.matches || compact.matches || lost) { raf = 0; last = 0; return; }
92    if (last) clock += Math.min(100, now - last) / 1000;
93    last = now;
94    if (now - rendered > 32) {
95      gl.uniform1f(timeUniform, clock); gl.uniform3f(shockUniform, shock.x, shock.y, Math.min(30,clock-shock.born)); gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); rendered = now;
96    }
97    raf = requestAnimationFrame(frame);
98  }
99  function sync() {
100    if (raf) cancelAnimationFrame(raf);
101    raf = 0; last = 0;
102    if (ready && enabled && visible && !document.hidden && !reduced.matches && !compact.matches && !lost) raf = requestAnimationFrame(frame);
103  }
104  function load() {
105    if (!source.naturalWidth) return;
106    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
107    ready = true; canvas.dataset.renderer = "webgl-portal-flow"; resize(); sync();
108  }
109  source.complete ? load() : source.addEventListener("load", load, { once: true });
110  new ResizeObserver(resize).observe(hero);
111  new IntersectionObserver(entries => { visible = entries[0].isIntersecting; sync(); }, { threshold: .03 }).observe(hero);
112  window.addEventListener("scalz:preview-effects", e => { enabled = Boolean(e.detail.enabled); sync(); });
113  document.addEventListener("visibilitychange", sync);
114  reduced.addEventListener("change", () => { enabled = !reduced.matches && !document.documentElement.classList.contains("preview-effects-off"); sync(); });
115  compact.addEventListener("change", sync);
116  canvas.addEventListener("webglcontextlost", e => { e.preventDefault(); lost = true; sync(); canvas.style.opacity = "0"; });
117})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.