#version 300 es
precision mediump float;
in vec2 fragCoord;
out vec4 fragColor;

uniform float aspectRatio;
uniform float elapsedTime;
uniform vec2 mousePosition;
uniform int mouseButtons;
uniform vec3 cameraPos;
-
bool hasVoxelAt(ivec3 pos) {
    float x = float(pos.x) / 5.0, y = float(pos.y) / 5.0, z = float(pos.z) / 5.0;
    return sin(x) * sin(x) + sin(y) * sin(y) + sin(z) * sin(z) >= 1.5;
}

struct stepResult {
    ivec3 voxelPos;
    vec3 normal;
    vec3 newPos;
};

stepResult stepToNextVoxel(vec3 pos, vec3 direction) {
    vec3 u = (floor(1.0 + pos * sign(direction)) * sign(direction) - pos) / direction;
    float d = min(min(u.x, u.y), u.z);
    
    vec3 normal = normalize(sign(direction) * vec3(
        u.x == d ? 1 : 0, 
        u.y == d ? 1 : 0, 
        u.z == d ? 1 : 0
    ));

    pos += d * direction;
    return stepResult(
        ivec3(pos + direction * 0.000000001),
        normal,
        pos
    );
}

vec3 fog_color = vec3(0.5, 0.75, 1.0);

vec3 raycast(vec3 start, vec3 ray) {
    for(int i = 0; i < 400; i++) {
        stepResult r = stepToNextVoxel(start, ray);
        start = r.newPos;
        vec3 normal = r.normal;
        if(hasVoxelAt(r.voxelPos)) {
            vec3 d = abs(mod(start + 0.5, 1.0) - 0.5) / (1.0 - abs(normal)) / distance(cameraPos, start);
            float d2 = min(d.x, min(d.y, d.z)) * 500.;
            
            float t = d2 <= 1. ? 0.0 : 1.0;
            vec3 faceLight = vec3(0.6 + 0.4 * dot(normal, normalize(vec3(1, -2, 3))));

            vec3 color = t * faceLight;
            float fog_amount = pow(1.0 + 0.002 * distance(cameraPos, start), -4.0);

            return color * fog_amount + fog_color * (1.0 - fog_amount);
        }
    }
    return fog_color;
}

void main(){
   float cam_distance = 1.;
   vec3 ray = normalize(vec3(fragCoord, cam_distance));
   float phi = mousePosition.x * 3.14, theta = mousePosition.y * 1.5707;
   ray = ray * vec3(1, cos(theta), cos(theta)) + ray.xzy * vec3(0, sin(theta), -sin(theta));
   ray = ray * vec3(cos(phi), 1, cos(phi)) + ray.zyx * vec3(sin(phi), 0, -sin(phi));
   vec3 v = raycast(cameraPos, ray);
   fragColor = vec4(v, 1.0);
}-
aspectRatio
elapsedTime
mousePosition
mouseButtons
cameraPos