From a812fba43ca57109291c0d9bf4de68f064dd1665 Mon Sep 17 00:00:00 2001 From: MitchellHansen Date: Mon, 16 Jan 2017 20:36:15 -0800 Subject: [PATCH] Trying to get the position on the face where the rays intersect the voxel. Some promising first results. --- kernels/ray_caster_kernel.cl | 251 +++++++++++++++++++++++------------ src/Camera.cpp | 4 +- src/Old_Map.cpp | 6 +- src/main.cpp | 8 +- 4 files changed, 173 insertions(+), 96 deletions(-) diff --git a/kernels/ray_caster_kernel.cl b/kernels/ray_caster_kernel.cl index 86df0dd..13cb6f4 100644 --- a/kernels/ray_caster_kernel.cl +++ b/kernels/ray_caster_kernel.cl @@ -1,5 +1,5 @@ - +// Naive incident ray light float4 white_light(float4 input, float3 light, int3 mask) { input.w = input.w + acos( @@ -13,6 +13,45 @@ float4 white_light(float4 input, float3 light, int3 mask) { } + +// Phong + diffuse lighting function for g + +// 0 1 2 3 4 5 6 7 8 9 +// {r, g, b, i, x, y, z, x', y', z'} + +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); + in_color += pow(specTmp, 1.0f) * 0.1; + } + + //float3 halfwayDir = normalize(normalize(view) + normalize(light)); + //float spec = pow(max(dot(normalize(convert_float3(mask)), halfwayDir), 0.0f), 32.0f); + in_color += 0.02; + return in_color; +} + + +int rand(int* seed) // 1 <= *seed < m +{ + int const a = 16807; //ie 7**5 + int const m = 2147483647; //ie 2**31-1 + + *seed = ((*seed) * a) % m; + return(*seed); +} + + + +// =================================== Boolean ray intersection ============================ +// ========================================================================================= + bool cast_light_intersection_ray( global char* map, global int3* map_dim, @@ -33,9 +72,9 @@ bool cast_light_intersection_ray( // 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); + 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. @@ -62,13 +101,7 @@ bool cast_light_intersection_ray( // 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); @@ -86,7 +119,13 @@ bool cast_light_intersection_ray( return false; } + // 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; + } dist++; @@ -95,105 +134,94 @@ bool cast_light_intersection_ray( return false; } -// 0 1 2 3 4 5 6 7 8 9 -// {r, g, b, i, x, y, z, x', y', z'} - -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; +// =================================== float4 of intersected voxel ============================ +// ============================================================================================ - 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); - in_color += pow(specTmp, 1.0f) * 0.01; - } +float4 cast_color_ray( + global char* map, + global int3* map_dim, + float3 ray_dir, + float3 ray_pos, + global float* lights, + global int* light_count - //float3 halfwayDir = normalize(normalize(view) + normalize(light)); - //float spec = pow(max(dot(normalize(convert_float3(mask)), halfwayDir), 0.0f), 32.0f); - in_color += 0.02; - return in_color; -} + ) { + // 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; + } -// 0 1 2 3 4 5 6 7 8 9 -// {r, g, b, i, x, y, z, x', y', z'} + // Hard cut-off for how far the ray can travel + int max_dist = 800; + int dist = 0; -float4 cast_light_rays( - float3 eye_direction, - float3 ray_origin, - float4 voxel_color, - float3 voxel_normal, - global float* lights, - global int* light_count) { + int3 face_mask = { 0, 0, 0 }; - // set the ray origin to be where the initial ray intersected the voxel - // which side z, and the x and y position + // Andrew Woo's raycasting algo + do { - float ambient_constant = 0.5; - float intensity = 0; + // If we hit a voxel + int index = voxel.x + (*map_dim).x * (voxel.y + (*map_dim).z * (voxel.z)); + int voxel_data = map[index]; - for (int i = 0; i < *light_count; i++) { + if (voxel_data != 0) { + return true; + } - float distance = sqrt( - pow(lights[10 * i + 4] - ray_origin.x, 2) + - pow(lights[10 * i + 5] - ray_origin.y, 2) + - pow(lights[10 * i + 6] - ray_origin.z, 2)); + // 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 (distance > 50) - continue; + // If the ray went out of bounds + int3 overshoot = voxel < *map_dim; + int3 undershoot = voxel >= 0; - float3 light_direction = (lights[10 * i + 7], lights[10 * i + 8], lights[10 * i + 9]); - float c = 10.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; + } - //if (dot(light_direction, voxel_normal) > 0.0) { - float3 halfwayVector = normalize(light_direction + eye_direction); - float dot_prod = dot(voxel_normal, halfwayVector); - float specTmp = max((float)dot_prod, 0.0f); - intensity += pow(specTmp, c); - //} - } - if (get_global_id(0) == 1037760) { - //printf("%f", intensity); - voxel_color = (float4)(1.0, 1.0, 1.0, 1.0); - return voxel_color; - } - voxel_color.w *= intensity; - voxel_color.w += ambient_constant; - - return voxel_color; - - // for every light - // - // check if the light is within falloff distance - // every unit, light halfs - // - // if it is, cast a ray to that light and check for collisions. - // if ray exits voxel volume, assume unobstructed - // - // if ray intersects a voxel, dont influence the voxel color - // - // if it does -} + dist++; -int rand(int* seed) // 1 <= *seed < m -{ - int const a = 16807; //ie 7**5 - int const m = 2147483647; //ie 2**31-1 + } while (dist < 700); - *seed = ((*seed) * a) % m; - return(*seed); + return false; } +// ====================================== Raycaster entry point ===================================== +// ================================================================================================== __kernel void raycaster( global char* map, @@ -256,7 +284,7 @@ __kernel void raycaster( // Intersection T is the collection of the next intersection points // for all 3 axis XYZ. - float3 intersection_t = delta_t * offset; + 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 @@ -324,15 +352,62 @@ __kernel void raycaster( // set to which face float3 face_position = convert_float3(face_mask * voxel_step); + + + if (face_mask.x * voxel_step.x == -1) { + + float z_percent = (intersection_t.x - (intersection_t.z - delta_t.z)) / delta_t.z; + float y_percent = (intersection_t.x - (intersection_t.y - delta_t.y)) / delta_t.y; + + face_position = (float3)(1.0f, y_percent, z_percent); + + if (face_mask.x == 1) + face_position *= -1; + + } + + if (face_mask.y * voxel_step.y == -1) { + + float x_percent = (intersection_t.y - (intersection_t.x - delta_t.x)) / delta_t.x; + float z_percent = (intersection_t.y - (intersection_t.z - delta_t.z)) / delta_t.z; + + face_position = (float3)(x_percent, 1.0f, z_percent); + + if (face_mask.y == 1) + face_position *= -1; + } + + if (face_mask.z * voxel_step.z == -1) { + + float vx = intersection_t.x - delta_t.x; + float vy = intersection_t.y - delta_t.y; + float vz = intersection_t.z - delta_t.z; + + float x_percent = (intersection_t.z - (intersection_t.x - delta_t.x)) / delta_t.x; + float y_percent = (intersection_t.z - (intersection_t.y - delta_t.y)) / delta_t.y; + + face_position = (float3)(x_percent, y_percent, 1.0f); + + if (face_mask.z == 1) + face_position *= -1; + + } + + // set the xy for that face - face_position += convert_float3(face_mask == (int3)(0,0,0)) * ((intersection_t) / delta_t); + //face_position += + // convert_float3(face_mask == (int3)(1,1,1)) + // convert_float3(face_mask == (int3)(0,0,0)) * (intersection_t - delta_t); + + + //face_position += convert_float3(face_mask == (int3)(0,0,0)) * (rand(&seed) % 10) / 50.0; if (cast_light_intersection_ray( map, map_dim, - (float3)(lights[4], lights[5], lights[6]) - (convert_float3(voxel)), - (convert_float3(voxel) - convert_float3(face_mask * voxel_step)),//face_position),// + normalize((float3)(lights[4], lights[5], lights[6]) - (convert_float3(voxel))), + (convert_float3(voxel) + face_position),//convert_float3(face_mask * voxel_step)),//face_position),// lights, light_count )) { diff --git a/src/Camera.cpp b/src/Camera.cpp index 9de7db2..760d7ef 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -126,11 +126,11 @@ void Camera::recieve_event(VrEventPublisher* publisher, std::unique_ptrtype == vr::Event::KeyHeld) { + else if (event->type == vr::Event::KeyPressed) { vr::KeyPressed *key_event = static_cast(event.get()); - if (key_event->code == sf::Keyboard::M) { + if (key_event->code == sf::Keyboard::Y) { if (mouse_enabled) mouse_enabled = false; else diff --git a/src/Old_Map.cpp b/src/Old_Map.cpp index 668b149..3b7f19a 100644 --- a/src/Old_Map.cpp +++ b/src/Old_Map.cpp @@ -139,9 +139,9 @@ void Old_Map::generate_terrain() { } - for (int x = dimensions.x / 2; x < dimensions.x / 2 + dimensions.x / 16; x++) { - for (int y = dimensions.x / 2; y < dimensions.y / 2 + dimensions.x / 16; y++) { - for (int z = 0; z < 20; z++) { + for (int x = dimensions.x / 2; x < dimensions.x / 2 + dimensions.x / 64; x++) { + for (int y = dimensions.x / 2; y < dimensions.y / 2 + dimensions.x / 64; y++) { + for (int z = 0; z < 5; z++) { voxel_data[x + dimensions.x * (y + dimensions.z * z)] = 6; } diff --git a/src/main.cpp b/src/main.cpp index 60704e1..c552d38 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -162,6 +162,7 @@ int main() { Input input_handler; camera->subscribe_to_publisher(&input_handler, vr::Event::EventType::KeyHeld); + camera->subscribe_to_publisher(&input_handler, vr::Event::EventType::KeyPressed); camera->subscribe_to_publisher(&input_handler, vr::Event::EventType::MouseMoved); WindowHandler win_hand(&window); @@ -181,14 +182,15 @@ int main() { if (sf::Keyboard::isKeyPressed(sf::Keyboard::Dash)) { raycaster->test_edit_viewport(WINDOW_X, WINDOW_Y, w -= 5, h -= 5); } - if (sf::Keyboard::isKeyPressed(sf::Keyboard::L)) { + if (sf::Keyboard::isKeyPressed(sf::Keyboard::LAlt)) { light_vec.at(0).position = camera->get_position(); + light_vec.at(0).direction_cartesian = SphereToCart(camera->get_direction()); } - if (sf::Keyboard::isKeyPressed(sf::Keyboard::N)) { + if (sf::Keyboard::isKeyPressed(sf::Keyboard::O)) { light_vec.at(0).orbit_around_center(timer_accumulator += delta_time); } - if (sf::Keyboard::isKeyPressed(sf::Keyboard::N)) { + if (sf::Keyboard::isKeyPressed(sf::Keyboard::M)) { std::string path = "../assets/"; std::string filename; std::getline(std::cin, filename);