Synthwave Shader: How it Works
Related Post: Synthwave Shader
Shader Configuration
shader_type spatial;
render_mode unshaded, depth_draw_always, cull_disabled;
spatial: This indicates it's a 3D shader designed to work with spatial nodes in Godot.unshaded: This mode tells the shader to ignore scene lighting. The colors defined in the shader are the final colors, which is ideal for the flat, glowing look of synthwave grids.depth_draw_always: This ensures the object using this shader is always drawn, regardless of depth testing. This can make the grid appear "on top" of other objects, contributing to the retro effect.cull_disabled: This disables backface culling. Normally, triangles facing away from the camera aren't drawn. Disabling this ensures that if you use this shader on a flat plane, it's visible from both above and below.
Uniform Parameters
These are variables exposed in the Godot editor, allowing you to customize the shader's appearance without editing the code:
grid_color: Sets the color of the grid lines.background_color: Defines the color of the space between the grid lines.line_thickness: Controls the width of the grid lines in world units.grid_spacing: Determines the distance between adjacent grid lines in world units.glow_strength: Adjusts the intensity and falloff of the glow effect around the lines. A higher value creates a sharper, more intense glow.
Vertex Function
varying vec3 world_pos;
void vertex() {
world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
}
- This function runs for each vertex of the mesh the shader is applied to.
- It calculates the vertex's position in world space by transforming the local vertex position (
VERTEX) using the object'sMODEL_MATRIX. - The resulting
world_posis passed to the fragment shader via avaryingvariable. This allows the fragment shader to know the exact world location of the pixel it's currently processing.
Grid Line Function (filtered_grid)
float filtered_grid(float coord, float spacing, float thickness) {
float coord_mod = mod(coord, spacing);
float dist = min(coord_mod, spacing - coord_mod);
float scale = fwidth(coord);
return smoothstep(thickness + scale, thickness - scale, dist);
}
This helper function calculates the intensity of a grid line at a specific coordinate (coord):
mod(coord, spacing): Finds the position within a single grid cell (from 0 tospacing).min(coord_mod, spacing - coord_mod): Calculates the shortest distance from the current point to the nearest grid line boundary within that cell.fwidth(coord): Estimates the change in the coordinate across a single pixel. This is crucial for anti-aliasing.smoothstep(thickness + scale, thickness - scale, dist): Creates a smooth transition between 0 (outside the line) and 1 (inside the line) based on the distance (dist). The range is adjusted byscale(pixel size) andthicknessto create soft edges instead of sharp, aliased lines.
Fragment Shader
float grid_x = filtered_grid(world_pos.x, grid_spacing, line_thickness);
float grid_z = filtered_grid(world_pos.z, grid_spacing, line_thickness);
- Calls the
filtered_gridfunction separately for the world X and Z coordinates to determine the intensity contribution from vertical and horizontal lines, respectively. It ignores the Y coordinate, effectively projecting the grid onto the XZ plane.
float line_intensity = max(grid_x, grid_z);
- Combines the intensities. If a pixel is close to either a horizontal or a vertical line, it takes the maximum intensity, ensuring intersections are bright.
float glow = pow(line_intensity, glow_strength);
- Applies the glow effect. Raising the
line_intensityto the power ofglow_strengthenhances the brightness near the center of the lines and creates a non-linear falloff.
ALBEDO = mix(background_color.rgb, grid_color.rgb, glow);
- Blends between the
background_colorandgrid_colorusing the calculatedglowvalue as the mixing factor. Whereglowis 1, the color isgrid_color; whereglowis 0, it'sbackground_color. Values between 0 and 1 create the smooth gradient effect.ALBEDOis the final base color output for the pixel.
ALPHA = 1.0;
- Sets the pixel's opacity to fully opaque.
Summary
This shader effectively:
- Draws an infinite 2D grid projected onto the XZ plane in world space.
- Uses world-space coordinates, so the grid remains stationary as objects move through it.
- Creates glowing lines with customizable color, thickness, spacing, and glow intensity.
- Implements anti-aliasing using
fwidthandsmoothstepfor clean, smooth line edges. - Renders independently of scene lighting (
unshaded) and can draw over other objects (depth_draw_always), making it suitable for stylized retro or sci-fi visuals, particularly for ground planes.
Full Shader Code
Here is the complete Godot shader code (.gdshader file):
shader_type spatial;
render_mode unshaded, depth_draw_always, cull_disabled;
uniform vec4 grid_color : source_color = vec4(0.0, 0.3, 0.8, 1.0);
uniform vec4 background_color : source_color = vec4(0.02, 0.0, 0.05, 1.0);
uniform float line_thickness = 0.02;
uniform float grid_spacing = 2.5;
uniform float glow_strength = 1.3;
varying vec3 world_pos;
void vertex() {
world_pos = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
}
float filtered_grid(float coord, float spacing, float thickness) {
float coord_mod = mod(coord, spacing);
float dist = min(coord_mod, spacing - coord_mod);
float scale = fwidth(coord);
return smoothstep(thickness + scale, thickness - scale, dist);
}
void fragment() {
float grid_x = filtered_grid(world_pos.x, grid_spacing, line_thickness);
float grid_z = filtered_grid(world_pos.z, grid_spacing, line_thickness);
float line_intensity = max(grid_x, grid_z);
float glow = pow(line_intensity, glow_strength);
ALBEDO = mix(background_color.rgb, grid_color.rgb, glow);
ALPHA = 1.0;
}