elkraneo / lygia

lygia, it's a granular and multi-language shader library designed for performance and flexibility

Home Page:https://lygia.xyz

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

LYGIA Shader Library

Tired of searching for the same functions over and over? or to port and reimplementing them between platforms and shader languages? LYGIA is shader library of reusable functions that can be include easily on your projects. Doesn't matter the shader language, if they run local or on the cloud. LYGIA is very granular, designed for reusability, performance and flexibility.

How does it work?

In your shader #include the functions you need:

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2    u_resolution;
uniform float   u_time;

#include "lygia/space/ratio.glsl"
#include "lygia/math/decimation.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 = decimation(color, 20.);
    color += circle(st, .5, .1);
    
    gl_FragColor = vec4(color, 1.0);
}

If you are working locally on an ecosystem that can resolve #include dependencies, just clone LYGIA in your project relative to the shader you are loading:

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

or as a submodule:

    git submodule add https://github.com/patriciogonzalezvivo/lygia.git

If you are working on a cloud platform probably you want to resolve the dependencies without needing to install anything. Just add a link to https://lygia.xyz/resolve.js:

<!DOCTYPE html>
<html>
	<head>
		...
	</head>
	<body>
        <script src="https://lygia.xyz/resolve.js"></script>
		...
	</body>
</html>

Or as a ES module, at the path https://lygia.xyz/resolve.esm.js:

    <script type="module">
      import resolveLygia from "https://lygia.xyz/resolve.esm.js"
    </script>

To then resolve the dependencies by passing a string or strings[] to resolveLygia() or resolveLygiaAsync():

    vertSource = resolveLygia(vertSource);
    fragSource = resolveLygia(fragSource);
    shdr = createShader(vertSource, fragSource);

Learn more about how to use it from this examples:

For more information, guidance or feedback about using LYGIA, join #Lygia channel on shader.zone discord.

How is it organized?

The functions are divided in different categories:

  • math/: general math functions and constants like PI, SqrtLength(), etc.
  • space/: general spatial operations like scale(), rotate(), etc.
  • color/: general color operations like luma(), saturation(), blend modes, palettes, color space conversion and tonemaps.
  • animation/: animation operations, like easing
  • generative/: generative functions like random(), noise(), etc.
  • sdf/: signed distance field functions.
  • draw/: drawing functions like digits(), stroke(), fill, etc/.
  • sample/: sample operations
  • filter/: typical filter operations like different kind of blurs, mean and median filters.
  • distort/: distort sampling operations
  • simulate/: simulate sampling operations
  • lighting/: different lighting models and functions for foward/deferred/raymarching rendering

Flexible how?

There are some functions whose behaviour can be changed using the #defines keyword before including it. For example, gaussian blurs are usually are done in two passes. By default, these are performed on their 1D version, but in the case you are interested on using a 2D kernel, all in the same pass, you will need to add the GAUSSIANBLUR_2D keyword this way:

    #define GAUSSIANBLUR_2D
    #include "filter/gaussianBlur.glsl"

    void main(void) {
        ...
        
        vec2 pixel = 1./u_resolution;
        color = gaussianBlur(u_tex0, uv, pixel, 9);
        ...
    }

Design Principles

This library:

  • Relies on #include "path/to/file.*lsl" which is defined by Khronos GLSL standard and suported by most engines and enviroments ( like Unity3D, OpenFrameworks, glslViewer, glsl-canvas VS Code pluging, etc. ). It requires a tipical C-like pre-compiler MACRO which is easy to implement with just basic string operations to resolve dependencies. Here you can find some implementations on different languages:

  • It's very granular. One function per file. The file and the function share the same name, namely: myFunc.glsl contains myFunct(). There are some files that just include a collection of files inside a folder with the same name. For example:

    color/blend.glsl
    // which includes
    color/blend/*.glsl

  • It's multi language. Right now most of is GLSL (*.glsl) and HLSL (*.hlsl), but there are plans to extend it to Metal (*.metal).
    math/mirror.glsl
    math/mirror.hlsl
  • Self documented. Each file contains a structured comment (in YAML) at the top of the file. This one contains the name of the original author, description, use and #define options
    /*
    original_author: <FULL NAME>
    description: [DESCRIPTION + URL]
    use: <vec2> myFunc(<vec2> st, <float> x [, <float> y])
    options:
        - MYFUNC_TYPE
        - MYFUNC_SAMPLER_FNC()
    */
  • Prevents name collisions by using the following pattern where FNC_ is followed with the function name:
    #ifndef FNC_MYFUNC
    #define FNC_MYFUNC

    float myFunc(float in) {
        return in;
    }

    #endif
  • Templating capabilities through #defines. Probably the most frequent use is templating the sampling function for reusability. The #define options start with the name of the function, in this example MYFUNC_. They are added as options: in the header.
    #ifndef MYFUNC_TYPE
    #define MYFUNC_TYPE vec4
    #endif

    #ifndef MYFUNC_SAMPLER_FNC
    #define MYFUNC_SAMPLER_FNC(POS_UV) texture2D(tex, POS_UV)
    #endif

    #ifndef FNC_MYFUNC
    #define FNC_MYFUNC
    MYFUNC_TYPE myFunc(sampler2D tex, vec2 st) {
        return MYFUNC_SAMPLER_FNC(st);
    }
    #endif
  • Function Overloading. Arguments are arranged in such a way that optional elements are at the back. When possible sort them according their memory size (except textures that reamin at the top). Ex.: sampler2D, mat4, mat3, mat2, vec4, vec3, vec2, float, ivec4, ivec3, ivec2, int, bool
    /*
    ...
    use: myFunc(<vec2> st, <vec2|float> x[, <float> y])
    */

    #ifndef FNC_MYFUNC
    #define FNC_MYFUNC
    vec2 myFunc(vec2 st, vec2 x) {
        return st * x;
    }

    vec2 myFunc(vec2 st, float x) {
        return st * x;
    }

    vec2 myFunc(vec2 st, float x, float y) {
        return st * vec2(x, y);
    }
    #endif

Contributions

LYGIA have a long way to go. Your support will be appreciated and rewarded (all contributors are automatically added to the commercial license ). This support can take multiple forms:

  • fixing bugs
  • expanding the crosscompatibility between languages GLSL/HLSL/WGSL/Metal
  • contributing new functions
  • adding new examples and integrations for new enviroments like: TouchDesigner, GoDot, ISF, MaxMSP, etc.
  • through sponsorships

License

LYGIA is dual-licensed under the Prosperity License and the Patron License for sponsors and contributors.

Sponsors and contributors are automatically added to the Patron License and they can ignore any non-commercial rule of the Prosperity Licensed software.

Comming soon will be possible to get a permanent comercial license hook to a single and specific version of LYGIA.

Acknowledgements

This library has been built over years, and in many cases on top of the work of brillant and generous people like: Inigo Quiles, Morgan McGuire, Alan Wolfe, Hugh Kennedy, Matt DesLauriers and many others.

About

lygia, it's a granular and multi-language shader library designed for performance and flexibility

https://lygia.xyz

License:Other


Languages

Language:GLSL 52.1%Language:HLSL 47.9%