Created
January 23, 2013 16:05
-
-
Save ishikawash/4608718 to your computer and use it in GitHub Desktop.
Distance function : example program
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 120 | |
// === vertex shader | |
// | |
// When you use OpenGL Shader Builder to execute shader programs, | |
// * select plane as geometry | |
// * set resolution to 640x480 | |
// * set scale_factor to 2.5 | |
uniform vec2 resolution; | |
const float scale_factor = 2.5; | |
void main() | |
{ | |
float aspect = resolution.y/resolution.x; | |
vec2 v = vec2(scale_factor*gl_Vertex.x, aspect*scale_factor*gl_Vertex.y); | |
gl_Position = gl_ModelViewProjectionMatrix * vec4(v.x, v.y, 0.0, 1.0); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#version 120 | |
// === fragment shader | |
// | |
// reference | |
// * http://www.iquilezles.org/www/articles/raymarchingdf/raymarchingdf.htm | |
// * http://www.iquilezles.org/www/articles/distfunctions/distfunctions.htm | |
uniform float time; | |
uniform vec2 resolution; | |
uniform vec4 light_direction; | |
const float EPSILON = 1.0e-4; | |
const int ITERATION_MAX = 48; | |
float sdSphere( vec3 p, float s ) | |
{ | |
return length(p)-s; | |
} | |
float udRoundBox( vec3 p, vec3 b, float r ) | |
{ | |
return length(max(abs(p)-b,0.0))-r; | |
} | |
float sdTorus( vec3 p, vec2 t ) | |
{ | |
vec2 q = vec2(length(p.xz)-t.x,p.y); | |
return length(q)-t.y; | |
} | |
float opU( float d1, float d2 ) | |
{ | |
return min(d1,d2); | |
} | |
mat4 translate_matrix(float x, float y, float z) | |
{ | |
mat4 m = mat4(1.0); | |
m[3][0] = x; | |
m[3][1] = y; | |
m[3][2] = z; | |
return m; | |
} | |
mat4 scale_matrix(float x, float y, float z) | |
{ | |
mat4 m = mat4(1.0); | |
m[0][0] = x; | |
m[1][1] = y; | |
m[2][2] = z; | |
return m; | |
} | |
mat4 rotate_matrix(vec3 n, float theta) | |
{ | |
float c = cos(theta); | |
float s = sin(theta); | |
mat4 m = mat4(1.0); | |
m[0][0] = n.x*n.x*(1.0 - c) + c; | |
m[1][0] = n.x*n.y*(1.0 - c) + n.z*s; | |
m[2][0] = n.z*n.x*(1.0 - c) - n.y*s; | |
m[0][1] = n.x*n.y*(1.0 - c) - n.z*s; | |
m[1][1] = n.y*n.y*(1.0 - c) + c; | |
m[2][1] = n.y*n.z*(1.0 - c) + n.x*s; | |
m[0][2] = n.z*n.x*(1.0 - c) + n.y*s; | |
m[1][2] = n.y*n.z*(1.0 - c) - n.x*s; | |
m[2][2] = n.z*n.z*(1.0 - c) + c; | |
return m; | |
} | |
float compute_distance(vec3 position) | |
{ | |
// return sdTorus(position, vec2(1.0, 0.5)); | |
float d1 = sdSphere(position, 2.0); | |
float d2 = udRoundBox(position, vec3(1.4), 0.1); | |
return opU(d1, d2); | |
} | |
vec3 estimate_normal(vec3 p) | |
{ | |
float dx = compute_distance(vec3(p.x + EPSILON, p.y, p.z)) - compute_distance(vec3(p.x - EPSILON, p.y, p.z)); | |
float dy = compute_distance(vec3(p.x, p.y + EPSILON, p.z)) - compute_distance(vec3(p.x, p.y - EPSILON, p.z)); | |
float dz = compute_distance(vec3(p.x, p.y, p.z + EPSILON)) - compute_distance(vec3(p.x, p.y, p.z - EPSILON)); | |
return normalize(vec3(dx, dy, dz)); | |
} | |
vec4 shade(vec3 N, vec3 L) | |
{ | |
float kd = clamp(dot(N, L), 0.0, 1.0); | |
return vec4(kd, kd, kd, 1.0); | |
} | |
void main() | |
{ | |
float aspect = resolution.y/resolution.x; | |
vec2 uv = 2.0*gl_FragCoord.xy/resolution - 1.0; | |
uv.y = aspect*uv.y; | |
vec3 ray_origin = vec3(0.0, 0.0, 5.0); | |
vec3 ray_direction = normalize(vec3(uv - ray_origin.xy, -1.0)); | |
mat4 M = rotate_matrix(vec3(0.0, 1.0, 0.0), 0.7) * rotate_matrix(vec3(1.0, 0.0, 0.0), time) * scale_matrix(1.0, 1.0, 1.0) * translate_matrix(0.0, 0.0, 1.0); | |
vec3 L = normalize(-1.0 * ( M * light_direction ).xyz); | |
vec3 N = vec3(0.0); | |
float t = 0.0; | |
bool hit = false; | |
for (int i = 0; i < ITERATION_MAX; i++) { | |
vec3 p = ( M * vec4(ray_origin + t*ray_direction, 1.0) ).xyz; | |
float d = compute_distance(p); | |
if (d < EPSILON) { | |
N = estimate_normal(p); | |
hit = true; | |
break; | |
} | |
t += d; | |
} | |
if (hit) { | |
gl_FragColor = shade(N, L); | |
} else { | |
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment