249 lines
7.2 KiB
C
249 lines
7.2 KiB
C
#ifndef SLB_COMMON_H
|
|
#define SLB_COMMON_H
|
|
|
|
#include "slb_aliases.h"
|
|
|
|
#define SLB_PI 3.14159265358979323846
|
|
#define SLB_TAU 6.28318530717958647693
|
|
#define SLB_GoldenAngle 2.39996322972865332223
|
|
#define SLB_GoldenRatio 0.61803398874989484820
|
|
|
|
/// Taken from https://gist.github.com/yiwenl/3f804e80d0930e34a0b33359259b556c
|
|
float2x2 SLB_Rotate2Matrix(float a) {
|
|
float s = sin(a);
|
|
float c = cos(a);
|
|
return float2x2(float2(c, s), float2(-s, c));
|
|
}
|
|
|
|
float2 SLB_Rotate2(float2 v, float a) {
|
|
float2x2 m = SLB_Rotate2Matrix(a);
|
|
return mul(v, m);
|
|
}
|
|
|
|
float SLB_ToFloat1(uint v) {
|
|
return float(v) * (1.0/float(0xffffffffu));
|
|
}
|
|
|
|
float2 SLB_ToFloat2(uint2 v) {
|
|
return float2(v) * (1.0/float(0xffffffffu));
|
|
}
|
|
|
|
float3 SLB_ToFloat3(uint3 v) {
|
|
return float3(v) * (1.0/float(0xffffffffu));
|
|
}
|
|
|
|
float4 SLB_ToFloat4(uint4 v) {
|
|
return float4(v) * (1.0/float(0xffffffffu));
|
|
}
|
|
|
|
float SLB_Min3(float3 v) {
|
|
return min(v.x, min(v.y, v.z));
|
|
}
|
|
|
|
float SLB_Max3(float3 v) {
|
|
return max(v.x, max(v.y, v.z));
|
|
}
|
|
|
|
/// Taken from https://web.archive.org/web/20200306054846/http://lolengine.net:80/blog/2013/07/27/rgb-to-hsv-in-glsl
|
|
float3 SLB_RGB_To_HSV(float3 c) {
|
|
float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
|
|
float4 p = c.g < c.b ? float4(c.bg, K.wz) : float4(c.gb, K.xy);
|
|
float4 q = c.r < p.x ? float4(p.xyw, c.r) : float4(c.r, p.yzx);
|
|
float d = q.x - min(q.w, q.y);
|
|
const float e = 1.0e-10;
|
|
return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
|
|
}
|
|
|
|
/// It took me long time to found this somewhere in vanilla shaders codebase;
|
|
float2 SLB_Pos2DToCoord(float2 pos2d) {
|
|
// return float2((pos2d.x * screen_res.z * 2.0 - 1.0), (pos2d.y * screen_res.w * 2.0 - 1.0))/2.0 * screen_res.xy;
|
|
return (pos2d.xy * screen_res.zw - 0.5) * screen_res.xy;
|
|
}
|
|
|
|
/// Taken from https://iquilezles.org/articles/smoothsteps
|
|
float SLB_Cubic1D(float x) {
|
|
return x*x*(3.0 - 2.0*x);
|
|
}
|
|
|
|
/// Taken from https://iquilezles.org/articles/smoothsteps
|
|
float SLB_Quartic1D(float x) {
|
|
return x*x*(2.0 - x*x);
|
|
}
|
|
|
|
/// Taken from https://iquilezles.org/articles/smoothsteps
|
|
float SLB_Quintic1D(float x) {
|
|
return x*x*x*(x*(6.0*x - 15.0) + 10.0);
|
|
}
|
|
|
|
/// Taken from https://iquilezles.org/articles/smoothsteps
|
|
float SLB_CubicRational1D(float x) {
|
|
return x*x*x/(3.0*x*x - 3.0*x + 1.0);
|
|
}
|
|
|
|
/// Taken from https://iquilezles.org/articles/smoothsteps
|
|
float SLB_QuarticRational1D(float x) {
|
|
return x*x*x*x/(2.0*x*x*x*x - 4.0*x*x*x + 6.0*x*x - 4.0*x + 1.0);
|
|
}
|
|
|
|
/// Taken from somewhere
|
|
float SLB_Gaussian1D(float x, float sigma) {
|
|
return exp(-(x * x) / (2.0 * sigma * sigma));
|
|
}
|
|
|
|
/// Taken from http://www.java-gaming.org/index.php?topic=35123.0
|
|
/// Idk how to name it
|
|
float4 SLB_Cubic_For_Bicubic(float v) {
|
|
float4 n = float4(1.0, 2.0, 3.0, 4.0) - v;
|
|
float4 s = n * n * n;
|
|
float x = s.x;
|
|
float y = s.y - 4.0 * s.x;
|
|
float z = s.z - 4.0 * s.y + 6.0 * s.x;
|
|
float w = 6.0 - x - y - z;
|
|
return float4(x, y, z, w) * (1.0/6.0);
|
|
}
|
|
|
|
float2 SLB_VogelDisk_Sample(const int sample_index, const int samples_count) {
|
|
const float r = sqrt(float(sample_index) + 0.5) / sqrt(float(samples_count));
|
|
const float theta = float(sample_index) * SLB_GoldenAngle;
|
|
|
|
const float sine = sin(theta), cosine = cos(theta);
|
|
|
|
return float2(r * cosine, r * sine);
|
|
}
|
|
|
|
/// Taken from https://extremelearning.com.au/unreasonable-effectiveness-of-quasirandom-sequences
|
|
float SLB_R1(float n) {
|
|
const float g = 1.6180339887498948482;
|
|
const float a1 = 1.0 - 1.0/g;
|
|
float _n = floor(n);
|
|
return frac(0.5 + a1*_n);
|
|
}
|
|
|
|
/// Taken from https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes
|
|
uint SLB_Part1By1(uint x) {
|
|
x &= 0x0000ffffu;
|
|
x = (x ^ (x << 8u)) & 0x00ff00ffu;
|
|
x = (x ^ (x << 4u)) & 0x0f0f0f0fu;
|
|
x = (x ^ (x << 2u)) & 0x33333333u;
|
|
x = (x ^ (x << 1u)) & 0x55555555u;
|
|
return x;
|
|
}
|
|
|
|
/// Taken from https://fgiesen.wordpress.com/2009/12/13/decoding-morton-codes
|
|
uint SLB_EncodeMorton2(uint x, uint y) {
|
|
return (SLB_Part1By1(y) << 1u) + SLB_Part1By1(x);
|
|
}
|
|
|
|
/// From https://psychopath.io post
|
|
uint SLB_OwenHash4(uint n, uint seed) {
|
|
n ^= n * 0x3d20adeau;
|
|
n ^= (n >> 1u) & (n << 1u) & 0x55555555u;
|
|
n += seed;
|
|
n *= (seed >> 16u) | 1u;
|
|
n ^= (n >> 1u) & (n << 1u) & 0x55555555u;
|
|
n ^= n * 0x05526c56u;
|
|
n ^= n * 0x53a22864u;
|
|
return n;
|
|
}
|
|
|
|
/// Inspired by https://www.shadertoy.com/view/ssBBW1 shader and https://psychopath.io posts
|
|
uint SLB_Morton_OwenHash4_Bluenoise(uint2 coord) {
|
|
uint m;
|
|
m = SLB_EncodeMorton2(coord.x, coord.y);
|
|
m = SLB_OwenHash4(reversebits(m), 0xe7843fbfu); // owen-scramble morton index
|
|
m = SLB_OwenHash4(reversebits(m), 0x8d8fb1e0u); // map morton index to sobol sequence and owen-scramble
|
|
return reversebits(m); // convert to float
|
|
}
|
|
|
|
float SLB_Morton_OwenHash4_Bluenoise_float(uint2 coord) {
|
|
return SLB_ToFloat1(SLB_Morton_OwenHash4_Bluenoise(coord));
|
|
}
|
|
|
|
/// Taken from https://www.shadertoy.com/view/wltSDn
|
|
uint SLB_PhiNoise(uint2 uv) {
|
|
// flip every other tile to reduce anisotropy
|
|
if(((uv.x ^ uv.y) & 4u) == 0u) uv = uv.yx;
|
|
|
|
// constants of 2d Roberts sequence rounded to nearest primes
|
|
const uint r0 = 3242174893u;// prime[(2^32-1) / phi_2 ]
|
|
const uint r1 = 2447445397u;// prime[(2^32-1) / phi_2^2]
|
|
|
|
// h = high-freq dither noise
|
|
uint h = (uv.x * r0) + (uv.y * r1);
|
|
|
|
// l = low-freq white noise
|
|
uv = uv >> 2u;// 3u works equally well (I think)
|
|
uint l = ((uv.x * r0) ^ (uv.y * r1)) * r1;
|
|
|
|
// combine low and high
|
|
return l + h;
|
|
}
|
|
|
|
float SLB_PhiNoise_float(uint2 uv) {
|
|
return SLB_ToFloat1(SLB_PhiNoise(uv));
|
|
}
|
|
|
|
/// Taken from https://www.shadertoy.com/view/wltSDn
|
|
uint SLB_PhiNoise2(uint2 uv) {
|
|
uint2 uv0 = uv;
|
|
// flip every other tile to reduce anisotropy
|
|
if(((uv.x ^ uv.y) & 4u) == 0u) uv = uv.yx;
|
|
if(((uv.x ) & 4u) == 0u) uv.x = -uv.x;// more iso but also more low-freq content
|
|
|
|
// constants of 2d Roberts sequence rounded to nearest primes
|
|
const uint r0 = 3242174893u;// prime[(2^32-1) / phi_2 ]
|
|
const uint r1 = 2447445397u;// prime[(2^32-1) / phi_2^2]
|
|
|
|
// h = high-freq dither noise
|
|
uint h = (uv.x * r0) + (uv.y * r1);
|
|
|
|
uint l;
|
|
{
|
|
uv = uv0 >> 2u;
|
|
|
|
if(((uv.x ^ uv.y) & 4u) == 0u) uv = uv.yx;
|
|
if(((uv.x ) & 4u) == 0u) uv.x = -uv.x;
|
|
|
|
uint h = (uv.x * r0) + (uv.y * r1);
|
|
h = h ^ 0xE2E17FDCu;
|
|
|
|
l = h;
|
|
|
|
{
|
|
uv = uv0 >> 4u;
|
|
if(((uv.x ^ uv.y) & 4u) == 0u) uv = uv.yx;
|
|
if(((uv.x ) & 4u) == 0u) uv.x = -uv.x;
|
|
|
|
uint h = (uv.x * r0) + (uv.y * r1);
|
|
h = h ^ 0x1B98264Du;
|
|
|
|
l += h;
|
|
}
|
|
}
|
|
|
|
// combine low and high
|
|
return l + h;
|
|
}
|
|
|
|
float SLB_PhiNoise2_float(uint2 uv) {
|
|
return SLB_ToFloat1(SLB_PhiNoise2(uv));
|
|
}
|
|
|
|
/// Taken from paper named "Hash Functions for GPU Rendering"
|
|
uint4 SLB_PCG4D(uint4 v) {
|
|
v = v * 1664525u + 1013904223u;
|
|
v.x += v.y*v.w; v.y += v.z*v.x; v.z += v.x*v.y; v.w += v.y*v.z;
|
|
v ^= v >> 16u;
|
|
v.x += v.y*v.w; v.y += v.z*v.x; v.z += v.x*v.y; v.w += v.y*v.z;
|
|
return v;
|
|
}
|
|
|
|
/// Taken from https://www.pcg-random.org
|
|
uint SLB_PCG(uint v) {
|
|
uint state = v * 747796405u + 2891336453u;
|
|
uint word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u;
|
|
return (word >> 22u) ^ word;
|
|
}
|
|
|
|
#endif // SLB_COMMON_H
|