three-d 0.19.0

2D/3D renderer - makes it simple to draw stuff across platforms (including web)
Documentation
uniform vec3 cameraPosition;
uniform vec4 surfaceColor;
uniform float metallic;
uniform float roughness;
uniform sampler3D tex;
uniform vec3 size;
uniform float threshold;
uniform vec3 h;

in vec3 pos;

layout (location = 0) out vec4 outColor;

vec3 estimate_normal(vec3 uvw) {
    float x = texture(tex, uvw + vec3(h.x, 0.0, 0.0)).r - texture(tex, uvw - vec3(h.x, 0.0, 0.0)).r;
    float y = texture(tex, uvw + vec3(0.0, h.y, 0.0)).r - texture(tex, uvw - vec3(0.0, h.y, 0.0)).r;
    float z = texture(tex, uvw + vec3(0.0, 0.0, h.z)).r - texture(tex, uvw - vec3(0.0, 0.0, h.z)).r;
    return -normalize(vec3(x, y, z) / (2.0 * h));
}

void main() {
    int steps = 200;
    vec3 rayDir = normalize(pos - cameraPosition);
    // Start the ray from the camera position by default
    const float minDistFromCamera = 0.2;
    vec3 rayPos = cameraPosition + minDistFromCamera * rayDir;
    float stepSize = length(size) / float(steps);
    vec3 step = rayDir * stepSize;
    for (int i = 0; i < 200; i++) {
        if (i == steps-1) {
            // Out of steps: transparent
            outColor = vec4(0.0, 0.0, 0.0, 0.0);
            break;
        }
        if (rayPos.x < -0.501*size.x || rayPos.y < -0.501*size.y || rayPos.z < -0.501*size.z ||
        rayPos.x > 0.501*size.x || rayPos.y > 0.501*size.y || rayPos.z > 0.501*size.z) {
            // Out of bounds
            if (i == 0) {
                // Use the contact point on the box as the starting point
                rayPos = pos;
            } else {
                // Debug the number of steps:
                //outColor = vec4(0.0, float(i)/float(steps), 0.0, 1.0);
                outColor = vec4(0.0, 0.0, 0.0, 0.0);
                break;
            }
        }
        vec3 uvw = (rayPos / size) + 0.5;
        float surfaceDensity = texture(tex, uvw).r - threshold;
        if (surfaceDensity >= 0.0) { // We hit the surface
            vec3 normal = estimate_normal(uvw);
            outColor.rgb = calculate_lighting(cameraPosition, surfaceColor.rgb, rayPos, normal, metallic, roughness, 1.0);
            outColor.rgb = tone_mapping(outColor.rgb);
            outColor.rgb = color_mapping(outColor.rgb);
            outColor.a = surfaceColor.a;
            break;
        }
        rayPos += step;
    }
}