// EndPropGI.glsl - Освещение от пропа через raymarching (как GI)
#ifndef END_PROP_GI_INCLUDED
#define END_PROP_GI_INCLUDED

// === НАСТРОЙКИ ===
const vec3 END_PROP_POSITION = vec3(0.0, 80.0, 0.0);
const float END_PROP_RADIUS = 256.0;
const vec3 END_PROP_COLOR = vec3(5.0, 4.5, 4.0); // Увеличил яркость света

// Raymarching настройки
#ifndef PROP_SHADOW_STEPS
#define PROP_SHADOW_STEPS 20 // Увеличил для более точных теней [8 12 16 20 24]
#endif

// Проверяет видимость пропа через raymarching
float TracePropVisibility(vec3 viewPos, vec3 worldPos, vec3 worldNormal) {
    vec3 toProp = END_PROP_POSITION - worldPos;
    float propDist = length(toProp);
    
    // За радиусом
    if (propDist > END_PROP_RADIUS) return 0.0;
    
    vec3 propDir = toProp / propDist;
    float NdotL = max(0.0, dot(worldNormal, propDir));
    
    // Backface
    if (NdotL < 0.01) return 0.0;
    
    // Raymarching от поверхности к пропу
    float stepSize = propDist / float(PROP_SHADOW_STEPS);
    vec3 rayPos = viewPos + normalize(mat3(gbufferModelView) * propDir) * 0.1; // Начинаем ближе
    
    for (int i = 0; i < PROP_SHADOW_STEPS; i++) {
        rayPos += normalize(mat3(gbufferModelView) * propDir) * stepSize;
        
        // Преобразуем в screen space
        vec4 clipPos = gbufferProjection * vec4(rayPos, 1.0);
        clipPos.xyz /= clipPos.w;
        vec3 screenPos = clipPos.xyz * 0.5 + 0.5;
        
        // Bounds check
        if (any(lessThan(screenPos.xy, vec2(0.0))) || any(greaterThan(screenPos.xy, vec2(1.0)))) {
            break; // Вышли за экран - путь свободен
        }
        
        // Sample depth
        float sceneDepth = texture(depthtex0, screenPos.xy).x;
        if (sceneDepth >= 1.0) continue; // Sky
        
        // Преобразуем depth в view space
        vec3 ndcPos = screenPos * 2.0 - 1.0;
        vec4 tmp = gbufferProjectionInverse * vec4(ndcPos, 1.0);
        vec3 sceneViewPos = tmp.xyz / tmp.w;
        
        // Проверка пересечения - сделал более чувствительной
        float rayZ = rayPos.z;
        float surfaceZ = sceneViewPos.z;
        float thickness = 0.5; // Увеличил толщину для надёжности
        
        if (rayZ < surfaceZ && rayZ > surfaceZ - thickness) {
            // Окклюзия! Луч заблокирован
            return 0.0;
        }
    }
    
    // Луч дошёл до пропа - есть видимость!
    // Применяем затухание
    float attenuation = 1.0 - smoothstep(0.0, END_PROP_RADIUS, propDist);
    attenuation = attenuation * attenuation * attenuation; // Кубическое затухание для более резкого контраста
    
    return NdotL * attenuation * 2.0; // Умножаем на 2 для яркости
}

// Вычисляет освещение от пропа
vec3 CalculatePropLighting(vec3 viewPos, vec3 worldPos, vec3 worldNormal) {
    float visibility = TracePropVisibility(viewPos, worldPos, worldNormal);
    
    if (visibility < 0.001) return vec3(0.0);
    
    return END_PROP_COLOR * visibility;
}

// Рендерит проп на небе
vec3 RenderPropInSky(vec3 viewDir, vec3 cameraPos) {
    vec3 toProp = normalize(END_PROP_POSITION - cameraPos);
    float angle = dot(viewDir, toProp);
    
    const float propSize = 0.02;
    if (angle < cos(propSize)) return vec3(0.0);
    
    float intensity = pow(saturate((angle - cos(propSize)) / (1.0 - cos(propSize))), 2.0);
    return END_PROP_COLOR * intensity * 50.0;
}

#endif // END_PROP_GI_INCLUDED