# LYGIA Shader Library: Multi-Language Shader Functions You Include, Not Import

> LYGIA is a granular shader library that ships the same functions in GLSL, HLSL, Metal, WGSL and CUDA. It is aimed at graphics programmers who want to prototype and port across engines, and its main constraint is that your toolchain has to resolve #include before the GPU sees the code.

**patriciogonzalezvivo/lygia** — LYGIA, it's a granular and multi-language (GLSL, HLSL, Metal,  WGSL,  WEGL and CUDA) shader library designed for performance and flexibility

- Repository: https://github.com/patriciogonzalezvivo/lygia
- Website: https://lygia.xyz
- Stars: 3,451 · Forks: 223
- Language: GLSL
- License: NOASSERTION
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/patriciogonzalezvivo-lygia

## What LYGIA solves for shader authors who target more than one API

Shader code that works in one API rarely moves to another unchanged. A noise function written for GLSL has to be rewritten for HLSL, then again for Metal, then again for WGSL. LYGIA attacks that by keeping the same functions available in each language and letting you include only the pieces you need. The repository lists math.cuh, math.glsl, math.hlsl, math.msl and math.wgsl at the top level, and the same pattern repeats for sampler and sdf, so a project can move a routine between targets without hunting for a port.

The intended user is someone who already writes shaders and wants a library rather than a framework. The README describes LYGIA as "granular, flexible and efficient" and says it is made of reusable functions. Granularity is the real design decision here: you include lygia/draw/circle.glsl, not the whole draw folder. That keeps generated shader code small, which matters when every unused function still costs compile time in some drivers.

The README also claims LYGIA is "the biggest shader library," which is a marketing line rather than a measurable statement, and it should be read as such. What is verifiable is the breadth of integrations the README links to: Unity, Unreal Engine, three.js, p5.js, openFrameworks, TouchDesigner, Max, Figma, ComfyUI, Minecraft, and an npm package. Those links point at separate repositories and packages maintained by different people, not at code inside this repository.

## How the include-based mechanism works, and why it constrains your build

There is no runtime. LYGIA does not compile, link or execute anything on its own. The README's example shader uses #include directives inside a fragment shader, then calls ratio(), decimate() and circle() as ordinary functions. Resolution happens before the shader reaches the driver, either through your own preprocessor or through the hosted resolver at lygia.xyz.

That split is the whole architecture. The README states you have two options: clone a local version you can bundle into your project, or use the server at https://lygia.xyz to resolve dependencies online. The local route requires your environment to resolve #include dependencies, and the README points at README_GLSL.md for GLSL-specific examples rather than documenting a universal loader. So the integration cost is not in LYGIA, it is in whatever sits between your shader source and the GPU.

The repository also carries a bundling path for WebGPU. package.json defines build:wesl as wesl-packager --multiBundle --outDir dist, and the test scripts run both vitest and wgsl-test. A wesl.toml exists at the top level. That suggests the WebGPU story is more packaged than the GLSL story, where the README leaves resolution to the host. If you are on WebGPU, README_WebGPU.md is the document to read first; if you are on OpenGL or Vulkan, README_GLSL.md is the relevant one.

## Installing LYGIA and rendering a first fragment shader

The npm package is the shortest path if your project already uses a JavaScript bundler. The package metadata declares the entry points, with dist/umd/lygia.main.js as main and dist/module/lygia.main.js as the module field, so both CommonJS-style and ES module consumers are covered.

```bash
npm install lygia
```

After that, the shader still needs #include resolution. The README's local option is a plain clone placed relative to the shader you are loading. The README's own command is truncated in the published text, but the documented form is a git clone of the repository into your project:

```bash
git clone https://github.com/patriciogonzalezvivo/lygia.git
```

With the clone in place, the README's example shader is the first thing to try. It includes three functions, uses ratio() to correct the aspect ratio, decimate() to quantize color, and circle() to add a shape. This is the exact structure the README gives, with the include paths as written there:

```glsl
#ifdef GL_ES
precision mediump float;
#endif

uniform vec2  u_resolution;
uniform float u_time;

#include "lygia/space/ratio.glsl"
#include "lygia/math/decimate.glsl"
#include "lygia/draw/circle.glsl"

void main(void) {
    vec3 color = vec3(0.0);
    vec2 st = gl_FragCoord.xy/u_resolution.xy;
    st = ratio(st, u_resolution);

    color = vec3(st.x,st.y,abs(sin(u_time)));
    color = decimate(color, 20.);
    color += circle(st, .5, .1);

    gl_FragColor = vec4(color, 1.0);
}
```

What you should see is a gradient background quantized into 20 steps with a circle drawn at the center. If the shader fails to compile with an unresolved include, the problem is the loader, not the library. The repository ships sample files such as sample/2DCube.glsl, sample/3DSdf.glsl and sample/dither.glsl, with .hlsl and .wgsl counterparts, so you can compare a working file against your own setup.

## Where LYGIA stops being the right tool

The include model is also the failure mode. Any host that cannot preprocess #include before compilation cannot use LYGIA as shipped. That rules out pasting a shader into a web playground that rejects unknown directives, and it rules out engines whose shader pipeline treats the source as opaque text handed straight to the driver. The README does not document a fallback for those cases; it tells you to make your environment resolve dependencies.

Version skew is the second constraint. The recent releases are 1.4.1 on 2026-02-07, 1.4.0 on 2025-12-18 and 1.3.0 on 2024-11-21. That is a gap of roughly thirteen months between 1.3.0 and 1.4.0. If you vendor a clone into your project, you own the upgrade, and a function you depend on can change between those tags. The README does not document a deprecation policy or a stability guarantee for individual function signatures.

The third case is scale. LYGIA is a library of small functions. If you need a full material system with a node graph, an asset pipeline and a runtime that manages shader permutations for you, LYGIA gives you none of that. It gives you the math, the SDF primitives and the filters, and leaves the surrounding system to you.

## LYGIA compared with a single-language shader utility library

The obvious alternative is a shader utility collection written for one language, typically GLSL, distributed as a header you paste or include. The difference is not quality, it is where the porting cost lands. A single-language library gives you one well-tested copy of a function and no answer when you need the same routine in WGSL. LYGIA gives you parallel files: sdf.glsl, sdf.hlsl, sdf.msl, sdf.wgsl, and the same for math and sampler. You trade a smaller surface for a wider one.

That trade shows up in review. With a single-language library, one file is the source of truth and any divergence is a bug. With LYGIA, each language file is its own artifact, and the repository's test setup reflects that: package.json runs vitest alongside wgsl-test, and test:built rebuilds the WESL bundles before running both test suites with TEST_BUNDLES=true. The test tooling is concentrated on the WGSL and WESL side, which is where the build scripts point. The README does not describe an equivalent automated verification path for the GLSL, HLSL or MSL files, so if you are targeting those languages, plan to verify the specific functions you include in your own scene rather than assuming a test suite covers them.

A second alternative is to write the handful of functions you actually need. For a project that uses one noise function and one SDF, a 40-line file you control beats a dependency you have to vendor and update. LYGIA pays off when the count of functions you need crosses the point where maintaining your own ports across languages costs more than resolving includes.

## Maintenance, upgrade cost and what the licence actually says

The repository is not archived and the last push was on 2026-09-14. That is recent enough that the project is being worked on, but the release cadence is uneven: 1.3.0 landed on 2024-11-21, 1.4.0 on 2025-12-18, and 1.4.1 on 2026-02-07. Commits between releases do not appear as tagged versions, so a clone pulled from main is not the same artifact as a release tarball. If you vendor LYGIA, pin a tag rather than tracking main, and record which tag you took, because the README does not describe a migration guide between versions.

Upgrade cost is mostly mechanical. Because you include individual files, an upgrade is a file-by-file diff, and you can see exactly which functions you consume. The risk is in the functions you include indirectly: ratio.glsl may itself include other files, and those transitive includes are not listed in your shader. The README does not document a dependency listing command, so the reliable way to see the full set is to resolve the includes and inspect the output.

On licensing, the repository's package.json names the license as "Prosperity License & Patron License (https://lygia.xyz/license)" and the repository-level LICENSE.md is the file to read. This is not an OSI-standard identifier, which is why the repository metadata reports NOASSERTION. The practical consequence is that you cannot assume MIT or Apache-2.0 terms, and the terms that do apply are defined on the lygia.xyz license page rather than in a familiar template. Read LICENSE.md and that page before shipping LYGIA inside a commercial product, and if the terms are ambiguous for your use, ask someone qualified to interpret them.

## Conclusion

Adopt LYGIA if you write shaders by hand across more than one target, or if you want a reference implementation of a noise, SDF or filter routine you can read and edit. Do not adopt it if you expect an import statement, a single binary, or a library that hides its source: LYGIA is a directory of .glsl, .hlsl, .msl, .wgsl and .cuh files that your build has to resolve. Before committing, verify that your engine's shader loader handles #include, check whether the WebGPU path applies to you by reading README_WebGPU.md, and read LICENSE.md together with the license page at lygia.xyz, because the npm metadata names the Prosperity License and the Patron License rather than a standard SPDX identifier.

## FAQ

### Does LYGIA work with WebGPU and WGSL?

Yes. The repository ships math.wgsl, sampler.wgsl, sdf.wgsl and version.wgsl alongside the GLSL, HLSL and MSL equivalents, and the README directs WebGPU users to README_WebGPU.md. The package.json build script build:wesl runs wesl-packager --multiBundle --outDir dist, and a wesl.toml sits at the repository root.

### How do I install LYGIA in a JavaScript or TypeScript project?

The npm package is named lygia and installs with npm install lygia. Its package.json exposes dist/umd/lygia.main.js as main, unpkg and jsdelivr, and dist/module/lygia.main.js as the module entry. Installing the package does not resolve #include directives by itself, so you still need a loader that handles them.

### What licence does LYGIA use?

The package.json license field reads "Prosperity License & Patron License (https://lygia.xyz/license)", and LICENSE.md is the repository-level licence file. That is not a standard SPDX identifier, which is why the repository metadata reports NOASSERTION.

### Which shader languages does LYGIA support?

The repository description names GLSL, HLSL, Metal, WGSL, WESL and CUDA. The top-level files confirm this with math.glsl, math.hlsl, math.msl, math.wgsl and math.cuh, plus version files for GLSL, HLSL, WESL and WGSL.

## Sources

- [Issues](https://github.com/patriciogonzalezvivo/lygia/issues)
- [patriciogonzalezvivo/lygia on GitHub](https://github.com/patriciogonzalezvivo/lygia)
- [Project website](https://lygia.xyz)
- [README](https://github.com/patriciogonzalezvivo/lygia/blob/main/README.md)
- [Releases](https://github.com/patriciogonzalezvivo/lygia/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/patriciogonzalezvivo-lygia
