Created
April 29, 2019 21:37
-
-
Save benhardy/b58b463d24d2249dd6e53bdbc24b9dde to your computer and use it in GitHub Desktop.
This file contains hidden or 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
#define MAX_STEPS 100000 | |
#define MAX_DIST 300.0f | |
#define EPSILON 0.001f | |
#define ID_SPHERE 1 | |
#define ID_BIZZO 2 | |
#define ID_FLOOR 3 | |
#define ID_COLUMN 4 | |
#define BIZZO_ITERATIONS 6 | |
float measure_floor(float3 where); | |
float cmod(float x, float r); | |
float2 dist_bizzo(float3 where, float iTime); | |
float measure_column(float3 where); | |
float3 measure(float3 where, float iTime); | |
float3 calc_surface_normal(float3 hit, float iTime); | |
float dist_opening(float3 pos); | |
float dist_surrounding_sphere(float3 where); | |
float round_box(float3 where, float3 dims, float rounding); | |
float dist_balcony(float3 pos); | |
float measure_floor(float3 where) { | |
return where.y + 1.0f; | |
} | |
float cmod(float x, float r) { | |
x = x/r + 0.5; | |
return (x-floor(x)-0.5) * r; | |
} | |
float round_box(float3 where, float3 dims, float rounding) { | |
return length(fmax(0.0f, fabs(where) - dims)) - rounding; | |
} | |
float dist_balcony(float3 pos) { | |
float r_min = 95; | |
float r_max = 105; | |
float r = length(pos.xz); | |
float cyl = max(r - r_max, - (r - r_min)); | |
return fmax(cyl, fmax(pos.y, -pos.y - 1)); | |
} | |
float dist_opening(float3 pos) { | |
pos.y -= 6.0; | |
pos.xz = fabs(pos.xz); | |
//pos.x += 100.0; | |
float3 dims = { 120, 5.0, 50 }; | |
float op = round_box(pos, dims, 1.0); | |
return op; | |
} | |
float dist_surrounding_sphere(float3 where) { | |
float ball = length(where) -100.0f; | |
//float clearing = fmax(fabs(where.y) - 3.0f; | |
float op = dist_opening(where); | |
float walls = fmax(-ball, -op); | |
float2 edging = { ball, op-0.9 }; | |
float2 edgebox = { 0.9, 0.9 }; | |
float edge_d = length(max(0.0,fabs(edging)-edgebox)); | |
walls = fmin(walls, edge_d); | |
//where.y += 3.0; | |
//float with_b = fmin(walls, dist_balcony(fabs(where))); | |
float w = fmin(walls, dist_balcony(where)); | |
return w; | |
} | |
__constant float3 box_size = { 1.7, 0.7, 2.7 }; | |
__constant float3 hole_size = { 1, 0.5, 4 }; | |
__constant float3 box_top_size = { 1, 0.5, 2.2 }; | |
float2 dist_bizzo(float3 where, float iTime) { | |
float d = length(where) -1.0; | |
float ratio = 1.75 + 0.1 * sin(iTime * 0.13f); | |
float a2 = 1.0 + 1.0 * sin(iTime *0.49f) + 0.5f * where.y; | |
float s2 = sin(a2); | |
float c2 = cos(a2); | |
float a3 = 1.0 * sin(iTime *0.29f) + 0.15f * 0.5 * where.x ; | |
float s3 = sin(a3); | |
float c3 = cos(a3); | |
float a = 1.0 + sin(iTime * 0.39f) + 0.15f * cos(where.z); | |
float s = sin(a); | |
float c = cos(a); | |
float depth = 0.0; | |
float3 displacement = { | |
-2.2f + c, | |
2.5f + 0.9f * s, | |
-1.5f + 0.9f * sin(iTime * 0.13f) | |
}; | |
for (int i = 0; i <BIZZO_ITERATIONS; i++) { | |
const float3 w2 = { | |
mad(c3, mad(c2, where.x, - s2 * where.z), - s3 * where.y), | |
mad(s3, mad(c2, where.x, - s2 * where.z), + c3 * where.y), | |
mad(s2, where.x, c2 * where.z) | |
}; | |
// a bit of good old fashioned space foldin' & swizzlin' | |
where = -fabs(w2); | |
where.xz = -where.zx; | |
// shit gets real here, i guess you'd call it hyperbolic warping | |
where.y = -5.0/mad(length(where.yz), length(where.yz), 1.0f); | |
// shrink and displace for this fractal level | |
where = mad(where, ratio, displacement); | |
// actual measurement for this fractal level | |
float j = 0.5 * (length(where) -1.0) / ratio; | |
// blend function body, disassembled so we can make a fractional depth measurement for coloring | |
float k = 0.2; | |
float h = fmax( k - fabs(d - j), 0.0f ); | |
float together = fmin(d, j); | |
d= together - h*h*0.25f/k; | |
float progress = clamp((j-d)/k, 0.0f, 1.0f); | |
depth+=progress; | |
} | |
return (float2)(d, depth+1); | |
} | |
float measure_column(float3 where) { | |
where.z = cmod(where.z, 25.0f); | |
where.x = cmod(where.x, 25.0f); | |
float s = sin(where.y); | |
float c = cos(where.y); | |
float3 w2 = { | |
c * where.x - s * where.z, | |
where.y, | |
s * where.x + c * where.z | |
}; | |
float3 w3 = { | |
fabs(w2.x)-0.2, | |
w2.y, | |
fabs(w2.z)-0.2 | |
}; | |
return length(w3.xz) - 0.2f; | |
} | |
float3 measure(float3 where, float iTime) { | |
float closestDist = MAX_DIST; | |
float what = 0; | |
float d; | |
float extra = 0; | |
/*float d = measure_floor(where); | |
if (d < closestDist) { | |
closestDist = d; | |
what = ID_FLOOR; | |
} | |
*/ | |
float2 biz = dist_bizzo(where, iTime); | |
if (biz.x < closestDist) { | |
closestDist = biz.x; | |
what = ID_BIZZO; | |
extra = biz.y; | |
} | |
d = dist_surrounding_sphere(where); | |
if (d < closestDist) { | |
closestDist = d; | |
what = ID_SPHERE; | |
} | |
/* | |
d = measure_column(where); | |
if (d < closestDist) { | |
closestDist = d; | |
what = ID_COLUMN; | |
} | |
*/ | |
float3 res = { closestDist, what, extra }; | |
return res; | |
} | |
__constant float4 color_box_top = { 0.2, 0.87, 0.9, 0.5 }; | |
__constant float4 color_box_bot = { 0.40, 0.42, 0.6, 0.75 }; | |
__constant float4 color_outer_walls = { 0.8, 0.8, 0.8, 0.75 }; | |
__constant float4 bizzo_color = { 0.05, 0.2, 0.16, 0.2 }; | |
__constant float4 bizzo_lightening_color = { 1,1,0.5,1 }; | |
__kernel void raymarchDemo2( | |
__global uint *output, | |
int sizeX, int sizeY, | |
float eyeX, float eyeY, float eyeZ, | |
float lookX, float lookY, float lookZ, | |
float stepRatio, | |
float iTime | |
) | |
{ | |
// pixel coordinates | |
const int ix = get_global_id(0); | |
const int iy = get_global_id(1); | |
const float3 eye = { eyeX, eyeY, eyeZ }; | |
const float3 look = normalize((float3)(lookX, lookY, lookZ)); | |
const float3 cameraUp = { 0, 1, 0 }; | |
const float x_pixel = (float)ix / sizeX - 0.5; | |
const float y_pixel = -((float)iy / sizeY - 0.5) * (float)sizeY / sizeX; | |
const float3 right = normalize(cross(cameraUp, look)); | |
const float3 actual_up = normalize(cross(look, right)); | |
const float3 ray = normalize(look + (right * x_pixel) + (actual_up * y_pixel)); | |
float t = 0.0; | |
int hitId = 0; | |
float3 hitInfo; | |
float3 where = eye; | |
for (int step = 0; step < MAX_STEPS && t < MAX_DIST; step++) { | |
where = eye + (t * ray); | |
hitInfo = measure(where, iTime); | |
if (hitInfo.x < EPSILON) { | |
hitId = (int)(hitInfo.y); | |
break; | |
} | |
t += (stepRatio * hitInfo.x); | |
} | |
float4 pigment; | |
switch(hitId) { | |
case ID_FLOOR: { | |
int level = ((int)floor(where.x) ^ (int)floor(where.z)) & 0x01; | |
pigment = (float4)( | |
1, | |
level, | |
level, | |
0.5 | |
); | |
break; | |
} | |
case ID_BIZZO: { | |
pigment = bizzo_color + (hitInfo.z/BIZZO_ITERATIONS) * bizzo_lightening_color; | |
break; | |
} | |
case ID_SPHERE: { | |
float3 pp = where / 10.0f; | |
int level = ((int)floor(pp.x) ^ (int)floor(pp.y) ^ (int)floor(pp.z)) & 0x01; | |
pigment = color_outer_walls * (1.0f + 0.1f * level); | |
break; | |
} | |
case ID_COLUMN: { | |
pigment = (float4)( | |
1, | |
1, | |
0, | |
0.5 | |
); | |
break; | |
} | |
default: { | |
pigment = (float4)(0,0,0,1); | |
break; | |
} | |
} | |
float3 lightDir = normalize((float3)( -1, 3, -2)); | |
float3 norm = calc_surface_normal(where, iTime); | |
float ambient = pigment.w; | |
float diffuse = (1.0f - ambient) * fmax(0.0f, dot(lightDir, norm)); | |
float3 reflected = norm * 2.0f * dot(lightDir, norm) - lightDir; | |
float specular = pow(fmax(0.0f, dot(-ray, reflected)), 32.0f); | |
float3 specColor = { specular, specular, specular }; | |
float4 color = (pigment * (diffuse + ambient) + specular) * (1.0f - t/MAX_DIST); | |
color = clamp(color, 0.0f, 1.0f) * 255; | |
output[iy*sizeX+ix] = ((int)(color.x)<<16) | ((int)(color.y)<<8) | ((int)(color.z)) | ((int)(color.z)<<24); | |
} | |
#define NORMAL_DELTA 0.001 | |
__constant float3 normalBumpX = { NORMAL_DELTA, 0, 0 }; | |
__constant float3 normalBumpY = { 0, NORMAL_DELTA, 0 }; | |
__constant float3 normalBumpZ = { 0, 0, NORMAL_DELTA }; | |
float3 calc_surface_normal(float3 hit, float iTime) { | |
return normalize((float3)( | |
measure(hit+normalBumpX, iTime).x - measure(hit-normalBumpX, iTime).x, | |
measure(hit+normalBumpY, iTime).x - measure(hit-normalBumpY, iTime).x, | |
measure(hit+normalBumpZ, iTime).x - measure(hit-normalBumpZ, iTime).x | |
)); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment