Skip to content

Instantly share code, notes, and snippets.

@aman-tiwari
Created September 29, 2018 20:55
Show Gist options
  • Save aman-tiwari/fddabe17962a473f778cb3ab1688ce28 to your computer and use it in GitHub Desktop.
Save aman-tiwari/fddabe17962a473f778cb3ab1688ce28 to your computer and use it in GitHub Desktop.
basic kodelife raymarch with outlines
#version 150
// these are set by kodelife
uniform float time;
uniform vec2 resolution;
uniform vec2 mouse;
uniform vec3 spectrum;
uniform sampler2D texture0;
uniform sampler2D texture1;
uniform sampler2D texture2;
uniform sampler2D texture3;
uniform sampler2D prevFrame;
uniform sampler2D prevPass;
in VertexData
{
vec4 v_position;
vec3 v_normal;
vec2 v_texcoord; // coordinate of the fragment, [0-1]
} inData;
// set this variable in main to the color you want to be displayed
out vec4 fragColor;
// from http://iquilezles.org/www/articles/distfunctions/distfunctions.htm
// signed distance function for a box with at p with sides of length s
float sdBox( vec3 p, vec3 b )
{
vec3 d = abs(p) - b;
return min(max(d.x,max(d.y,d.z)),0.0) + length(max(d,0.0));
}
// union two signed distance functions with a smooth join
// from https://www.iquilezles.org/www/articles/smin/smin.htm
float smin( float a, float b, float k )
{
float h = clamp( 0.5+0.5*(b-a)/k, 0.0, 1.0 );
return mix( b, a, h ) - k*h*(1.0-h);
}
float scene(vec3 p) {
float sphere = length(p) - 1.0;
// this offsets the cube left-right
float box = sdBox(p - vec3(sin(time) * 2.0 + 2.0, 0.0, 0.0), vec3(0.1, 2.1, 1.0));
return smin(sphere, box, 0.5);
}
// central difference approximation to normal vector of the scene
vec3 calcNormal(vec3 pos, float eps) {
const vec3 v1 = vec3( 1.0,-1.0,-1.0);
const vec3 v2 = vec3(-1.0,-1.0, 1.0);
const vec3 v3 = vec3(-1.0, 1.0,-1.0);
const vec3 v4 = vec3( 1.0, 1.0, 1.0);
return normalize( v1 * scene( pos + v1*eps ) +
v2 * scene( pos + v2*eps ) +
v3 * scene( pos + v3*eps ) +
v4 * scene( pos + v4*eps ));
}
vec3 calcNormal(vec3 pos) {
return calcNormal(pos, 0.002);
}
#define STEPS (50)
#define MIN_DIST (0.001)
// raymarching function!
// ro = ray origin
// rd = ray direction
// hitPoint <- will be set if we hit the surface to where we hit
// minDist <- will be set to the minimum distance to the surface the ray encountered
bool raymarch(vec3 ro, vec3 rd,
out vec3 hitPoint,
out float minDist) {
vec3 pos = ro;
minDist = 100.0;
for(int i = 0; i < STEPS; i++) {
float dist = scene(pos);
if(dist < MIN_DIST) {
hitPoint = pos + rd * dist;
return true;
}
pos += rd * dist;
minDist = min(dist, minDist);
}
return false;
}
void main(void)
{
float aspect = resolution.x / resolution.y;
vec2 uv = -1.0 + 2.0 * inData.v_texcoord;
uv.x *= aspect;
vec3 rayOrigin = vec3(0.0, 0.0, -4.0);
vec3 rayDir = normalize(vec3(uv, 2.0));
vec3 hitPos; // this will be set by raymarch to the point on the surface we hit
vec3 color = vec3(1.0);
float minDist = 100.0; // minimum distance to surface encountered
if(raymarch(rayOrigin, rayDir, hitPos, minDist)) { // if hit surface
vec3 nor = calcNormal(hitPos);
vec3 light = vec3(-1.0, -1.0, 0.0);
float diffuseIntesity = clamp(dot(nor, light), 0.0, 1.0);
color = mix(vec3(1.0, 0.0, 0.0), // light colour
vec3(0.0, 0.0, 1.0), // shadow colour
diffuseIntesity);
// uncomment below line to visualise the normals
//color = nor * 0.5 + 0.5;
} else if(minDist < 0.05) { // if near miss to surface
color = vec3(0.0, 0.0, 0.0);
}
fragColor = vec4(color, 1.0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment