Shader examples#
Back to shader guides · Try in playground
Example 1: Fragment, Simple Filter (blue.hlsl)#
Stage: Fragment · Hook: INJECT_BEFORE_RETURN (default)
Simple post-TEV tint: guard with input.position.w, then write prev.rgb.
// Guard check: only apply to 3D perspective elements (ignores 2D HUD/Text)
bool is3D = input.position.w != 1.0f;
if (is3D) {
// Modify the output color: clear red and green channels, keeping blue intact
prev.rgb = float3(0.0f, 0.0f, prev.b);
}
Example 2: Fragment, Screen Space Effect (crt.hlsl)#
Stage: Fragment · Hook: INJECT_BEFORE_RETURN (default)
Screen-space effect: normalized UVs from input.position and _timePad, then modify prev after TEV.
bool is3D = input.position.w != 1.0f;
if (is3D) {
// Normalize absolute screen pixel coordinates to standard [0.0, 1.0] UV range
float2 uv = input.position.xy * float2(_timePad.x, _timePad.y);
// Convert coordinates to centered range [-1.0, 1.0] for radial math
float2 centeredUV = uv * 2.0f - 1.0f;
// Apply CRT Screen Curvature (barrel distortion)
float2 distortion = float2(0.04f, 0.05f); // horizontal and vertical distortion factors
centeredUV.x += (centeredUV.y * centeredUV.y) * distortion.x * centeredUV.x;
centeredUV.y += (centeredUV.x * centeredUV.x) * distortion.y * centeredUV.y;
// Convert back to standard [0, 1] range to sample and clip edges
float2 distortedUV = (centeredUV + 1.0f) * 0.5f;
// Generate outer screen bezel vignette shadow
float2 vignetteUV = centeredUV * centeredUV;
float vign = saturate((1.0f - vignetteUV.x) * (1.0f - vignetteUV.y) * 15.0f);
vign = pow(vign, 0.25f); // Soften the edge
// Only render the screen effects if the warped coordinates land inside visible bounds
if (distortedUV.x >= 0.0f && distortedUV.x <= 1.0f && distortedUV.y >= 0.0f && distortedUV.y <= 1.0f) {
// Generate vertical scanlines based on the screen y coordinate
float scanline = sin(input.position.y * 1.4f) * 0.12f + 0.88f;
prev.rgb *= scanline;
// Phosphor Grid sub-pixels
int pixelX = int(input.position.x);
float3 phosphor = float3(1.0f, 1.0f, 1.0f);
if (pixelX % 3 == 0) {
phosphor = float3(1.08f, 0.85f, 0.85f); // Red sub-pixel boost
} else if (pixelX % 3 == 1) {
phosphor = float3(0.85f, 1.08f, 0.85f); // Green sub-pixel boost
} else {
phosphor = float3(0.85f, 0.85f, 1.08f); // Blue sub-pixel boost
}
prev.rgb *= phosphor;
// Adjust contrast and apply bezel shadow
prev.rgb = saturate(prev.rgb * 1.05f + 0.02f);
prev.rgb *= vign;
} else {
// Outside the screen warp boundaries, draw black bezels
prev.rgb = float3(0.0f, 0.0f, 0.0f);
}
}
Example 3: Fragment, Animated Shader (drunk.hlsl)#
Stage: Fragment · Hook: INJECT_BEFORE_RETURN (default)
Animated screen-space effect using u_time, input.position, and prev after TEV.
#define PI 3.14159265f
bool is3D = input.position.w != 1.0f;
if (is3D) {
float2 uv = input.position.xy * float2(_timePad.x, _timePad.y);
float2 centeredUV = uv * 2.0f - 1.0f;
// Swaying Vignette: drift the vignette center over time using sine/cosine loops (periods of 0.5s and 0.75s)
float2 vigCenter = float2(
sin(u_time * (2.0f * PI / 0.5f)) * 0.12f,
cos(u_time * (2.0f * PI / 0.75f)) * 0.10f
);
float dist = length(centeredUV - vigCenter);
float pulse = sin(u_time * (2.0f * PI / 1.0f)) * 0.03f; // 1.0s period
float vignette = saturate(1.0f - smoothstep(0.4f + pulse, 1.25f + pulse, dist));
// Chromatic double vision wave offsets (shifting coordinate maps over time)
float t = u_time * (2.0f * PI / 2.5f); // 2.5s base wave period
float waveX = sin(centeredUV.y * 8.0f + t) * cos(centeredUV.x * 3.0f - t * 0.5f) * 0.15f;
float waveY = cos(centeredUV.x * 8.0f - t * 1.2f) * sin(centeredUV.y * 3.0f + t * 0.6f) * 0.15f;
// Separate color channel offsets
float rShift = sin((centeredUV.x + waveX) * 25.0f + t) * 0.12f + 0.88f;
float gShift = cos((centeredUV.y + waveY) * 22.0f - t * 0.8f) * 0.12f + 0.88f;
float bShift = sin((centeredUV.x - centeredUV.y + waveX - waveY) * 20.0f + t * 1.3f) * 0.12f + 0.88f;
prev.r *= rShift;
prev.g *= gShift;
prev.b *= bShift;
// Color tint and screen brightness flicker
prev.g *= 1.05f; // Sickly green tint
prev.rgb *= (sin(u_time * (2.0f * PI / 1.111f)) * 0.08f + 0.92f); // ~1.111s pulsing flicker period (frequency 1.8)
// Apply vignette boundary shadow
float3 vignetteColor = float3(0.015f, 0.008f, 0.025f);
prev.rgb = lerp(vignetteColor, prev.rgb, vignette);
prev.rgb = saturate(prev.rgb);
}
Example 4: Vertex, Outline Hull (outline_hull.vs.hlsl)#
Stage: Vertex · Hook: INJECT_BEFORE_TRANSFORM (automatic for .vs.hlsl)
Geometry effect: modifies position along normal in model space before skinning / MV.