#version 330 core

out vec4 fragColor;

uniform vec2 _iResolution;
uniform uint _maxSteps;
uniform vec3 _camPose;
uniform vec3 _lookingAt;
uniform vec3 _camUp;
uniform float _fx;
uniform float _stopEpsilon;
uniform float _tmax;

{% for i in global_inputs -%}
uniform {{ i.type }} {{ i.name }};
{% endfor %}

float map(in vec3 p)
{
    float d;
    {% for line in lines -%}
    {{line}}
    {% endfor %}
    return d;
}

vec4 mainImage( in vec2 fragCoord )
{
    vec3 cam_norm = normalize(_lookingAt - _camPose);
    vec3 cam_right = normalize(cross(cam_norm, _camUp));
    vec3 cam_down = normalize(cross(cam_right, cam_norm));
    float fy = (_fx / _iResolution.x) * _iResolution.y;

    vec2 normalized_coord = (fragCoord / _iResolution) - 0.5;
    normalized_coord.x = normalized_coord.x * _fx;
    normalized_coord.y = normalized_coord.y * fy;

    vec3 p0 = cam_right * normalized_coord.x + cam_down * normalized_coord.y;
    p0 += _camPose;

        
    vec3 tot = vec3(0.0);

    // raymarch
    const float tmax = 3.0;
    float t = 0.0;
    float h = 0.0;
    vec3 pos;
    for( uint i=0u; i<_maxSteps; i++ )
    {
        pos = p0 + t*cam_norm;
        h = map(pos);
        if( h<_stopEpsilon || t>_tmax ) break;
        t += h;
    }
    float opacity = 0.0;
    if( h<_stopEpsilon ) opacity = 1.0;

    return vec4(mod(pos, 1.0), opacity);
}

void main() {
    fragColor = mainImage(gl_FragCoord.xy);
}
