Shaders

Shaders

Overview

Welcome to the exciting world of shaders in Hatch! Shaders are powerful GPU programs that enable you to create stunning visual effects, process images, and generate graphics with high performance. In Hatch, Shader Elements allow you to harness this power directly within your projects, responding to various inputs like time, mouse position, and scroll progress for interactive and animated designs.

Shader Elements seamlessly integrate with Hatch's full suite of interactivity and animation features, including Visual Scripting, Animation Effects, and JavaScript integration.

Moreover, like all Hatch projects, Shader Elements are portable, allowing you to embed them in other web creation tools like WordPress, Wix, and Webflow.

Hatch's Shader Editor is built on Monaco Editor (opens in a new tab), the same technology that powers Visual Studio Code. We've enhanced it with features tailored for shader development, including syntax highlighting, code completion, and error reporting. This creates a responsive "live coding" environment that updates the visual output as you type and generates a simple UI for adjusting parameters. These features make shader development in Hatch efficient, accessible, and fun!

Understanding Shaders

Hatch provides a collection of pre-built shaders that you can add to your project with a single click, complete with simple controls for customization. which can be added to a project with a click and provide simple controls for customization. If you have coding experience — or are comfortable using AI tools that generate code — you can also create your own custom shaders.

Shaders are written in GLSL (OpenGL Shading Language), which is similar to the C programming language. If you have programming experience, you'll find the syntax familiar. If you're new to coding, don't worry – we'll guide you through the process step-by-step.

Here's an example of a Shader Element in action:

Creating Your First Shader

Follow these steps to create your own Shader Element in Hatch:

  1. Add a Shader Element to Your Project

    • In the Hatch editor, click on the "Add Element" button.
    • Select "Shader" from the list of available elements. [TODO: Add a screenshot or steps to create a new Shader Element in Hatch]
  2. Open the Shader Editor With the Shade Element selected, click the edit button in the properties panel. [TODO: Include a screenshot of the Shader Editor interface]

  3. Write Your Shader Code Every shader must have a mainImage function. This is the entry point for your shader:

    void mainImage( out vec4 fragColor, in vec2 fragCoord )
    {
        // Your shader code goes here
    }
  4. Declare Uniforms (Optional) Uniforms allow you to create controllable parameters for your shader. Use special comments to provide information for the UI:

    uniform float angle; // default: 0.0, min: 0.0, max: 360.0
    uniform vec4 color1; // default: red, type: Color, title: "Primary Color"
    uniform bool useEffect; // default: true, title: "Apply Effect"
    uniform int option; // default: 1, type: Option, options: { cover: 1, contain: 2, "scale down": 3 }
  5. Utilize Built-in Uniforms Hatch provides several built-in uniforms for common use cases:

    vec2 uv = fragCoord / iResolution.xy; // Normalized pixel coordinates (0.0 - 1.0)
    float time = iTime; // Current time in seconds
  6. Perform Calculations Use GLSL functions and your own algorithms to calculate color values:

    vec3 col = 0.5 + 0.5 * cos(time + uv.xyx + vec3(0, 2, 4));
  7. Set the Output Color Assign the final color to fragColor:

    fragColor = vec4(col, 1.0);
  8. Iterate and Experiment Take advantage of Hatch's live-coding environment to see your changes in real-time. Experiment with different functions, colors, and effects to create unique visuals.

A Complete Shader Example

Here's a simple shader that creates a colorful, animated pattern with controls for animation speed and base color:

uniform float speed; // default: 1.0, min: -10, max: 10, step: 0.1, title: "Animation Speed"
uniform vec4 baseColor; // default: #3320ff, type: Color, title: "Base Color"
 
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
    vec2 uv = fragCoord / iResolution.xy;
    vec3 col = 0.5 + 0.5 * cos(iTime * speed + uv.xyx + vec3(0, 2, 4));
    fragColor = vec4(col, 1.0) * baseColor;
}

And here's how it looks:

Generating Shaders with AI

You can leverage AI tools like ChatGPT or Claude.ai to generate shaders for you. Here's how

  1. Copy the instructions. Select all the text on this page and copy it to your clipboard. Shortcut: Press Ctl/Cmd+a to select all, then Ctl/Cmd+c to copy.

  2. Paste into the AI Tool. Open your prefered AI tool and paste the instructions. Both Claude.ai (Claude 3.5 Sonnet) and ChatGPT.com (4o or o1-preview) have been tested to work.

  3. Add your prompt. Try one of these prompts:

    • Generate a cool shader with a time-based animation.
    • Generate an image effect shader that makes everything look like its underwater.
    • Generate a shader that uses the mouse position to create an interactive effect.

Alternatively, you can copy/paste an existing, permissively licensed, shader from Shadertoy (opens in a new tab) and ask the AI to add uniforms for customization. Remember to include this page of instructions. Prompt like so:

  • Add some uniforms to this shader so it can be interactively customized. Do not leave out any functions or comments. Follow the instructions for how to create a Hatch Shader Element.
  1. Copy the output to Hatch's Shader Editor. Copy the shader code generated by the AI and paste it into Hatch's Shader Editor, replacing any pre-existing code.

That's it!

Automatic Uniform User Interface

Hatch intelligently analyzes the uniforms declared in your shader and generates a simple user interface for real-time adjustments. The UI adapts based on the uniform type:

  • vec3/4 color uniforms: Color picker
  • float uniforms: Slider and numeric input
  • sampler2D uniforms: Image/Video picker (defaults to a transparent pixel if no image is selected)
  • bool uniforms: An on/off switch

Uniform Customization Syntax

Use comments to customize the UI for each uniform:

uniform float angle; // default: 0.0, min: 0.0, max: 360.0
uniform vec4 color1; // default: red, type: Color, title: "Primary Color"
uniform sampler2D texture1; // title: "Background Texture"
uniform float opacity; // default: 1.0, min: 0.0, max: 1.0, step: 0.01, scalingFactor: 100, decimalPlaces: 2, title: "Opacity"
uniform bool useEffect; // default: true, title: "Apply Effect"

Available parameters:

  • type: Specifies the input type. Color (a color picker) or Option (a list of options)
  • default: Sets the default value. Default Color values can be in any CSS color format.
  • min / max: Defines the range for numeric inputs
  • step: Sets the increment for numeric inputs
  • title: Provides a user-friendly label in the UI
  • scalingFactor: Applies a scaling factor to the input value
  • decimalPlaces: Controls the number of decimal places displayed
  • options: A list of options for the uniform. Only applicable for Option type. Usage: type: Option, options: { cover: 1, contain: 2, "scale down": 3 }, default: 1

Built-in Uniforms

Hatch provides several Shadertoy-compatible uniforms available in every shader:

  • uniform vec3 iResolution: Viewport resolution (in pixels)
  • uniform float iTime: Shader playback time (in seconds)
  • uniform float iTimeDelta: Render time (in seconds)
  • uniform sampler2D iChannel0: Input texture channel 0
  • uniform sampler2D iChannel1: Input texture channel 1
  • uniform sampler2D iChannel2: Input texture channel 2
  • uniform sampler2D iChannel3: Input texture channel 3
  • uniform vec3 iChannelResolution[4]: Channel resolution (in pixels)
  • uniform vec4 iMouse: Mouse pixel coords. xy: current, zw: click
  • uniform int iFrame: Shader playback frame

Remaining Shadertoy uniforms (coming soon):

  • uniform float iFrameRate: Shader playback frame rate
  • uniform float iChannelTime[4]: Channel playback time (in seconds)
  • uniform vec4 iDate: Year, month, day, time in seconds
  • uniform float iSampleRate: Audio sample rate (in Hz)

Additional Hatch uniforms:

  • uniform float iX: Element x position, in pixels.
  • uniform float iY: Element y position, in pixels.
  • uniform vec2 iMouseVelocity: Mouse velocity, in pixels per second.
  • uniform vec2 iScrollVelocity: Scroll velocity, in pixels per second.

Automatic Resolution Uniforms

When a sampler2D uniform is detected, Hatch automatically adds a matching Resolution uniform for it. For example, if you declare a uniform sampler2D image1; in your shader, Hatch will also add a uniform vec3 image1Resolution; uniform for you with it's x and y components set to the width and height of the image in pixels.

Image Fitting

By adding the iImageFit uniform to your shader and calling the fit or extended texture function, you can control how images are resized to fit the canvas while preserving their aspect ratio.

uniform int iImageFit; // title: "fit", default: 1, type: Option, options: { fill: 0, cover: 1, contain: 2, "scale down": 3, none: 4 }

The default value is cover, which scales the image to fill the container while maintaining its aspect ratio. Other options include fill, contain, scale down, and none.

Once the uniform is set, you can use the fit function in your shader to map uv coordinates based on iImageFit or Or you can use the extended texture function to sample a remapped texture directly.

The fit function takes a vec2 for the uv coordinates and a vec3 for the resolution and an int for the fit mode.

The extended texture function takes a sampler2D, a vec2 for the uv coordinates and a vec3 for the resolution and an int for the fit mode. A final, optional bool parameter specifies whether out of bounds pixels should be clamped or transparent.

Function signatures:

vec2 fit(vec2 uv, vec3 resolution, int fitMode);
vec4 texture(sampler2D image, vec2 uv, vec3 resolution, int fitMode, bool transparent);

Example usage:

// Map the uv coordinates to fit the image then sample with `texture`.
vec2 uv = fit(fragCoord / iResolution.xy, imageResolution, iImageFit);
uv = fit(fragCoord / iResolution.xy, iChannelResolution[0], iImageFit);
vec4 color = texture(image, uv);
 
// Combined coordinate mapping and texture sampling with a single function call.
vec4 color = texture(image, fragCoord / iResolution.xy, imageResolution, iImageFit, true);
color = texture(iChannel0, fragCoord / iResolution.xy, iChannelResolution[0], iImageFit, true);

Note: Avoid using property names, like scale, color, backgroundColor, x or y as uniform names unless you intend to use the corresponding property values as the uniform value.

Essential GLSL Functions

GLSL provides a rich set of built-in functions for mathematical calculations, vector operations, and more. Here are some commonly used ones:

Mathematical Functions

  • float abs(float x)
  • float sin(float angle)
  • float cos(float angle)
  • float pow(float x, float y)
  • float sqrt(float x)
  • float floor(float x)
  • float ceil(float x)
  • float fract(float x) // Fractional part of x
  • float mod(float x, float y) // Modulo operation

Vector Operations

  • float length(vec2/vec3/vec4 x)
  • float distance(vec2/vec3/vec4 p0, vec2/vec3/vec4 p1)
  • vec3 normalize(vec3 v)
  • float dot(vec3 v1, vec3 v2)
  • vec3 cross(vec3 v1, vec3 v2)
  • vec3 reflect(vec3 I, vec3 N)

Texture Sampling

  • vec4 texture(sampler2D sampler, vec2 coord)

Utility Functions

  • float min(float x, float y)
  • float max(float x, float y)
  • float clamp(float x, float y, float a)
  • float mix(float x, float y, float a) // Linear interpolation
  • vec3 mix(vec3 x, vec3 y, float a)

For a comprehensive list of GLSL functions, refer to the GLSL specification (opens in a new tab) or the OpenGL ES 3.0 quick reference card (opens in a new tab) (page 4).

Next Steps

Now that you're familiar with the basics of Shader Elements in Hatch, try creating your own! Experiment with different effects, combine multiple shaders, and integrate them into your projects. Don't hesitate to consult the Hatch community forum (opens in a new tab) for more advanced techniques and inspiration.

Happy shader coding!