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:
Starry Planes (opens in a new tab) by mrange (opens in a new tab)
Creating Your First Shader
Follow these steps to create your own Shader Element in Hatch:
-
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]
-
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]
-
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 }
-
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 }
-
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
-
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));
-
Set the Output Color Assign the final color to
fragColor
:fragColor = vec4(col, 1.0);
-
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
-
Copy the instructions. Select all the text on this page and copy it to your clipboard. Shortcut: Press
Ctl/Cmd+a
to select all, thenCtl/Cmd+c
to copy. -
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.
-
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.
- 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 pickerfloat
uniforms: Slider and numeric inputsampler2D
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) orOption
(a list of options)default
: Sets the default value. Default Color values can be in any CSS color format.title
: Provides a user-friendly label in the UI
Number parameters (only applicable to float
and int
types):
min
/max
: Defines the range for numeric inputsstep
: Sets the increment for numeric inputsscalingFactor
: Applies a scaling factor to the input valuedecimalPlaces
: Controls the number of decimal places displayed
Option parameters (only applicable to Option
type):
options
: A list of options for the uniform. Usage:type: Option, options: { cover: 1, contain: 2, "scale down": 3 }, default: 1
sampler2D
parameters (only applicable to sampler2D
type):
filter
: Specifies the texture filtering mode.nearest
,linear
ormipmap
(default:mipmap
)wrap
: Specifies the texture wrapping mode.repeat
,mirror
, orclamp
(default:repeat
)vflip
: Flips the texture vertically (default:true
)
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 0uniform sampler2D iChannel1
: Input texture channel 1uniform sampler2D iChannel2
: Input texture channel 2uniform sampler2D iChannel3
: Input texture channel 3uniform vec3 iChannelResolution[4]
: Channel resolution (in pixels)uniform vec4 iMouse
: Mouse pixel coords. xy: current, zw: clickuniform int iFrame
: Shader playback frame
Remaining Shadertoy uniforms (coming soon):
uniform float iFrameRate
: Shader playback frame rateuniform float iChannelTime[4]
: Channel playback time (in seconds)uniform vec4 iDate
: Year, month, day, time in secondsuniform 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 xfloat 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 interpolationvec3 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!