Skip to content

Real-time generative shader experience rendering infinite abstract landscapes through WebGL2. Built with logarithmic-polar transformations and procedural color mapping, featuring a live GLSL editor for real-time shader modification.

License

Notifications You must be signed in to change notification settings

QC20/hallucinatory-phantasmagoria

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Hallucinatory Phantasmagoria

A real-time generative shader experience that transforms your browser into an infinite, breathing abstract landscape. Built entirely with WebGL2, the project renders complex procedural forms directly on the GPU through fragment shader computations, creating saturated dreamlike patterns that evolve continuously across the screen.

What It Does

The experience maps screen-space coordinates into a logarithmic-polar domain, then applies a series of mathematical transformations including folding, distortion, and time-based rotations. The result is a looping visual field where geometric patterns ripple and breathe, their colors derived from procedural hue functions and luminance-based tone mapping.

Everything happens in real-time on your graphics card. No pre-rendered assets, no image files. Just mathematics and light.

The Mathematics Behind It

At the core of the rendering pipeline sits a coordinate transformation that converts Cartesian screen positions into logarithmic-polar space. This transformation allows the shader to create infinite recursive patterns from finite screen coordinates.

float d = length(uv) / MN;
uv = vec2(log(d), 0.205 + atan(uv.x, uv.y)) * 8.0 / PI;

The logarithm of the distance creates a radial scaling effect where patterns appear to zoom infinitely inward or outward. The arctangent component wraps angular information around this radial axis, establishing the rotational symmetry you see in the forms.

Time drives multiple transformation layers. A rotation matrix modulates with both sine and exponential functions:

uv *= mat2(cos(sin(T*0.2) - vec4(0,11,33,0))) * exp(cos(T)*0.321) * (0.7 + 0.5*cos(T*0.5));

This creates the breathing, pulsing quality as geometric forms expand and contract. The multiplication by different phase-shifted cosine values ensures the scaling never settles into a simple periodic loop.

Color generation uses a custom hue function that maps scalar values to RGB through phase-shifted sine waves:

#define hue(a) (0.5 + 0.5*sin(PI*(a) + vec3(1,2,3)))

This produces saturated colors across the spectrum without requiring lookup tables or color space conversions. The final color passes through a hyperbolic tangent function for tone mapping, compressing the dynamic range while preserving the vivid saturation.

Fragment shader visualization

Fragment shaders process each pixel independently, enabling parallel computation of complex visual effects

Live Shader Editor

Press Ctrl+L to toggle the built-in GLSL editor. The interface provides syntax-aware editing with auto-indentation, tab handling, and real-time error reporting. When you modify the shader source, changes compile and deploy to the GPU with debounced hot-reload, letting you experiment with the mathematics while the experience runs.

The editor tracks cursor position to maintain proper scroll state even as you insert line breaks or indentation. Error messages display with line-number precision, and a visual indicator points to the problematic line in your source.

Shader state persists to localStorage, so your modifications survive page reloads. This makes it practical to develop and refine shaders entirely within the browser environment.

Customization Possibilities

You can reshape the entire visual character by modifying key parameters in the fragment shader. Here are some starting points:

Time scaling affects how quickly patterns evolve. Change T*1.5 to T*0.5 for slower, more meditative motion. Increase it to T*3.0 for rapid morphing forms.

Rotation matrices determine how the coordinate space twists and folds. The current implementation uses cos(sin(T*0.2) - vec4(0,11,33,0)). Try replacing this with cos(T + vec4(0,11,33,0)) for smoother, more predictable rotations. Or use cos(T*T*0.1 - vec4(0,11,33,0)) for accelerating temporal dynamics.

Color mapping can shift entirely by modifying the hue function input. The current hue(l*l - T*0.5) creates colors that pulse with the geometric forms. Change it to hue(l + T) for colors that sweep through the spectrum independently of the geometry. Using hue(atan(uv.x, uv.y)) would map colors radially around the center point.

Domain repetition is controlled by the modulo operation mod(uv, 2.0) - 1.0. Changing the 2.0 to 4.0 doubles the size of the repeated cells, creating larger, more expansive patterns. Values below 1.0 create dense, intricate tiling.

Vignette intensity affects the edge darkening. The current power value of 0.3 in pow(vig, 0.3) creates a subtle gradient. Increase it to 0.8 for sharper falloff, or reduce it to 0.1 for barely perceptible edge dimming.

These aren't just parameter tweaks. Each modification reshapes the mathematical relationships that generate the forms, leading to genuinely different visual systems. A simple change to the rotation matrix phase can transform smooth spirals into jagged crystalline structures.

Shader art examples showing different mathematical transformations

Different mathematical transformations create vastly different visual systems from the same rendering pipeline

Technical Architecture

The project separates concerns across several specialized classes:

Renderer manages the WebGL2 context, compiles shaders, and drives the render loop. It exposes methods for testing shader validity before deployment, preventing broken states from reaching the GPU.

PointerHandler normalizes mouse and touch input into the shader's coordinate system. It maintains a map of active pointers for multi-touch support and calculates movement deltas for interactive effects.

Editor provides the GLSL editing environment with keyboard handling for indentation, line breaks, and tab management. It uses DOM measurement to position error indicators at the correct line offsets.

Store persists shader source to localStorage using base64-encoded keys derived from the page location. This allows multiple shader projects to coexist without namespace collisions.

The render loop runs through requestAnimationFrame, passing current time, resolution, and pointer data as uniforms to the fragment shader. The shader has access to these inputs:

  • time - elapsed milliseconds converted to seconds
  • resolution - canvas dimensions in pixels
  • touch - primary pointer coordinates
  • pointers - array of all active touch/mouse positions
  • pointerCount - number of simultaneous touches
  • move - accumulated movement deltas

Running Locally

Open index.html in a modern browser that supports WebGL2. No build process, no dependencies, no server required. The experience runs entirely client-side.

If you want to work with the repository: git clone https://github.com/ionas/hallucinatory-phantasmagoria.git

License

MIT License - see LICENSE file for details.

About

Real-time generative shader experience rendering infinite abstract landscapes through WebGL2. Built with logarithmic-polar transformations and procedural color mapping, featuring a live GLSL editor for real-time shader modification.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published