/***********************************************/
/*           Copyright (c) 2025 Belmu          */
/*             All Rights Reserved             */
/***********************************************/

layout (local_size_x = 8, local_size_y = 4, local_size_z = 1) in;

const vec2 workGroupsRender = vec2(1.0, 1.0);

layout (rgba32f) uniform image2D colorimg0;

#include "/settings.glsl"
#include "/include/common.glsl"
#include "/include/utility/transforms.glsl"

#include "/include/voxels/voxelization.glsl"
#include "/include/materials/material.glsl"
#include "/include/voxels/raytracer.glsl"

#include "/include/atmospherics/constants.glsl"
#include "/include/atmospherics/celestial_paths.glsl"

void main() {
    ivec2 fragCoords = ivec2(gl_GlobalInvocationID.xy);
    if (fragCoords.x > viewWidth || fragCoords.y > viewHeight) return;

    vec3 lighting = texelFetch(RADIANCE_HISTORY_BUFFER, ivec2(fragCoords * renderScale), 0).rgb;

    #if DEBUG_ALBEDO == 0 && DEBUG_NORMALS == 0 && DEBUG_HIT_POSITION == 0

        if (hideGUI == 0) {
            vec3 screenPosition = vec3(fragCoords * texelSize, 0.0);
            vec3 sceneDirection = normalize(mat3(gbufferModelViewInverse) * screenToView(screenPosition));

            VoxelIntersection hit = raytraceVoxel(cameraPosition, sceneDirection, MAX_RAYTRACE_STEPS);

            vec3 sunPosition  = calculateSunPosition (LATITUDE, LONGITUDE);
            vec3 moonPosition = calculateMoonPosition(LATITUDE, LONGITUDE);

            vec3 sunDirection  = normalize(sphericalToCartesian(sunPosition ));
            vec3 moonDirection = normalize(sphericalToCartesian(moonPosition));

            vec3 shadowDirection = sunAngle < 0.5 ? sunDirection : moonDirection;

            if (hit.intersect) {
                vec3 albedo = getVoxelAlbedoRGB(hit.voxel.packedData, hit.textureCoords);
                vec3 normal = getMaterialNormal(hit.voxel.packedData, hit.textureCoords, hit.normal);

                float visibility = dot(normal, shadowDirection);

                #if defined WORLD_OVERWORLD
                    VoxelIntersection shadowRay = raytraceVoxel(hit.position + hit.normal * 1e-3, shadowDirection, MAX_PT_SHADOW_STEPS);

                    if (shadowRay.intersect) {
                        visibility *= 0.5;
                    }
                #endif

                visibility = clamp(visibility, 0.1, 1.0);

                lighting = albedo * visibility;
            }
            else {
                lighting = vec3(0.0);
            }

            lighting += (dot(sceneDirection, sunDirection ) < cos(sunAngularRadius ) ? vec3(0.0) : vec3(0.87, 0.63, 0.08));
            lighting += (dot(sceneDirection, moonDirection) < cos(moonAngularRadius) ? vec3(0.0) : vec3(1.0             ));
        }

    #endif

    imageStore(colorimg0, ivec2(gl_GlobalInvocationID.xy), vec4(lighting, 0.0));
}
