// 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); } 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; } 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; } #if TEXTURE_WORKAROUND vec4 sampleTexture( uint id, vec2 uv ) { const Texture t = textures[id]; return texture( samplerTextures[nonuniformEXT(t.index - surface.instance.imageID)], mix( t.lerp.xy, t.lerp.zw, uv ) ); } vec4 sampleTexture( uint id, vec2 uv, float mip ) { const Texture t = textures[id]; return textureLod( samplerTextures[nonuniformEXT(t.index - surface.instance.imageID)], mix( t.lerp.xy, t.lerp.zw, uv ), mip ); } #else 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 ) { 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 ) { return sampleTexture( id, surface.uv ); } vec4 sampleTexture( uint id, float mip ) { return sampleTexture( id, surface.uv, 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 uv ) { const vec2 dx_vtc = dFdx(uv); const vec2 dy_vtc = dFdy(uv); 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; }