diff --git a/src/webgl/shaders/imageLightDiffused.frag b/src/webgl/shaders/imageLightDiffused.frag index 60867f81ac..7b342bdb2b 100644 --- a/src/webgl/shaders/imageLightDiffused.frag +++ b/src/webgl/shaders/imageLightDiffused.frag @@ -28,6 +28,12 @@ vec2 nTOE( vec3 v ){ return angles; } +float random(vec2 p) { + vec3 p3 = fract(vec3(p.xyx) * .1031); + p3 += dot(p3, p3.yzx + 33.33); + return fract((p3.x + p3.y) * p3.z); +} + void main() { // the sample direction equals the hemisphere's orientation @@ -48,13 +54,15 @@ void main() // We specify a fixed sampleDelta delta value to traverse // the hemisphere; decreasing or increasing the sample delta // will increase or decrease the accuracy respectively. - const float sampleDelta = 0.025; + const float sampleDelta = 0.100; float nrSamples = 0.0; - - for(float phi = 0.0; phi < 2.0 * PI; phi += sampleDelta) + float randomOffset = random(gl_FragCoord.xy) * sampleDelta; + for(float rawPhi = 0.0; rawPhi < 2.0 * PI; rawPhi += sampleDelta) { - for(float theta = 0.0; theta < ( 0.5 ) * PI; theta += sampleDelta) + float phi = rawPhi + randomOffset; + for(float rawTheta = 0.0; rawTheta < ( 0.5 ) * PI; rawTheta += sampleDelta) { + float theta = rawTheta + randomOffset; // spherical to cartesian (in tangent space) // tangent space to world // add each sample result to irradiance float x = sin(theta) * cos(phi); float y = sin(theta) * sin(phi); diff --git a/src/webgl/shaders/imageLightSpecular.frag b/src/webgl/shaders/imageLightSpecular.frag index 3c4ab9f316..8b6edcdf10 100644 --- a/src/webgl/shaders/imageLightSpecular.frag +++ b/src/webgl/shaders/imageLightSpecular.frag @@ -36,7 +36,8 @@ vec2 nTOE( vec3 v ){ void main(){ - const int SAMPLE_COUNT = 1024; // 4096 + const int SAMPLE_COUNT = 400; // 4096 + int lowRoughnessLimit = int(pow(2.0,(roughness+0.1)*20.0)); float totalWeight = 0.0; vec3 prefilteredColor = vec3(0.0); float phi = vTexCoord.x * 2.0 * PI; @@ -48,6 +49,11 @@ void main(){ vec3 V = N; for (int i = 0; i < SAMPLE_COUNT; ++i) { + // break at smaller sample numbers for low roughness levels + if(i == lowRoughnessLimit) + { + break; + } vec2 Xi = HammersleyNoBitOps(i, SAMPLE_COUNT); vec3 H = ImportanceSampleGGX(Xi, N, roughness); vec3 L = normalize(2.0 * dot(V, H) * H - V); @@ -88,22 +94,38 @@ vec3 ImportanceSampleGGX(vec2 Xi, vec3 N, float roughness){ float VanDerCorput(int n, int base) { +#ifdef WEBGL2 + + uint bits = uint(n); + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 + +#else + float invBase = 1.0 / float(base); float denom = 1.0; float result = 0.0; + for (int i = 0; i < 32; ++i) { - if (n > 0) - { - denom = mod(float(n), 2.0); - result += denom * invBase; - invBase = invBase / 2.0; - n = int(float(n) / 2.0); - } + if (n > 0) + { + denom = mod(float(n), 2.0); + result += denom * invBase; + invBase = invBase / 2.0; + n = int(float(n) / 2.0); + } } + return result; + +#endif } vec2 HammersleyNoBitOps(int i, int N)