diff --git a/assets/screenshot.PNG b/assets/screenshot.PNG index 2b1825b..0e1ca7b 100644 Binary files a/assets/screenshot.PNG and b/assets/screenshot.PNG differ diff --git a/kernels/ray_caster_kernel.cl b/kernels/ray_caster_kernel.cl index 40f974c..43a0564 100644 --- a/kernels/ray_caster_kernel.cl +++ b/kernels/ray_caster_kernel.cl @@ -13,15 +13,98 @@ float4 white_light(float4 input, float3 light, int3 mask) { } +bool cast_light_intersection_ray( + global char* map, + global int3* map_dim, + float3 ray_dir, + float3 ray_pos, + global float* lights, + global int* light_count + + ){ + + // Setup the voxel step based on what direction the ray is pointing + int3 voxel_step = { 1, 1, 1 }; + voxel_step *= (ray_dir > 0) - (ray_dir < 0); + + // Setup the voxel coords from the camera origin + int3 voxel = convert_int3(ray_pos); + + // Delta T is the units a ray must travel along an axis in order to + // traverse an integer split + float3 delta_t = fabs(1.0f / ray_dir); + + // offset is how far we are into a voxel, enables sub voxel movement + float3 offset = ((ray_pos) - floor(ray_pos)) * convert_float3(voxel_step); + + // Intersection T is the collection of the next intersection points + // for all 3 axis XYZ. + float3 intersection_t = delta_t * offset; + + // for negative values, wrap around the delta_t, rather not do this + // component wise, but it doesn't appear to want to work + if (intersection_t.x < 0) { + intersection_t.x += delta_t.x; + } + if (intersection_t.y < 0) { + intersection_t.y += delta_t.y; + } + if (intersection_t.z < 0) { + intersection_t.z += delta_t.z; + } + + // Hard cut-off for how far the ray can travel + int max_dist = 800; + int dist = 0; + + int3 face_mask = { 0, 0, 0 }; + + // Andrew Woo's raycasting algo + do { + + // If we hit a voxel + int index = voxel.x + (*map_dim).x * (voxel.y + (*map_dim).z * (voxel.z)); + int voxel_data = map[index]; + + if (voxel_data != 0) { + return true; + } + + // Fancy no branch version of the logic step + face_mask = intersection_t.xyz <= min(intersection_t.yzx, intersection_t.zxy); + intersection_t += delta_t * fabs(convert_float3(face_mask.xyz)); + voxel.xyz += voxel_step.xyz * face_mask.xyz; + + // If the ray went out of bounds + int3 overshoot = voxel <= *map_dim; + int3 undershoot = voxel > 0; + + if (overshoot.x == 0 || overshoot.y == 0 || overshoot.z == 0 || undershoot.x == 0 || undershoot.y == 0) { + return false; + } + if (undershoot.z == 0) { + return false; + } + + + + dist++; + + } while (dist < 700); + + return false; +} float4 view_light(float4 in_color, float3 light, float3 view, int3 mask) { float diffuse = max(dot(normalize(convert_float3(mask)), normalize(light)), 0.0f); + in_color += diffuse * 0.5; + if (dot(light, normalize(convert_float3(mask))) > 0.0) { float3 halfwayVector = normalize(normalize(light) + normalize(view)); float specTmp = max(dot(normalize(convert_float3(mask)), halfwayVector), 0.0f); - return in_color + pow(specTmp, 1.0f) * 0.01 +diffuse * 0.5; + in_color += pow(specTmp, 1.0f) * 0.01; } //float3 halfwayDir = normalize(normalize(view) + normalize(light)); @@ -31,9 +114,7 @@ float4 view_light(float4 in_color, float3 light, float3 view, int3 mask) { } -void cast_ray(float3 ray_origin, float3 ray_direction) { -} @@ -154,7 +235,8 @@ __kernel void raycaster( ray_dir.z ); - // Setup the voxel step based on what direction the ray is pointing + + // Setup the voxel step based on what direction the ray is pointing int3 voxel_step = {1, 1, 1}; voxel_step *= (ray_dir > 0) - (ray_dir < 0); @@ -194,8 +276,9 @@ __kernel void raycaster( float4 fog_color = { 0.73, 0.81, 0.89, 0.8 }; float4 voxel_color = (float4)(0.25, 0.52, 0.30, 0.1); float4 overshoot_color = { 0.25, 0.48, 0.52, 0.8 }; + - // Andrew Woo's raycasting algo + // Andrew Woo's raycasting algo do { // Fancy no branch version of the logic step @@ -221,13 +304,37 @@ __kernel void raycaster( int voxel_data = map[index]; if (voxel_data != 0) { + switch (voxel_data) { case 5: - - //write_imagef(image, pixel, (float4)(0.40, 0.00, 0.40, 0.2)); - write_imagef(image, pixel, view_light(voxel_color, (convert_float3(voxel) + offset) - (float3)(lights[4], lights[5], lights[6]), (convert_float3(voxel) + offset) - (*cam_pos), face_mask)); - //write_imagef(image, pixel, white_light(mix(fog_color, voxel_color, 1.0 - max((dist/700.0f) - 0.3f, (float)0)), (float3)(lights[7], lights[8], lights[9]), face_mask)); + + // write_imagef(image, pixel, (float4)(0.90, 0.00, 0.40, 0.9)); + + if (!cast_light_intersection_ray( + map, + map_dim, + (float3)(lights[4], lights[5], lights[6]) - (convert_float3(voxel) + offset), + (convert_float3(voxel) + offset + convert_float3(face_mask)/10.0f), + lights, + light_count + )) { + + write_imagef(image, pixel, (float4)(0.90, 0.00, 0.40, 0.9)); + return; + } + + write_imagef( + image, + pixel, + view_light( + voxel_color, + (convert_float3(voxel) + offset) - (float3)(lights[4], lights[5], lights[6]), + (convert_float3(voxel) + offset) - (*cam_pos), + face_mask * voxel_step + ) + ); + return; float3 vox = convert_float3(voxel); @@ -250,7 +357,7 @@ __kernel void raycaster( case 6: - write_imagef(image, pixel, view_light((float4)(0.0, 0.239, 0.419, 0.3), (convert_float3(voxel) + offset) - (float3)(lights[4], lights[5], lights[6]), (convert_float3(voxel) + offset) - (*cam_pos), face_mask)); + write_imagef(image, pixel, view_light((float4)(0.0, 0.239, 0.419, 0.3), (convert_float3(voxel) + offset) - (float3)(lights[4], lights[5], lights[6]), (convert_float3(voxel) + offset) - (*cam_pos), face_mask * voxel_step)); //write_imagef(image, pixel, white_light(mix((float4)(0.73, 0.81, 0.89, 0.6), (float4)(0.0, 0.239, 0.419, 0.3), 1.0 - max((dist / 700.0f) - 0.3f, (float)0)), (float3)(lights[7], lights[8], lights[9]), face_mask)); return; diff --git a/src/main.cpp b/src/main.cpp index 655b46d..4e60361 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -115,8 +115,8 @@ int main() { // Light for the currently non functional Bling Phong shader Light l; - l.direction_cartesian = sf::Vector3f(+1.5f, -1.2f, -0.5f); - l.position = sf::Vector3f(100.0f, 100.0f, 100.0f); + l.direction_cartesian = sf::Vector3f(-0.2f, -0.2f, -1.5f); + l.position = sf::Vector3f(100.0f, 100.0f, 500.0f); l.rgbi = sf::Vector4f(0.3f, 0.4f, 0.3f, 1.0f); std::vector light_vec;