PTGI (current progress)

mail@pastecode.io avatar
unknown
glsl
2 years ago
3.2 kB
2
Indexable
Never
/***********************************************/
/*       Copyright (C) Noble RT - 2021         */
/*   Belmu | GNU General Public License V3.0   */
/*                                             */
/* By downloading this content you have agreed */
/*     to the license and its terms of use.    */
/***********************************************/

vec3 BRDFSpecular(vec3 N, vec3 V, vec3 L, vec3 fresnel, float roughness) {
    float NdotL = max(EPS, dot(N, L));
    float NdotV = max(EPS, dot(N, V));

    float r = roughness + 1.0;
    float G2 = G_SchlickGGX(NdotL, (r * r) / 8.0);

    return (fresnel * G2) / max(EPS, 4.0 * NdotL * NdotV);
}

vec3 computePTGI(in vec3 screenPos) {
    vec3 radiance = vec3(0.0);

    for(int i = 0; i < GI_SAMPLES; i++) {
        vec3 hitPos = screenPos; 
        vec3 viewPos = screenToView(screenPos); 
        vec3 rayDir = normalize(viewPos); vec3 prevDir;

        vec3 throughput = vec3(1.0);
        for(int j = 0; j < GI_BOUNCES; j++) {
            prevDir = rayDir;

            vec2 noise = uniformAnimatedNoise(animBlueNoise.xy);
            float rng = rand(gl_FragCoord.xy + frameTimeCounter);

            if(j > 3) {
                float roulette = max(throughput.x, max(throughput.y, throughput.z));
                if(roulette < rng) break;
                throughput /= roulette;
            }

            vec3 normal = normalize(decodeNormal(texture(colortex1, hitPos.xy).xy));
            mat3 TBN = getTBN(normal);
            if(!raytrace(screenToView(hitPos), prevDir, GI_STEPS, uniformNoise(j, blueNoise).x, hitPos)) continue;

            vec2 params = texture(colortex2, hitPos.xy).rg; // F0 and Roughness
            bool isMetal = params.g * 255.0 > 229.5;

            float NdotD = max(EPS, dot(normal, -prevDir));
            float NdotL = max(EPS, dot(normal, sunDir));

            vec3 albedo = isMetal ? vec3(0.0) : texture(colortex4, hitPos.xy).rgb;
            vec3 fresnel = cookTorranceFresnel(NdotD, params.g, albedo, isMetal);
            vec3 sunSpecular = cookTorranceSpecular(normal, -prevDir, sunDir, params.r, params.g, albedo, isMetal);

            radiance += throughput * albedo * (texture(colortex1, hitPos.xy).z * EMISSION_INTENSITY);
            radiance += throughput * (albedo + sunSpecular) * (NdotL * texture(colortex9, hitPos.xy).rgb) * viewPosSkyColor(viewPos) * SUN_INTENSITY;

            float specBounceProbability = luma(fresnel);
            if(specBounceProbability > rng) {
                vec3 microfacet = sampleGGXVNDF(-prevDir * TBN, noise, params.r * params.r);
                rayDir = reflect(prevDir, TBN * microfacet);

                throughput /= specBounceProbability;
                throughput *= BRDFSpecular(normal, -prevDir, rayDir, fresnel, params.r);
            } else {
                throughput /= 1.0 - specBounceProbability;
                throughput *= 1.0 - fresnel;
                throughput *= albedo;

                rayDir = TBN * randomHemisphereDirection(noise);
            }
        }
    }
    radiance /= GI_SAMPLES;
    return radiance;
}