---
title: "GZDoom Cross-Hatch Shader"
url: https://manvsmidi.com/projects/gzdoom-crosshatch/
category: graphics
status: writeup
date: 2026-02-16
tags: [doom, shaders, glsl, npr]
related: [ascension-buffer, doom-claude]
---

# GZDoom Cross-Hatch Shader

> A non-photorealistic post-process for GZDoom that turns scene brightness into pen-and-ink hatching, with optional Sobel outlines and every knob exposed as a CVar.

Graphics · Write-up · 2026-02-16

This is a configurable post-process NPR style for GZDoom. Scene luminance becomes hatch density, optional Sobel outlines add ink definition, and the whole look can be toggled at runtime through CVars.

![Hatch density increasing in darker areas](https://manvsmidi.com/_astro/hatch-2.CUlOT_3_.jpg)
*Mid-to-dark density progression with optional outline emphasis.*

![Hatch, softness and grain combined](https://manvsmidi.com/_astro/hatch-3.DcbhH0O2.jpg)
*Combined hatch, softness, and grain controls tuned for readability.*

## Goal

Deliver a comic/etching visual treatment that is practical in actual gameplay: readable, adjustable, and easy to distribute as a single PK3.

The current scope prioritizes a robust screen-space implementation over deeper material-level integration. In v0-M3 the effect is intentionally post-process only. That keeps compatibility high on stock GZDoom hardware renderers and avoids the complexity of per-material world-space hatching.

## Pipeline

- `GLDEFS` registers `hatch.fp` as a post-process shader and binds CVar uniforms.
- `CVARINFO` exposes runtime controls for hatch, breakup, tone, and outlines.
- `MAPINFO` and `ZSCRIPT.lmp` register `HatchHandler` for integration.
- `shaders/PostProcess/hatch.fp` computes the full NPR stylization pass.

## Shader approach

1. Sample `InputTexture` and compute luminance.
2. Quantize darkness into configurable bands (`hatch_bands`).
3. Build procedural hatch masks from stripe functions plus breakup layers: `hatch_stipple`, `hatch_grain`, and `hatch_jitter`.
4. Increase dark-area density with adaptive scale (`hatch_dark_density`).
5. Apply optional 3-tap smoothing (`hatch_softness`) to reduce shimmer.
6. Composite ink with scene/base tone using `hatch_strength`, `hatch_bw`, and `hatch_flat_tone`.
7. Optionally add Sobel outlines via `outline_enable`, `outline_strength`, and `outline_threshold`.

## Limitations

- **Resolution-bound line quality.** Hatch detail is pixel-space (`gl_FragCoord`), so low render resolutions collapse strokes and high resolutions can reveal aliasing unless retuned.
- **Motion shimmer and moiré.** Repeated line frequencies can alias in camera motion; softness and breakup help but don't fully remove temporal artifacts.
- **Screen-space drift.** Patterns don't lock to world geometry/UVs, so hatching can slide over surfaces during viewpoint changes.
- **Global coverage.** The effect applies scene-wide, including HUD and sprites, which requires careful strength tuning for readability.
- **NPR is subjective.** There's no single correct stylization across all maps and lighting conditions; scene-specific CVar adjustments remain part of production use.

## Connected projects

- [Ascension Buffer](https://manvsmidi.com/projects/ascension-buffer/index.md): linked
- [DOOM-CLAUDE Monitor](https://manvsmidi.com/projects/doom-claude/index.md): shared tags: doom
