const canvas = document.createElement("canvas")
const gl = canvas.getContext("webgl2")

document.body.innerHTML = ""
document.body.appendChild(canvas)
document.body.style = "margin: 0;overflow: hidden;"
canvas.style.width = "100%"
canvas.style.height = "auto"

const dpr = window.devicePixelRatio

function resize() {
  const {
    innerWidth: width,
    innerHeight: height
  } = window

  canvas.width = width * dpr
  canvas.height = height * dpr

  gl.viewport(0, 0, width * dpr, height * dpr)
}

window.onresize = resize

const vertexSource = `#version 300 es
  #ifdef GL_FRAGMENT_PRECISION_HIGH
  precision highp float;
  #else
  precision mediump float;
  #endif

  in vec4 position;

  void main(void) {
    gl_Position = position;
  }
`

const fragmentSource = `#version 300 es
  /*********
   * made by Matthias Hurrle (@atzedent) 
   */
    #ifdef GL_FRAGMENT_PRECISION_HIGH
    precision highp float;
    #else
    precision mediump float;
    #endif
    
    out vec4 fragColor;
    
    uniform vec2 resolution;
    uniform float time;
    
    #define T time
    #define S smoothstep
    
    float box(vec3 p, vec3 s, float r) {
        p = abs(p)-s;
        return length(max(p,.0))+
            min(.0,max(max(p.x,p.y),p.z))-r;
    }
    
    float map(vec3 p) {
        p.y += sin(p.z*.2-.6)*1.25;
        p.x -= sin(p.z*.125+.05)*4.;
        return -box(p, vec3(1,1.65,20), .05);
    }
    
    void main(void) {
        vec2 uv = (
            gl_FragCoord.xy -.5 * resolution
        ) / min(resolution.x, resolution.y);
        
        vec3 col = vec3(0),
        rd = normalize(vec3(uv,1)),
        p = vec3(1,0,0);
        
        const float steps = 400.;
        
        for (float i=.0; i<steps; i++) {
            float d=map(p);
            
            if (d<1e-3) {
                col += (steps-i)/steps;
                col *= S(.05,.0,sin(p.z+sin(p.z*.1)*2.+T*6.));
                break;
            }
    
            p += rd*d;
        }
    
      fragColor = vec4(col, 1);
    }
`

function compile(shader, source) {
  gl.shaderSource(shader, source)
  gl.compileShader(shader)

  if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
    console.error(gl.getShaderInfoLog(shader))
  }
}

let program

function setup() {
  const vs = gl.createShader(gl.VERTEX_SHADER)
  const fs = gl.createShader(gl.FRAGMENT_SHADER)

  compile(vs, vertexSource)
  compile(fs, fragmentSource)

  program = gl.createProgram()

  gl.attachShader(program, vs)
  gl.attachShader(program, fs)
  gl.linkProgram(program)

  if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
    console.error(gl.getProgramInfoLog(program))
  }
}

let vertices, buffer;

function init() {
  vertices = [
    -1,-1, 1,
    -1,-1, 1,
    -1, 1, 1,
    -1, 1, 1
  ]
  buffer = gl.createBuffer()
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
  gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW)

  const position = gl.getAttribLocation(program, "position")

  gl.enableVertexAttribArray(position)
  gl.vertexAttribPointer(position, 2, gl.FLOAT, false, 0, 0)

  program.resolution = gl.getUniformLocation(program, "resolution")
  program.time = gl.getUniformLocation(program, "time")
}

function loop(now) {
  gl.clearColor(0, 0, 0, 1)
  gl.clear(gl.COLOR_BUFFER_BIT)
  gl.useProgram(program)
  gl.bindBuffer(gl.ARRAY_BUFFER, buffer)
  gl.uniform2f(program.resolution, canvas.width, canvas.height)
  gl.uniform1f(program.time, now * 1e-3)
  gl.drawArrays(gl.TRIANGLES, 0, vertices.length * 0.5)

  requestAnimationFrame(loop)
}

setup()
init()
resize()
loop(0)

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.