NOTE: This site has just upgraded to Forester 5.x and is still having some style and functionality issues, we will fix them ASAP.

test ray-marching [uts-0016]

From :

float SDSphere(in vec3 worldCoordinate, in vec3 center, in float radius) {

    return distance(worldCoordinate, center) - radius;

}

float SDPlane(in vec3 worldCoordinate, in float planeHeight, in vec3 rayDirection) {

    return (worldCoordinate.y - planeHeight)/abs(rayDirection.y);

}

float SDOctahedron( vec3 p, float s)
{
  p = abs(p);
  return (p.x+p.y+p.z-s)*0.57735027;
}


float SDScene(in vec3 worldCoordinate, in vec3 rayDirection) {

    float sphereOne = SDSphere(worldCoordinate, vec3(0.0, 0.0, 0.0), 0.5);
    //float sphereTwo = SDSphere(worldCoordinate, vec3(cos(iTime/3.0), -0.3, sin(iTime/5.0)), 0.2);
    //float sphereThree = SDSphere(worldCoordinate, vec3(sin(iTime/5.0), 0.3, cos(iTime/5.0)), 0.2);
    float orbital = SDOctahedron(worldCoordinate - vec3(cos(iTime/2.0), -0.15, sin(iTime/2.0)), 0.2);
    
    float groundPlane = SDPlane(worldCoordinate, -0.5, rayDirection);

    return min(min(sphereOne, orbital), groundPlane);

}


# define EPSILON 0.001

vec3 estimateNormal(in vec3 worldCoordinate) {

    if (worldCoordinate.y < -0.49) return vec3(0.0, 1.0, 0.0);

    float partialX = SDScene(worldCoordinate + vec3(EPSILON, 0.0, 0.0), vec3(0.0, 0.0, 1.0)) - SDScene(worldCoordinate - vec3(EPSILON, 0.0, 0.0), vec3(0.0, 0.0, 1.0));
    float partialY = SDScene(worldCoordinate + vec3(0.0, EPSILON, 0.0), vec3(0.0, 0.0, 1.0)) - SDScene(worldCoordinate - vec3(0.0, EPSILON, 0.0), vec3(0.0, 0.0, 1.0));
    float partialZ = SDScene(worldCoordinate + vec3(0.0, 0.0, EPSILON), vec3(0.0, 0.0, 1.0)) - SDScene(worldCoordinate - vec3(0.0, 0.0, EPSILON), vec3(0.0, 0.0, 1.0));
    
    return normalize(vec3(partialX, partialY, partialZ));

}


# define MAX_STEPS 105

vec3 rayMarch(in vec3 rayOrigin, in vec3 rayDirection) {

    vec3 ray = rayOrigin;

    for (int index = 0; index < MAX_STEPS; index++) {
   
        float distanceToScene = SDScene(ray, rayDirection);
        
        if (distanceToScene < EPSILON) return ray;
        
        ray += distanceToScene * rayDirection;
    
    }
    
    return vec3(0.0, 0.0, 0.0);

}


void mainImage(out vec4 pixelColor, in vec2 pixelCoordinate) {
    
    float aspect = iResolution.x/iResolution.y;
    
    vec2 uv = pixelCoordinate/iResolution.xy;
    
    uv -= vec2(0.5, 0.5);
    uv *= 2.0 * vec2(aspect, 1.0);
    
    vec3 observerPosition = vec3(0.0, 0.0, -5.0);
    
    vec3 cameraBox = observerPosition + vec3(uv, 5.0);
    
    vec3 rayDirection = normalize(cameraBox - observerPosition);
    vec3 worldCoordinate = rayMarch(observerPosition, rayDirection);
    
    float renderable = length(worldCoordinate) > 0.0 ? 1.0 : 0.0;
    
    vec3 surfaceNormal = estimateNormal(worldCoordinate);
    float fresnel = 0.9 + dot(surfaceNormal, rayDirection);
    
    vec3 lightSource = vec3(7.0 * cos(iTime), 5.0, 7.0 * sin(iTime));
    
    vec3 photonDirection = normalize(worldCoordinate - lightSource);
    vec3 photonPosition = rayMarch(lightSource, photonDirection);
    
    float directLight = 1.2 - step(0.01, distance(photonPosition, worldCoordinate));
    
    float diffuseLight = 0.25 * smoothstep(0.0, 1.0, directLight * dot(surfaceNormal, -photonDirection));
    
    float ambientLight = 0.7;

    float specularLight = 0.1 * smoothstep(0.0, 1.0, dot(reflect(photonDirection, surfaceNormal), normalize(observerPosition - worldCoordinate)));

    float scatterFactor = 1.0 / sqrt(distance(worldCoordinate, lightSource)/5.0);

    pixelColor = vec4(renderable * (diffuseLight + ambientLight + specularLight) * scatterFactor * vec3(1.0, 1.0, 1.0), 1.0);
    
}