<!DOCTYPE html>

<html lang="en">

<head>

  <meta charset="UTF-8">

  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>Holographic Complex Function Visualization</title>

  <style>

    body, html { margin: 0; padding: 0; overflow: hidden; }

    canvas { display: block; }

  </style>

</head>

<body>

  <canvas id="shaderCanvas"></canvas>

  <script>

    // Vertex Shader (Simple Pass-Through)

    const vertexShaderSource = `

      attribute vec4 position;

      void main() {

        gl_Position = position;

      }

    `;

    // Pixel Shader (Holographic Complex Function Visualization)

    const fragmentShaderSource = `

      precision highp float;

      uniform float time;

      uniform vec2 resolution;

      // Chaotic Attractor (Lorenz System)

      vec3 lorenzAttractor(vec3 pos, float t) {

        float sigma = 10.0;

        float rho = 28.0;

        float beta = 8.0 / 3.0;

        float dx = sigma * (pos.y - pos.x);

        float dy = pos.x * (rho - pos.z) - pos.y;

        float dz = pos.x * pos.y - beta * pos.z;

        return vec3(dx, dy, dz) * 0.01;

      }

      // Complex function: f(z) = z^2 + c

      vec2 complexFunction(vec2 z, vec2 c) {

        return vec2(

          z.x * z.x - z.y * z.y + c.x, // Real part

          2.0 * z.x * z.y + c.y        // Imaginary part

        );

      }

      void main() {

        vec2 uv = gl_FragCoord.xy / resolution.xy; // Normalize coordinates

        uv = uv * 2.0 - 1.0; // Center coordinates

        // Initialize Lorenz attractor for chaotic modulation

        vec3 lorenzPos = vec3(uv.x, uv.y, 0.0);

        for (int i = 0; i < 5; i++) { // Reduced iterations for mobile

          lorenzPos += lorenzAttractor(lorenzPos, time);

        }

        // Use chaotic system to modulate the complex function parameters

        vec2 c = vec2(lorenzPos.x * 0.1, lorenzPos.y * 0.1); // Chaotic parameter

        vec2 z = vec2(uv.x, uv.y); // Input complex number

        // Iterate the complex function to generate intricate patterns

        vec2 result = complexFunction(z, c);

        for (int i = 0; i < 3; i++) { // Reduced iterations for mobile

          result = complexFunction(result, c);

        }

        // Extract real and imaginary parts

        float realPart = result.x;

        float imaginaryPart = result.y;

        // Map real and imaginary parts to color channels

        vec3 color = vec3(

          0.5 + 0.5 * sin(realPart * 10.0 + time), // Red channel (real part)

          0.5 + 0.5 * cos(realPart * 5.0 + time),  // Green channel (real part)

          0.5 + 0.5 * sin(imaginaryPart * 10.0 + time) // Blue channel (imaginary part)

        );

        // Add depth-based shading for a 3D effect

        float depth = length(result); // Magnitude of the complex number

        float depthShading = 1.0 - smoothstep(0.0, 2.0, depth);

        color *= depthShading;

        gl_FragColor = vec4(color, 1.0);

      }

    `;

    // WebGL Setup

    const canvas = document.getElementById('shaderCanvas');

    const gl = canvas.getContext('webgl');

    if (!gl) {

      console.error('WebGL not supported');

      throw new Error('WebGL not supported');

    }

    // Compile Shader

    function compileShader(gl, source, type) {

      const shader = gl.createShader(type);

      gl.shaderSource(shader, source);

      gl.compileShader(shader);

      if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {

        console.error('Shader compile error:', gl.getShaderInfoLog(shader));

        return null;

      }

      return shader;

    }

    // Create Program

    const vertexShader = compileShader(gl, vertexShaderSource, gl.VERTEX_SHADER);

    const fragmentShader = compileShader(gl, fragmentShaderSource, gl.FRAGMENT_SHADER);

    const program = gl.createProgram();

    gl.attachShader(program, vertexShader);

    gl.attachShader(program, fragmentShader);

    gl.linkProgram(program);

    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {

      console.error('Program link error:', gl.getProgramInfoLog(program));

      throw new Error('Program link error');

    }

    gl.useProgram(program);

    // Set Up Buffers

    const positionBuffer = gl.createBuffer();

    gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);

    const positions = [-1, -1, 1, -1, -1, 1, 1, 1]; // Full-screen quad

    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);

    const positionLocation = gl.getAttribLocation(program, 'position');

    gl.enableVertexAttribArray(positionLocation);

    gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);

    // Set Up Uniforms

    const timeLocation = gl.getUniformLocation(program, 'time');

    const resolutionLocation = gl.getUniformLocation(program, 'resolution');

    // Render Loop

    function render(time) {

      time *= 0.001; // Convert to seconds

      gl.uniform1f(timeLocation, time);

      gl.uniform2f(resolutionLocation, canvas.width, canvas.height);

      gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

      requestAnimationFrame(render);

    }

    // Resize Handler

    function resize() {

      canvas.width = window.innerWidth;

      canvas.height = window.innerHeight;

      gl.viewport(0, 0, canvas.width, canvas.height);

    }

    window.addEventListener('resize', resize);

    resize();

    // Start Rendering

    requestAnimationFrame(render);

  </script>

</body>

</html>

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.