engine/bin/data/shaders/common/functions.h

199 lines
6.7 KiB
C

// Helper Functions
float random(vec3 seed, int i){ return fract(sin(dot(vec4(seed,i), vec4(12.9898,78.233,45.164,94.673))) * 43758.5453); }
float rand2(vec2 co){ return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 143758.5453); }
float rand3(vec3 co){ return fract(sin(dot(co.xyz ,vec3(12.9898,78.233, 37.719))) * 143758.5453); }
//
uint tea(uint val0, uint val1) {
uint v0 = val0;
uint v1 = val1;
uint s0 = 0;
for(uint n = 0; n < 16; n++) {
s0 += 0x9e3779b9;
v0 += ((v1 << 4) + 0xa341316c) ^ (v1 + s0) ^ ((v1 >> 5) + 0xc8013ea4);
v1 += ((v0 << 4) + 0xad90777d) ^ (v0 + s0) ^ ((v0 >> 5) + 0x7e95761e);
}
return v0;
}
uint lcg(inout uint prev) {
uint LCG_A = 1664525u;
uint LCG_C = 1013904223u;
prev = (LCG_A * prev + LCG_C);
return prev & 0x00FFFFFF;
}
float rnd(inout uint prev) { return (float(lcg(prev)) / float(0x01000000)); }
uint prngSeed;
float rnd() { return rnd(prngSeed); }
//
void tangentBitangent(in vec3 N, out vec3 Nt, out vec3 Nb) {
if(abs(N.x) > abs(N.y)) Nt = vec3(N.z, 0, -N.x) / sqrt(N.x * N.x + N.z * N.z);
else Nt = vec3(0, -N.z, N.y) / sqrt(N.y * N.y + N.z * N.z);
Nb = cross(N, Nt);
}
vec3 samplingHemisphere(inout uint seed, in vec3 x, in vec3 y, in vec3 z) {
float r1 = rnd(seed);
float r2 = rnd(seed);
float sq = sqrt(1.0 - r2);
vec3 direction = vec3(cos(2 * PI * r1) * sq, sin(2 * PI * r1) * sq, sqrt(r2));
direction = direction.x * x + direction.y * y + direction.z * z;
return direction;
}
vec3 samplingHemisphere(inout uint seed, in vec3 z) {
vec3 x;
vec3 y;
tangentBitangent( z, x, y );
float r1 = rnd(seed);
float r2 = rnd(seed);
float sq = sqrt(1.0 - r2);
vec3 direction = vec3(cos(2 * PI * r1) * sq, sin(2 * PI * r1) * sq, sqrt(r2));
direction = direction.x * x + direction.y * y + direction.z * z;
return direction;
}
//
#if BUFFER_REFERENCE
uint64_t uvec2uint64( uvec2 src ) {
uint64_t dst;
dst = (src.x << 32) | src.y;
return dst;
}
#endif
//
float max3( vec3 v ) { return max(max(v.x, v.y), v.z); }
float min3( vec3 v ) { return min(min(v.x, v.y), v.z); }
uint biasedRound( float x, float bias ) { return uint( ( x < bias ) ? floor(x) : ceil(x)); }
float wrap( float i ) { return fract(i); }
vec2 wrap( vec2 uv ) { return vec2( wrap( uv.x ), wrap( uv.y ) ); }
vec3 orthogonal(vec3 u){
u = normalize(u);
const vec3 v = vec3(0.99146, 0.11664, 0.05832); // Pick any normalized vector.
return abs(dot(u, v)) > 0.99999f ? cross(u, vec3(0, 1, 0)) : cross(u, v);
}
vec4 blend( vec4 source, vec4 dest, float a ) {
return source * a + dest * (1.0 - a);
}
float gauss( float x, float sigma ) {
return (1.0 / (2.0 * 3.14157 * sigma) * exp(-(x*x) / (2.0 * sigma)));
}
bool enabled( uint flag, uint bit ) {
return (flag & (1 << bit)) != 0;
}
vec3 decodeNormals( vec2 enc ) {
const vec2 ang = enc*2-1;
const vec2 scth = vec2( sin(ang.x * PI), cos(ang.x * PI) );
const vec2 scphi = vec2(sqrt(1.0 - ang.y*ang.y), ang.y);
return normalize( vec3(scth.y*scphi.x, scth.x*scphi.x, scphi.y) );
}
vec2 encodeNormals( vec3 n ) {
// float p = sqrt(n.z*8+8);
// return n.xy/p + 0.5;
return (vec2(atan(n.y,n.x)/PI, n.z)+1.0)*0.5;
}
vec3 encodeSrgb(vec3 rgb) {
const vec3 a = 12.92 * rgb;
const vec3 b = 1.055 * pow(rgb, vec3(1.0 / 2.4)) - 0.055;
const vec3 c = step(vec3(0.0031308), rgb);
return mix(a, b, c);
}
vec3 decodeSrgb(vec3 rgb) {
const vec3 a = rgb / 12.92;
const vec3 b = pow((rgb + 0.055) / 1.055, vec3(2.4));
const vec3 c = step(vec3(0.04045), rgb);
return mix(a, b, c);
}
bool validTextureIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < MAX_TEXTURES;
}
bool validCubemapIndex( int textureIndex ) {
return 0 <= textureIndex && textureIndex < CUBEMAPS;
}
#if !BLOOM && (DEFERRED || FRAGMENT || COMPUTE)
#if !NO_NONUNIFORM_EXT
#extension GL_EXT_nonuniform_qualifier : enable
#endif
bool validTextureIndex( uint id ) {
return 0 <= id && id < MAX_TEXTURES;
}
bool validTextureIndex( uint start, int offset ) {
return 0 <= offset && start + offset < MAX_TEXTURES;
}
uint textureIndex( uint start, int offset ) {
return start + offset;
}
vec4 sampleTexture( uint id, vec2 uv ) {
const Texture t = textures[id];
return texture( samplerTextures[nonuniformEXT(t.index)], mix( t.lerp.xy, t.lerp.zw, uv ) );
}
vec4 sampleTexture( uint id, vec2 uv, float mip ) {
#if QUERY_MIPMAP
return sampleTexture( id, uv );
#else
const Texture t = textures[id];
return textureLod( samplerTextures[nonuniformEXT(t.index)], mix( t.lerp.xy, t.lerp.zw, uv ), mip );
#endif
}
vec4 sampleTexture( uint id, vec3 uvm ) { return sampleTexture( id, uvm.xy, uvm.z ); }
vec4 sampleTexture( uint id ) { return sampleTexture( id, surface.uv.xy, surface.uv.z ); }
vec4 sampleTexture( uint id, float mip ) { return sampleTexture( id, surface.uv.xy, mip ); }
#endif
vec2 rayBoxDst( vec3 boundsMin, vec3 boundsMax, in Ray ray ) {
const vec3 t0 = (boundsMin - ray.origin) / ray.direction;
const vec3 t1 = (boundsMax - ray.origin) / ray.direction;
const vec3 tmin = min(t0, t1);
const vec3 tmax = max(t0, t1);
const float tStart = max(0, max( max(tmin.x, tmin.y), tmin.z ));
const float tEnd = max(0, min( tmax.x, min(tmax.y, tmax.z) ) - tStart);
return vec2(tStart, tEnd);
}
#if VXGI
float cascadePower( uint x ) {
return pow(1 + x, ubo.vxgi.cascadePower);
// return max( 1, x * ubo.vxgi.cascadePower );
}
#endif
#if !COMPUTE
void whitenoise(inout vec3 color, const vec4 parameters) {
const float flicker = parameters.x;
const float pieces = parameters.y;
const float blend = parameters.z;
const float time = parameters.w;
if ( blend < 0.0001 ) return;
const float freq = sin(pow(mod(time, flicker) + flicker, 1.9));
const float whiteNoise = rand2( floor(gl_FragCoord.xy / pieces) + mod(time, freq) );
color = mix( color, vec3(whiteNoise), blend );
}
float mipLevel( in vec2 dx_vtc, in vec2 dy_vtc ) {
const float delta_max_sqr = max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc));
return 0.5 * log2(delta_max_sqr);
// return max(0.0, 0.5 * log2(delta_max_sqr) - 1.0);
// return 0.5 * log2(max(dot(dx_vtc, dx_vtc), dot(dy_vtc, dy_vtc)));
}
vec4 resolve( subpassInputMS t, const uint samples ) {
vec4 resolved = vec4(0);
for ( int i = 0; i < samples; ++i ) resolved += subpassLoad(t, i);
resolved /= vec4(samples);
return resolved;
}
uvec4 resolve( usubpassInputMS t, const uint samples ) {
uvec4 resolved = uvec4(0);
for ( int i = 0; i < samples; ++i ) resolved += subpassLoad(t, i);
resolved /= uvec4(samples);
return resolved;
}
#endif
vec4 resolve( sampler2DMS t, ivec2 uv ) {
vec4 resolved = vec4(0);
int samples = textureSamples(t);
for ( int i = 0; i < samples; ++i ) {
resolved += texelFetch(t, uv, i);
}
resolved /= float(samples);
return resolved;
}