ISF - Generators - VoxelEngine


/*{
	"CREDIT": "mojovideotech",
	"CATEGORIES": [
		"Generator",
		"voxels"
	],
	"DESCRIPTION": "Simple to reuse, fast voxel engine.",
	"INPUTS": [
		{
			"NAME": "rate",
			"TYPE": "float",
			"DEFAULT": 1,
			"MIN": 0,
			"MAX": 3
		},
		{
			"NAME": "rot",
			"TYPE": "float",
			"DEFAULT": 0.025,
			"MIN": -0.25,
			"MAX": 0.25
		},
		{
			"NAME": "light",
			"TYPE": "point2D",
			"DEFAULT": [
				-0.3,
				-0.2
			],
			"MAX": [
				1,
				1
			],
			"MIN": [
				-1,
				-1
			]
		},
		{
			"NAME": "tilt",
			"TYPE": "float",
			"MIN": 1.01,
			"MAX": 1.99,
			"DEFAULT": 1.88
		},
		{
			"NAME": "dof",
			"TYPE": "float",
			"MIN": 0.01,
			"MAX": 5,
			"DEFAULT": 0.88
		},
		{
			"NAME": "zoom",
			"TYPE": "float",
			"MIN": 6,
			"MAX": 50,
			"DEFAULT": 30
		},
		{
			"NAME": "grow",
			"TYPE": "float",
			"MIN": 0,
			"MAX": 8,
			"DEFAULT": 4.5
		},
		{
			"NAME": "seed1",
			"TYPE": "float",
			"MIN": 1,
			"MAX": 24,
			"DEFAULT": 6.84
		},
		{
			"NAME": "seed2",
			"TYPE": "float",
			"MIN": -12,
			"MAX": 12,
			"DEFAULT": -7.16
		},
		{
			"NAME": "seed3",
			"TYPE": "float",
			"MIN": 0,
			"MAX": 1,
			"DEFAULT": 0.53
		},
		{
			"NAME": "color",
			"TYPE": "float",
			"DEFAULT": 8.65,
			"MIN": -8,
			"MAX": 16
		},
		{
			"NAME": "loops",
			"TYPE": "float",
			"DEFAULT": 23,
			"MIN": 8,
			"MAX": 80
		},
		{
			"NAME": "c1",
			"TYPE": "color",
			"DEFAULT": [
				1,
				0,
				0,
				1
			]
		},
		{
			"NAME": "c2",
			"TYPE": "color",
			"DEFAULT": [
				0.7,
				1,
				0.1,
				1
			]
		}
	],
	"ISFVSN": 2
}
*/

////////////////////////////////////////////////////////////////////
// VoxelEngine  by mojovideotech
//
// based on :
// shadertoy.com\/view\/4tlfDn
//
// License Creative Commons Attribution-NonCommercial-ShareAlike 3.0
////////////////////////////////////////////////////////////////////

#define 	twpi  	6.2831853  	// two pi, 2*pi

const vec3 backgroundColor = vec3(0.0, 0.0, 0.0);
const float shadow = 0.5;

float setCamera(out vec3 eye, out vec3 center) {
    vec2 m = vec2(rot * TIME, 0.5);
    m *= twpi * vec2(1.0, tilt);    
    center = vec3(0.0);
    float D = 50.0 - zoom;
    eye = center + vec3(D * sin(m.x) * sin(m.y), D * cos(m.x) * sin(m.y), D * cos(m.y));
    return dof;
}

bool voxelHit(vec3 pos) {
    vec3 hash = fract(pos * vec3(28.657, 51.4229, 1.597));
    hash = mix(hash, dot(hash.zxy, hash.yzx)-hash, seed3);
    return length(pos) + seed2 * fract((hash.x + hash.y) * hash.z) < seed1 + grow * sin(TIME * rate);
}

vec3 voxelColor(vec3 pos, vec3 norm) { return mix(c1.rgb, c2.rgb, (length(floor(pos*fract(seed2))) - color)/seed1); }

float castRay(vec3 eye, vec3 ray, out float dist, out vec3 norm) {
    vec3 pos = floor(eye);
    vec3 ri = 1.0 / ray;
    vec3 rs = sign(ray);
    vec3 ris = ri * rs;
    vec3 dis = (pos - eye + 0.5 + rs * 0.5) * ri;
    vec3 dim = vec3(0.0);
    float II = 0.0;
    for (int i = 0; i < 80; ++i) {
    	if(II>=loops) { break; }
        if (voxelHit(pos)) {
            dist = dot(dis - ris, dim);
            norm = -dim * rs;
            return 1.0;
        }
        dim = step(dis, dis.yzx);
		dim *= (1.0 - dim.zxy);
        dis += dim * ris;
        pos += dim * rs;
        II += 1.0;
    }
	return 0.0;
}

void main() {
	float dist;
    vec3 eye, center, norm;
    float zoom = setCamera(eye, center);
    vec3 lightDir = vec3(light.xy, 0.8);
    vec3 forward = normalize(center - eye);
    vec3 right = normalize(cross(forward, vec3(0.0, 0.0, 1.0)));
    vec3 up = cross(right, forward);
    vec2 xy = 2.0 * gl_FragCoord.xy - RENDERSIZE.xy;
    vec3 ray = normalize(xy.x * right + xy.y * up + zoom * forward * RENDERSIZE.y);
    float hit = castRay(eye, ray, dist, norm);
    vec3 pos = eye + dist * ray;
    vec3 col = voxelColor(pos - 0.001 * norm, norm);
    float shade = dot(norm, lightDir);
    float illuminated = 1.0 - castRay(pos + 0.001 * norm, lightDir, dist, norm);
    float light = (1.0 + shadow * (illuminated * max(shade, 0.0) - 1.0)) * (1.0 - max(-shade, 0.0));

    gl_FragColor = vec4(mix(backgroundColor, light * col, hit), 1.0);
}