Pixelated Portal
A small shader using the stencil buffer to create a portal effect whose edges are pixelated. While simple portals can be created using Godot’s StandardMaterial shader alone, that approach renders the portal over the entire surface of the geometry. This custom shader allows the edges of the portal to be any arbitrary shape defined by the mask.
This effect has been tested to work even in web exports.
Parameters
- mask – The texture to mask the portal area. Transparent pixels are ignored while opaque pixels become part of the portal. Only the alpha channel is used.
- mask_threshold – Sets the lowest alpha value a pixel in the mask texture can be for it to be part of the portal.
Scene setup
To use this shader:
- Create a PNG mask texture where opque areas represent the portal surface and (color does not matter).
- Add a plane mesh (or particle) to the scene and apply this shader as its material and set the mask parameter to the created texture (it is normal for the geometry to disappear in editor).
- Add the geometry you only want to see through the portal to the scene.
- Give that geometry a standard material with the following settings:
- transparency: Alpha
- stecil_mode: Custom
- stencil_flags: Read
- stencil_compare: Equal
- stencil_reference: 1
- render_priority: 1
- (optional) If your mask texture is semi-transparent, adjust the mask_threshold parameter of the shader until only the pixels you want to be part of the portal are used.
Explanation
A stencil buffer is like a second screen that stores an 8-bit value for each pixel instead of a color. Any shader can read and write to this buffer while being rendered. Shaders with a lower render priority are drawn first and thus can write values to the stencil buffer that shaders with a higher render priority can read later. By writing a non-zero value to the stencil buffer in lower-priority shader, the higher-priority shader can read the value of the buffer at that screen position and decide whether to render its color or not.
Godot’s StandardMaterial shader already provides comparison logic to conditionally render based on the value of the stencil buffer so this custom shader is only required to set the stencil buffer. Normally, a Godot shader set to write to the stencil buffer will write the same value to every pixel covered by the geometry (even if it is transparent); however, you can tell Godot to completely ignore a pixel, and thus not set the stencil buffer for it, using the discard keyword. This shader simply compares the transparency of a given mask texture and discards any pixel below an opacity threshold.
Shader code
shader_type spatial;
render_mode unshaded, cull_disabled;
stencil_mode write, 1;
/** The mask defining the portal area. Solid pixels become the portal area. */
uniform sampler2D mask: hint_default_transparent, filter_nearest;
/** The minimum transparency of a mask pixel considered part of the portal. */
uniform float mask_threshold = 0.5;
void fragment() {
float mask_alpha = texture(mask, UV).a;
if (mask_alpha >= mask_threshold) {
// Hide portal pixels so the stencil is set but not blocked by the mask.
ALPHA = 0.0;
} else {
// Do not set the stencil buffer for pixels not part of the portal.
discard;
}
}



