From 61faec2e92fb7eb79379fe721a001cf3566cbf91 Mon Sep 17 00:00:00 2001 From: Christian Lawson-Perfect Date: Fri, 16 May 2025 06:32:01 +0000 Subject: [PATCH] WebGL 2 shader --- .gitignore | 1 + fragshader.glsl | 42 ++++++++++++++++ index.html | 23 +++++++++ script.js | 128 ++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 194 insertions(+) create mode 100644 .gitignore create mode 100644 fragshader.glsl create mode 100644 index.html create mode 100644 script.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8bc0f76 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.make.* \ No newline at end of file diff --git a/fragshader.glsl b/fragshader.glsl new file mode 100644 index 0000000..c16c37e --- /dev/null +++ b/fragshader.glsl @@ -0,0 +1,42 @@ +#version 300 es +#define PI 3.1415926538 +#define maxIterations 100 +precision mediump float; +uniform float t; +uniform vec2 screen_size; +in vec4 v_pos; +out vec4 fragColor; + +vec2 squareImaginary(vec2 number){ + return vec2( + pow(number.x,2.)-pow(number.y,2.), + 2.*number.x*number.y + ); +} + +float iterateMandelbrot(vec2 coord) { + vec2 z = vec2(0.,0.); + for(int i=0; i 2.) { + return float(i)/float(maxIterations); + } + } + return 1.; +} + +void main(void) { + float aspect = screen_size.x / screen_size.y; + mat2 squash = mat2(aspect, 0., 0., 1.); + vec2 pos = squash * v_pos.xy; + float r = length(pos.xy); + vec2 centre = vec2(0.367,0.6955); + float bounce = 1.;//(cos(t*0.1) + 1.)/2.; + float zoom = 0.5 / (1. + 200.*(1.-bounce)); + //float zoom = 1.; + float m = iterateMandelbrot(pos * zoom + centre); + float c = m==1. ? 1. : m*0.8; + vec4 color = vec4(c, c, c, 1.0); + fragColor = color; +} \ No newline at end of file diff --git a/index.html b/index.html new file mode 100644 index 0000000..bb2a900 --- /dev/null +++ b/index.html @@ -0,0 +1,23 @@ + + + + + + A thing made by CLP + + + + + +

WebGL reference card

+

+  
+
\ No newline at end of file
diff --git a/script.js b/script.js
new file mode 100644
index 0000000..3a7ab10
--- /dev/null
+++ b/script.js
@@ -0,0 +1,128 @@
+console.clear();
+
+function error(...msgs) {
+  const msg = msgs.join('\n');
+  console.error(msg);
+  document.getElementById('errors').textContent = msg;
+}
+
+function loadShader(gl, type, source) {
+    const shader = gl.createShader(type);
+
+    gl.shaderSource(shader, source);
+    gl.compileShader(shader);
+
+    if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
+        error('An error occurred compiling the shaders:', gl.getShaderInfoLog(shader));
+        gl.deleteShader(shader);
+        return null;
+    }
+
+    return shader;
+}
+
+function initShaderProgram(gl, vs, fs) {
+    const shaderProgram = gl.createProgram();
+    gl.attachShader(shaderProgram, vs);
+    gl.attachShader(shaderProgram, fs);
+    gl.linkProgram(shaderProgram);
+
+    if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
+        error('Unable to initialize the shader program:', gl.getProgramInfoLog(shaderProgram));
+        return null;
+    }
+
+    return shaderProgram;
+}
+
+function initBuffers(gl) {
+    const vertices = new Float32Array([
+        -1, 1,
+         1, 1,
+         -1, -1,
+         -1, -1,
+         1, 1,
+         1, -1
+    ]);
+
+    const vertexBuffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
+
+    return vertexBuffer;
+}
+
+async function init() {
+
+  const vsSource = `#version 300 es
+      in vec4 aVertexPosition;
+  
+      out vec4 v_pos;
+  
+      void main(void) {
+          gl_Position = aVertexPosition;
+          v_pos = gl_Position;
+      }
+  `;
+
+  const fsSource = await (await fetch('fragshader.glsl')).text();
+
+  console.log(fsSource);
+  
+
+  function set_canvas_size() {
+    const dpr = window.devicePixelRatio;
+    const {clientWidth: width, clientHeight: height} = canvas;
+    canvas.width = Math.round(width * dpr);
+    canvas.height = Math.round(height * dpr);
+  }
+  
+  function drawScene() {
+      gl.clear(gl.COLOR_BUFFER_BIT);
+  
+      const vertexPosition = gl.getAttribLocation(shaderProgram, 'aVertexPosition');
+      const tLoc = gl.getUniformLocation(shaderProgram, "t");
+      const screen_sizeLoc = gl.getUniformLocation(shaderProgram, "screen_size");
+      gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
+      const t = (new Date() - t1) / 1000;
+      gl.uniform1f(tLoc, t);
+      gl.uniform2fv(screen_sizeLoc, [canvas.width, canvas.height]);
+      gl.vertexAttribPointer(vertexPosition, 2, gl.FLOAT, false, 0, 0);
+      gl.enableVertexAttribArray(vertexPosition);
+      
+      gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
+  
+      gl.useProgram(shaderProgram);
+  
+      gl.drawArrays(gl.TRIANGLES, 0, 6);
+      
+      requestAnimationFrame(drawScene);
+  }
+
+  let mx = 0, my = 0;
+
+  const canvas = document.getElementById('glCanvas');
+  set_canvas_size();
+  const gl = canvas.getContext('webgl2');
+  
+  if (!gl) {
+      throw new Error('Unable to initialize WebGL. Your browser may not support it.');
+  }
+  if (gl) {
+      gl.clearColor(0.0, 0.0, 0.0, 1.0);
+  }
+  
+  const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
+  const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
+  
+  const shaderProgram = initShaderProgram(gl, vertexShader, fragmentShader);
+  
+  const vertexBuffer = initBuffers(gl);
+  const t1 = new Date();
+  drawScene();
+
+  const resize_observer = new ResizeObserver((entries) => set_canvas_size());
+  resize_observer.observe(canvas);
+}
+
+init();
\ No newline at end of file