HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
Lichtso
contrast_renderer
Rust2022–2026
Lichtso / contrast_renderer

contrast_renderer

Contrast is a WebGPU based 2D render engine written in Rust

3Distinct people
9Mentions
0Explicit recommenders
87GitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

Contrast is a WebGPU based 2D render engine written in Rust

GitHub

Where it is used

No documented product use has been verified yet.

What people are saying

No recommendation phrase was found in the indexed comments.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

No other repository is repeatedly linked in the same discussions.

This week on Hacker News

Nov 7–Nov 14 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/14/2026, 3:56:07 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year9 dated mentions

Observed mentions: 2022-08-10 20:01:04 UTC to 2026-03-19 00:37:36 UTC.

01232022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 3 mentions; 0 submissions, 3 comments20222023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments2024-01-01 00:00:00 UTC to 2025-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments20242025-01-01 00:00:00 UTC to 2026-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2026-01-01 00:00:00 UTC to 2027-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments. Incomplete calendar period.2026*

* An incomplete calendar period is marked with an outlined bar. Its count is not directly comparable with a full period.

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC303
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC101
20242024-01-01 00:00:00 UTC2025-01-01 00:00:00 UTC202
20252025-01-01 00:00:00 UTC2026-01-01 00:00:00 UTC202
2026 (partial)2026-01-01 00:00:00 UTC2027-01-01 00:00:00 UTC101

What Hacker News says

9 sources
> [1] and [2] sound similar to what you are describing. They still involve triangulating the shape, but the triangulation process seems much simpler Yes, they describe one variation of the angle based method to winding numbers by spanning a triangle fan from an arbitrarily chosen pivot point / vertex. > if you want to do distance based anti-aliasing rather than supersampling Particularly when it comes to rendering vector graphics I think of analytic anti-aliasing methods as somewhat cursed and prefer multisampling [0], at least for magnification. For minification mip-mapping remains the go to solution. However, if you only render 2D text on a 2D plane, which is typically overlap free, then these correctness issues don't matter. > I don't see a straightforward way to apply this technique in a pixel shader that includes multiple curves per
Read the rest
triangle All modern vector renderers I know of avoid triangle rasterization entirely. Like I said, they typically do tiles (screen space partitioned into quads) in a compute shader instead of using the fixed functionality with a fragment / pixel shader. The reason is that nowadays compute is cheap and memory bandwidth is the bottle neck. Thus, it makes sense to load a bunch of overlapping geometry from global memory into workgroup shared memory, render all of it down to pixels in workgroup shared memory, and then only write these pixels back to the framebuffer in global memory. > I feel like any attempt to do that will approach the complexity of Slug A highly optimized implementation might very well, yes. Yet, handling the many cases of intersections of the path and the scanline won't be contributing to the complexity, which is what started this discussion. > I would love to read more detailed information on that if you have it. I implemented the outdated stencil buffer + triangle fan + implicit curves approach [1] if you want to take a look under the hood. The library is quite complex because it also handles the notoriously hard rational cubic bezier curves analytically, which Slug does not even attempt and just approximates. But the integral quadratic bezier curves are very simple and that is what is comparable to the scope Slug covers. It is just a few lines of code for the vertex shader [2], the fragment shader [3] and the vertex buffer setup [4]. Edit: You can even spin loop & blinn into a scanline method / hybrid: They give you the side of the curve your pixel is on [5], which is typically also the thing scanline methods are interested in. They compute the exact intersection location relative to the pixel, only to throw away most of the information and only keep the sign (side the pixel is on). So, that might be the easiest fragment shader vector renderer possible. Put it together in a shader toy [6] a while back. [0]: https://news.ycombinator.com/item?id=46473247#46530503 [1]: https://github.com/Lichtso/contrast_renderer [2]: https://github.com/Lichtso/contrast_renderer/blob/main/src/s... [3]: https://github.com/Lichtso/contrast_renderer/blob/main/src/s... [4]: https://github.com/Lichtso/contrast_renderer/blob/main/src/f... [5]: https://news.ycombinator.com/item?id=45626037#45627274 [6]: https://www.shadertoy.com/view/fsXcDj
In A Decade of Slug
> "a³-bcd ≤ 0" formula These are the coefficients of the implicit curve, finding them can be done once upfront. For integral quadratic bezier curves that is trivial as they are constant, see: https://www.shadertoy.com/view/fsXcDj For rational cubic bezier curves it is more involved, see: https://www.shadertoy.com/view/ttVfzh And for the full complexity of dealing with self intersecting loops and cusps see: https://github.com/Lichtso/contrast_renderer/blob/main/src/f... > The winding number logic is usually super involved, especially when multiple sub-shapes start overlap and subtracting each other. Is this covered or orthogonal to what you are talking about? Orthogonal: The implicit curve only tells you if you are inside or outside (the sign of the SDF), so that is technically sufficient, but usually you want more things: Some kind of ant
Read the rest
i-aliasing, composite shapes of more than one bezier curve and boolean operators for masking / clipping. Using the stencil buffer for counting the winding number allows to do all of that very easily without tessellation or decomposition at path intersections. > Can you elaborate on it or provide resources? If you are interested in the theory behind implicit curve rendering and how to handle the edge cases of cubic bezier curves checkout these papers: Loop, Charles, and Jim Blinn. "Resolution independent curve rendering using programmable graphics hardware." https://www.microsoft.com/en-us/research/wp-content/uploads/... BARROWCLOUGH, Oliver JD. "A basis for the implicit representation of planar rational cubic Bézier curves." https://arxiv.org/abs/1605.08669
In Fast calculation of the distance to cubic Bezier curves on the GPU
> The next step is to work with chains of Bézier curves to make up complex shapes (such as font glyphs). It will lead us to build a signed distance field. This is not trivial at all and mandates one or several dedicated articles. We will hopefully study these subjects in the not-so-distant future. If you only want to fill a path of bezier curves (e.g. for text rendering) you can do without the "distance" part from "signed distance field" [0], leaving you with a "signed field" aka. an implicit curve [1]. Meaning not having to calculate the exact distance but only the sign (inside or outside) can be done without all the crazy iterative root finding in an actually cheap manner with only four multiplications and one addition per pixel / fragment / sample for a rational cubic curve [3]. [0]: https://en.wikipedia.org/wiki/Signed_distance_functi
Read the rest
In Fast calculation of the distance to cubic Bezier curves on the GPU
Hey, i'm brainstorming for a 3d vector renderer in WebGPU on JS/TS and stumbled on your project [0] yesterday. (Thick) line drawing is especially interesting to me, since it's hard [1]. I also stumbled upon this [2] recently and then wondered if i could use that technique for every shape, by converting it to quadratic bezier curve segments. Do you think that's a path to follow? [0] https://github.com/Lichtso/contrast_renderer [1] https://mattdesl.svbtle.com/drawing-lines-is-hard [2] https://scribe.rip/@evanwallace/easy-scalable-text-rendering...
In AAA – Analytical Anti-Aliasing
This is true, but there is a lot more to the story. For one, WebGPU does not (yet) support mesh shaders, though it may later as an extension. For two, consider a glyph such as "o" that has two contours. Real triangulation generates a mesh that only generates triangles between the outer and inner contours, and mesh shaders aren't good at that. There are techniques compatible with mesh shaders (cover and stencil) that draw twice, incrementing and decrementing a winding number stored in the stencil buffer (see contrast renderer[1] for a clean modern implementation), but it does require nontrivial tracking on the CPU side, and can result in lots of draw calls to switch between the cover and stencil stages unless sophisticated batching is done. (The outer contour is drawn as a disc with winding number +1, and the inner contour is drawn as a sm
Read the rest
aller disc with winding number -1, so the inner part ends up as 0) Compute shaders avoid all these problems and work on WebGPU 1.0 today. [1]: https://github.com/Lichtso/contrast_renderer
In WebGPU Fundamentals

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.