lygia
/color
/dither
/triangleNoise
)2016, Banding in Games: A Noisy Rant
Dependencies:
Use:
<vec4|vec3|float> ditherTriangleNoise(<vec4|vec3|float> value, <vec2> st, <float> time)
<vec4|vec3|float> ditherTriangleNoise(<vec4|vec3|float> value, <float> time)
#ifndef DITHER_TRIANGLENOISE_COORD
#define DITHER_TRIANGLENOISE_COORD gl_FragCoord.xy
#endif
#ifdef DITHER_TIME
#define DITHER_TRIANGLENOISE_TIME DITHER_TIME
#endif
#ifdef DITHER_CHROMATIC
#define DITHER_TRIANGLENOISE_CHROMATIC
#endif
#ifndef DITHER_TRIANGLENOISE_PRECISION
#ifdef DITHER_PRECISION
#define DITHER_TRIANGLENOISE_PRECISION DITHER_PRECISION
#else
#define DITHER_TRIANGLENOISE_PRECISION 255
#endif
#endif
#ifndef FNC_DITHER_TRIANGLENOISE
#define FNC_DITHER_TRIANGLENOISE
float triangleNoise(HIGHP in vec2 st) {
st = floor(st);
#ifdef DITHER_TRIANGLENOISE_TIME
st += vec2(0.07 * fract(DITHER_TRIANGLENOISE_TIME));
#endif
st = fract(st * vec2(5.3987, 5.4421));
st += dot(st.yx, st.xy + vec2(21.5351, 14.3137));
HIGHP float xy = st.x * st.y;
return (fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0);
}
vec3 ditherTriangleNoise(const in vec3 color, const HIGHP in vec2 st, const int pres) {
#ifdef DITHER_TRIANGLENOISE_CHROMATIC
vec3 ditherPattern = vec3(
triangleNoise(st),
triangleNoise(st + 0.1337),
triangleNoise(st + 0.3141));
#else
vec3 ditherPattern = vec3(triangleNoise(st));
#endif
// return color + ditherPattern / 255.0;
float d = float(pres);
float h = 0.5/d;
return decimate(color - h + ditherPattern / d, d);
}
float ditherTriangleNoise(const in float b, const HIGHP in vec2 st) { return b + triangleNoise(st) / float(DITHER_TRIANGLENOISE_PRECISION); }
vec3 ditherTriangleNoise(const in vec3 color, const in vec2 xy) { return ditherTriangleNoise(color, xy, DITHER_TRIANGLENOISE_PRECISION); }
vec4 ditherTriangleNoise(const in vec4 color, const in vec2 xy) { return vec4(ditherTriangleNoise(color.rgb, xy, DITHER_TRIANGLENOISE_PRECISION), color.a); }
float ditherTriangleNoise(const in float val, int pres) { return ditherTriangleNoise(vec3(val),DITHER_TRIANGLENOISE_COORD, pres).r; }
vec3 ditherTriangleNoise(const in vec3 color, int pres) { return ditherTriangleNoise(color, DITHER_TRIANGLENOISE_COORD, pres); }
vec4 ditherTriangleNoise(const in vec4 color, int pres) { return vec4(ditherTriangleNoise(color.rgb, DITHER_TRIANGLENOISE_COORD, pres), color.a); }
float ditherTriangleNoise(const in float val) { return ditherTriangleNoise(vec3(val), DITHER_TRIANGLENOISE_COORD, DITHER_TRIANGLENOISE_PRECISION).r; }
vec3 ditherTriangleNoise(const in vec3 color) { return ditherTriangleNoise(color, DITHER_TRIANGLENOISE_COORD, DITHER_TRIANGLENOISE_PRECISION); }
vec4 ditherTriangleNoise(const in vec4 color) { return vec4(ditherTriangleNoise(color.rgb), color.a); }
#endif
Use:
<float4|float3|float> ditherTriangleNoise(<float4|float3|float> value, <float2> fragcoord, <float> time)
<float4|float3|float> ditherTriangleNoise(<float4|float3|float> value, <float> time)
#ifdef DITHER_ANIMATED
#define DITHER_TRIANGLENOISE_ANIMATED
#endif
#ifdef DITHER_CHROMATIC
#define DITHER_TRIANGLENOISE_CHROMATIC
#endif
#ifndef RESOLUTION
#define RESOLUTION _ScreenParams
#endif
#ifndef FNC_DITHER_TRIANGLENOISE
#define FNC_DITHER_TRIANGLENOISE
float triangleNoise(in float2 n, const in float time) {
// triangle noise, in [-1.0..1.0[ range
#ifdef DITHER_TRIANGLENOISE_ANIMATED
n += float2(0.07 * frac(time));
#endif
n = frac(n * float2(5.3987, 5.4421));
n += dot(n.yx, n.xy + float2(21.5351, 14.3137));
float xy = n.x * n.y;
// compute in [0..2[ and remap to [-1.0..1.0[
return frac(xy * 95.4307) + frac(xy * 75.04961) - 1.0;
}
float ditherTriangleNoise(const in float b, in float2 fragcoord, const in float time) {
fragcoord /= RESOLUTION;
return b + triangleNoise(fragcoord, time) / 255.0;
}
float3 ditherTriangleNoise(const in float3 rgb, in float2 fragcoord, const in float time) {
fragcoord /= RESOLUTION;
#ifdef DITHER_TRIANGLENOISE_CHROMATIC
float3 dither = float3(
triangleNoise(fragcoord, time),
triangleNoise(fragcoord + 0.1337, time),
triangleNoise(fragcoord + 0.3141, time));
#else
float n = triangleNoise(fragcoord, time);
float3 dither = float3(n, n, n);
#endif
return rgb + dither / 255.0;
}
float4 ditherTriangleNoise(const in float4 rgba, in float2 fragcoord, const in float time) {
fragcoord /= RESOLUTION;
#ifdef DITHER_TRIANGLENOISE_CHROMATIC
float3 dither = float3(
triangleNoise(fragcoord, time),
triangleNoise(fragcoord + 0.1337, time),
triangleNoise(fragcoord + 0.3141, time));
#else
float n = triangleNoise(fragcoord, time);
float3 dither = float3(n, n, n);
#endif
return (rgba + float4(dither, dither.x)) / 255.0;
}
#endif
Dependencies:
Use:
<float4|float3|float> ditherTriangleNoise(<float4|float3|float> value, <float2> st, <float> time)
<float4|float3|float> ditherTriangleNoise(<float4|float3|float> value, <float> time)
#ifndef DITHER_TRIANGLENOISE_COORD
#define DITHER_TRIANGLENOISE_COORD gl_FragCoord.xy
#endif
#ifdef DITHER_TIME
#define DITHER_TRIANGLENOISE_TIME DITHER_TIME
#endif
#ifdef DITHER_CHROMATIC
#define DITHER_TRIANGLENOISE_CHROMATIC
#endif
#ifndef DITHER_TRIANGLENOISE_PRECISION
#ifdef DITHER_PRECISION
#define DITHER_TRIANGLENOISE_PRECISION DITHER_PRECISION
#else
#define DITHER_TRIANGLENOISE_PRECISION 255
#endif
#endif
#ifndef FNC_DITHER_TRIANGLENOISE
#define FNC_DITHER_TRIANGLENOISE
float triangleNoise(HIGHP float2 st) {
st = floor(st);
#ifdef DITHER_TRIANGLENOISE_TIME
st += float2(0.07 * fract(DITHER_TRIANGLENOISE_TIME));
#endif
st = fract(st * float2(5.3987, 5.4421));
st += dot(st.yx, st.xy + float2(21.5351, 14.3137));
HIGHP float xy = st.x * st.y;
return (fract(xy * 95.4307) + fract(xy * 75.04961) - 1.0);
}
float3 ditherTriangleNoise(const float3 color, const HIGHP float2 st, const int pres) {
#ifdef DITHER_TRIANGLENOISE_CHROMATIC
float3 ditherPattern = float3(
triangleNoise(st),
triangleNoise(st + 0.1337),
triangleNoise(st + 0.3141));
#else
float3 ditherPattern = float3(triangleNoise(st));
#endif
// return color + ditherPattern / 255.0;
float d = float(pres);
float h = 0.5/d;
return decimate(color - h + ditherPattern / d, d);
}
float ditherTriangleNoise(const float b, const HIGHP float2 st) { return b + triangleNoise(st) / float(DITHER_TRIANGLENOISE_PRECISION); }
float3 ditherTriangleNoise(const float3 color, const float2 xy) { return ditherTriangleNoise(color, xy, DITHER_TRIANGLENOISE_PRECISION); }
float4 ditherTriangleNoise(const float4 color, const float2 xy) { return float4(ditherTriangleNoise(color.rgb, xy, DITHER_TRIANGLENOISE_PRECISION), color.a); }
float ditherTriangleNoise(const float val, int pres) { return ditherTriangleNoise(float3(val),DITHER_TRIANGLENOISE_COORD, pres).r; }
float3 ditherTriangleNoise(const float3 color, int pres) { return ditherTriangleNoise(color, DITHER_TRIANGLENOISE_COORD, pres); }
float4 ditherTriangleNoise(const float4 color, int pres) { return float4(ditherTriangleNoise(color.rgb, DITHER_TRIANGLENOISE_COORD, pres), color.a); }
float ditherTriangleNoise(const float val) { return ditherTriangleNoise(float3(val), DITHER_TRIANGLENOISE_COORD, DITHER_TRIANGLENOISE_PRECISION).r; }
float3 ditherTriangleNoise(const float3 color) { return ditherTriangleNoise(color, DITHER_TRIANGLENOISE_COORD, DITHER_TRIANGLENOISE_PRECISION); }
float4 ditherTriangleNoise(const float4 color) { return float4(ditherTriangleNoise(color.rgb), color.a); }
#endif
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 the any non-commercial rule of the Prosperity Licensed software (please take a look to the exception).
It's also possible to get a permanent comercial license hook to a single and specific version of LYGIA.
Sign up for the news letter bellow, joing the LYGIA's channel on Discord or follow the Github repository