From 8806777dc97c5292684d9b91159153ea17159709 Mon Sep 17 00:00:00 2001 From: MitchellHansen Date: Thu, 13 Apr 2017 03:41:05 -0700 Subject: [PATCH] Lots of tweaking. Tenative buggy reflection implimented. --- include/Camera.h | 2 + include/LightController.h | 5 ++ include/raycaster/Hardware_Caster.h | 1 + kernels/ray_caster_kernel.cl | 107 ++++++++++++++++++++++------ src/Camera.cpp | 8 +++ src/main.cpp | 50 +++++++------ src/map/Old_Map.cpp | 15 ++-- src/raycaster/Hardware_Caster.cpp | 2 +- 8 files changed, 140 insertions(+), 50 deletions(-) diff --git a/include/Camera.h b/include/Camera.h index cb84706..2d8d3d7 100644 --- a/include/Camera.h +++ b/include/Camera.h @@ -34,6 +34,8 @@ public: sf::Vector3f get_position(); sf::Vector2f get_direction(); + void setSpeed(float speed); + float getSpeed(); void recieve_event(VrEventPublisher* p, std::unique_ptr event) override; diff --git a/include/LightController.h b/include/LightController.h index 81f8124..7e14f0f 100644 --- a/include/LightController.h +++ b/include/LightController.h @@ -8,6 +8,11 @@ #include "raycaster/Hardware_Caster.h" #include "LightHandle.h" + +// Lighting is a bit tricky as we need to + + + struct LightPrototype { LightPrototype( diff --git a/include/raycaster/Hardware_Caster.h b/include/raycaster/Hardware_Caster.h index fad7449..5934426 100644 --- a/include/raycaster/Hardware_Caster.h +++ b/include/raycaster/Hardware_Caster.h @@ -8,6 +8,7 @@ #include "LightController.h" #include "map/Old_Map.h" #include "Camera.h" +#include #ifdef linux #include diff --git a/kernels/ray_caster_kernel.cl b/kernels/ray_caster_kernel.cl index 30800c8..a21ae57 100644 --- a/kernels/ray_caster_kernel.cl +++ b/kernels/ray_caster_kernel.cl @@ -1,10 +1,12 @@ float DistanceBetweenPoints(float3 a, float3 b) { - return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2) + pow(a.z - b.z, 2)); + return fast_distance(a, b); + //return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2) + pow(a.z - b.z, 2)); } float Distance(float3 a) { - return sqrt(pow(a.x, 2) + pow(a.y, 2) + pow(a.z, 2)); + return fast_length(a); + //return sqrt(pow(a.x, 2) + pow(a.y, 2) + pow(a.z, 2)); } // Naive incident ray light @@ -17,6 +19,8 @@ float4 white_light(float4 input, float3 light, int3 mask) { ) ) / 32; + input.w += 0.25f; + return input; } @@ -43,6 +47,10 @@ float4 view_light(float4 in_color, float3 light, float4 light_color, float3 view in_color += pow(specTmp, 8.0f) * light_color * 0.5f / d; } + if (in_color.w > 1.0){ + in_color.xyz *= in_color.w; + } + return in_color; } @@ -99,6 +107,8 @@ bool cast_light_intersection_ray( int3 face_mask = { 0, 0, 0 }; + int length_cutoff = 0; + // Andrew Woo's raycasting algo do { @@ -123,6 +133,9 @@ bool cast_light_intersection_ray( if (voxel_data != 0) return true; + if (length_cutoff > 300) + return false; + //} while (any(isless(intersection_t, (float3)(distance_to_light - 1)))); } while (intersection_t.x < distance_to_light - 1 || intersection_t.y < distance_to_light - 1 || @@ -248,6 +261,8 @@ __kernel void raycaster( // If we hit a voxel int index = voxel.x + (*map_dim).x * (voxel.y + (*map_dim).z * (voxel.z)); int voxel_data = map[index]; + + // Debug, add the light position if (all(voxel == convert_int3((float3)(lights[4], lights[5], lights[6]-3)))) voxel_data = 1; @@ -257,72 +272,114 @@ __kernel void raycaster( float3 face_position = (float)(0); float2 tile_face_position = (float)(0); - + float3 sign = (float3)(1.0f, 1.0f, 1.0f); // First determine the percent of the way the ray is towards the next intersection_t // in relation to the xyz position on the plane if (face_mask.x == -1) { + sign.x *= -1.0; float z_percent = (intersection_t.z - (intersection_t.x - delta_t.x)) / delta_t.z; float y_percent = (intersection_t.y - (intersection_t.x - delta_t.x)) / delta_t.y; // Since we intersected face x, we know that we are at the face (1.0) - // Not entirely sure what is causing the 1.0 vs 1.001 rendering bug - face_position = (float3)(1.001f, y_percent, z_percent); + // I think the 1.001f rendering bug is the ray thinking it's within the voxel + // even though it's sitting on the very edge + face_position = (float3)(1.0001f, y_percent, z_percent); tile_face_position = (float2)(y_percent, z_percent); } else if (face_mask.y == -1) { + sign.y *= -1.0; float x_percent = (intersection_t.x - (intersection_t.y - delta_t.y)) / delta_t.x; float z_percent = (intersection_t.z - (intersection_t.y - delta_t.y)) / delta_t.z; - face_position = (float3)(x_percent, 1.001f, z_percent); + face_position = (float3)(x_percent, 1.0001f, z_percent); tile_face_position = (float2)(x_percent, z_percent); } else if (face_mask.z == -1) { + //sign.z *= -1.0; float x_percent = (intersection_t.x - (intersection_t.z - delta_t.z)) / delta_t.x; float y_percent = (intersection_t.y - (intersection_t.z - delta_t.z)) / delta_t.y; - face_position = (float3)(x_percent, y_percent, 1.001f); + face_position = (float3)(x_percent, y_percent, 1.0001f); tile_face_position = (float2)(x_percent, y_percent); } - // We now need to account for the ray wanting to skip the axis in which - // it flips its sign - // TODO: improve this + + // Because the raycasting process is agnostic to the quadrant + // it's working in, we need to transpose the sign over to the face positions. + // If we don't it will think that it is always working in the (1, 1, 1) quadrant + // and will just "copy" the quadrant. This includes shadows as they use the face_position + // in order to cast the intersection ray!! + + if (ray_dir.x > 0) { - face_position.x = -face_position.x + 1; + face_position.x = -face_position.x + 1.0; + //face_position.x = -face_position.x + 1; //tile_face_position.x = -tile_face_position.x + 1.0; } if (ray_dir.x < 0) { //face_position.x = face_position.x + 0; - //tile_face_position.x = tile_face_position.x; + + + // This cures the Z semmetry on the X axis + tile_face_position.x = -tile_face_position.x + 1.0; } if (ray_dir.y > 0){ + face_position.y = - face_position.y + 1; //tile_face_position.y = -tile_face_position.y + 1.0; } if (ray_dir.y < 0) { + //face_position.y = face_position.y + 0; - //tile_face_position.y = -tile_face_position.y + 1.0; + + // This cures the Y semmetry on the Z tile faces + tile_face_position.x = 1.0 - tile_face_position.x; + + // We run into the Hairy ball problem, so we need to define + // a special case for the zmask + if (face_mask.z == -1) { + tile_face_position.x = 1.0 - tile_face_position.x; + tile_face_position.y = 1.0 - tile_face_position.y; + } } if (ray_dir.z > 0) { - face_position.z = - face_position.z + 1; + + face_position.z = - face_position.z + 1; //tile_face_position.y = tile_face_position.y + 0.0; } if (ray_dir.z < 0) { + //sign.z *= -1.0; + // face_position.z = - face_position.z + 1; //face_position.z = face_position.z + 0; + tile_face_position.y = -tile_face_position.y + 1.0; } - + if (voxel_data == 6){ + // intersection_t = (1, 1, 1) - intersection_t; + //intersection_t += delta_t * -convert_float3(isless(intersection_t, 0)); + float3 ray_pos = (convert_float3(voxel) + face_position); + ray_dir *= sign; + delta_t = fabs(1.0f / ray_dir); + float3 offset = ((ray_pos)-floor(ray_pos)) * convert_float3(voxel_step); + intersection_t = delta_t * offset; + + // for negative values, wrap around the delta_t + intersection_t += delta_t * -convert_float3(isless(intersection_t, 0)); + voxel_step = (1, 1, 1);//convert_int3(sign); + voxel_step *= (ray_dir > 0) - (ray_dir < 0); + continue; + } // Now either use the face position to retrieve a texture sample, or // just a plain color for the voxel color @@ -331,17 +388,23 @@ __kernel void raycaster( } else if (voxel_data == 5) { float2 tile_size = convert_float2(*atlas_dim / *tile_dim); - voxel_color = read_imagef(texture_atlas, convert_int2(tile_face_position * tile_size) + convert_int2((float2)(3, 0) * tile_size)); + voxel_color = read_imagef( + texture_atlas, + convert_int2(tile_face_position * tile_size) + + convert_int2((float2)(3, 0) * tile_size) + ); + voxel_color.w = 0.0f; //voxel_color = (float4)(0.25, 0.52, 0.30, 0.1); } else if (voxel_data == 1) { voxel_color = (float4)(0.929f, 0.957f, 0.027f, 0.0f); } - //else { - // voxel_color = (float4)(1.0f, 0.0f, 0.0f, 0.0f); - //} - // + else { + voxel_color = (float4)(1.0f, 0.0f, 0.0f, 0.0f); + } + + if (cast_light_intersection_ray( map, @@ -353,7 +416,7 @@ __kernel void raycaster( )) { // If the light ray intersected an object on the way to the light point - float4 ambient_color = white_light(voxel_color, (float3)(256.0f, 256.0f, 256.0f), face_mask); + float4 ambient_color = white_light(voxel_color, (float3)(1.0f, 1.0f, 1.0f), face_mask); write_imagef(image, pixel, ambient_color); return; } @@ -380,7 +443,7 @@ __kernel void raycaster( dist++; - } while (dist / 700.0f < 1); + } while (dist < 700.0f); write_imagef(image, pixel, white_light(mix(fog_color, (float4)(0.40, 0.00, 0.40, 0.2), 1.0 - max(dist / 700.0f, (float)0)), (float3)(lights[7], lights[8], lights[9]), face_mask)); diff --git a/src/Camera.cpp b/src/Camera.cpp index 4bc4e11..20e08aa 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -201,3 +201,11 @@ sf::Vector3f Camera::get_position() { sf::Vector2f Camera::get_direction() { return direction; } + +void Camera::setSpeed(float speed) { + default_impulse = speed;; +} + +float Camera::getSpeed() { + return default_impulse; +} diff --git a/src/main.cpp b/src/main.cpp index 1f75c6f..2ee18b3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -74,6 +74,8 @@ sf::Texture window_texture; // - Diffuse fog hard cut off // - Infinite light distance, no inverse square // - Inconsistent lighting constants. GUI manipulation +// - Far pointers, attachment lookup and aux buffer, contour lookup & masking + int main() { @@ -87,10 +89,6 @@ int main() { // Do nothing, extension wrangling handled by macOS #endif - // The socket listener for interacting with the TCP streaming android controller - // NetworkInput ni; - // ni.listen_for_clients(5000); - // ni.stop_listening_for_clients(); // ============================= Map _map(32); @@ -184,13 +182,16 @@ int main() { float light_pos[4] = { 100, 100, 30 }; char screenshot_buf[128]{0}; + bool paused = false; + float camera_speed = 1.0; + while (window.isOpen()) { input_handler.consume_sf_events(&window); input_handler.handle_held_keys(); input_handler.dispatch_events(); - // Time keeping + // Time keeping elapsed_time = elap_time(); delta_time = elapsed_time - current_time; current_time = elapsed_time; @@ -198,21 +199,26 @@ int main() { delta_time = 0.2f; accumulator_time += delta_time; while ((accumulator_time - step_size) >= step_size) { - accumulator_time -= step_size; + accumulator_time -= step_size; - // ==== DELTA TIME LOCKED ==== - } + // ==== DELTA TIME LOCKED ==== + } // ==== FPS LOCKED ==== + + window.clear(sf::Color::Black); ImGui::SFML::Update(window, sf_delta_clock.restart()); - camera->update(delta_time); - handle->update(delta_time); - // Run the raycast - raycaster->compute(); + if (!paused) { + camera->update(delta_time); + handle->update(delta_time); + + // Run the raycast + raycaster->compute(); + + } - window.clear(sf::Color::Black); raycaster->draw(&window); // Give the frame counter the frame time and draw the average frame time @@ -274,6 +280,10 @@ int main() { if (ImGui::Button("Recompile kernel")) { while (raycaster->debug_quick_recompile() != 0); } + if (ImGui::Button("Pause")) { + paused = !paused; + } + ImGui::End(); ImGui::Begin("Lights"); @@ -283,16 +293,15 @@ int main() { handle->set_rgbi(light); } + if (ImGui::SliderFloat("Camera Speed", &camera_speed, 0, 4)) { + camera->setSpeed(camera_speed); + } + if (ImGui::SliderFloat3("Position", light_pos, 0, MAP_X)) { sf::Vector3f light(light_pos[0], light_pos[1], light_pos[2]); handle->set_position(light); } - // Menu - - - - if (ImGui::CollapsingHeader("Window options")) { if (ImGui::TreeNode("Style")) @@ -301,11 +310,6 @@ int main() { ImGui::TreePop(); } } - //light_pos[0] = static_cast(sin(elapsed_time) * 100.0f + 300.0f); - //light_pos[1] = static_cast(sin(elapsed_time) * 100.0f + 300.0f); - - //sf::Vector3f light(light_pos[0], light_pos[1], light_pos[2]); - //handle->set_position(light); ImGui::End(); diff --git a/src/map/Old_Map.cpp b/src/map/Old_Map.cpp index 105ea02..0c65876 100644 --- a/src/map/Old_Map.cpp +++ b/src/map/Old_Map.cpp @@ -101,7 +101,7 @@ void Old_Map::generate_terrain() { int DATA_SIZE = dimensions.x + 1; //an initial seed value for the corners of the data //srand(f_rand()); - double SEED = rand() % 40 + 40; + double SEED = rand() % 10 + 30; //seed the data set_sample(0, 0, SEED); @@ -109,7 +109,7 @@ void Old_Map::generate_terrain() { set_sample(dimensions.x, 0, SEED); set_sample(dimensions.x, dimensions.y, SEED); - double h = 40.0;//the range (-h -> +h) for the average offset + double h = 20.0;//the range (-h -> +h) for the average offset //for the new value in range of h //side length is distance of a single square side //or distance of diagonal in diamond @@ -188,7 +188,7 @@ void Old_Map::generate_terrain() { for (int y = 100; y < 150; y += 10) { for (int z = 0; z < 10; z += 1) { - voxel_data[x + dimensions.x * (y + dimensions.z * z)] = 5; + voxel_data[x + dimensions.x * (y + dimensions.z * z)] = 6; } } @@ -222,12 +222,19 @@ void Old_Map::generate_terrain() { } } + for (int x = 60; x < 65; x++) { + for (int y = 60; y < 65; y++) { + for (int z = 30; z < 35; z++) { + voxel_data[x + dimensions.x * (y + dimensions.z * z)] = 5; + } + } + } for (int x = 0; x < dimensions.x; x++) { for (int y = 0; y < dimensions.y; y++) { // for (int z = 0; z < dimensions.z; z++) { //if (rand() % 1000 < 1) - voxel_data[x + dimensions.x * (y + dimensions.z * 1)] = 6; + voxel_data[x + dimensions.x * (y + dimensions.z * 1)] = 5; // } } } diff --git a/src/raycaster/Hardware_Caster.cpp b/src/raycaster/Hardware_Caster.cpp index 04c8627..ba2a85b 100644 --- a/src/raycaster/Hardware_Caster.cpp +++ b/src/raycaster/Hardware_Caster.cpp @@ -630,7 +630,7 @@ int Hardware_Caster::compile_kernel(std::string kernel_source, bool is_path, std // Try and build the program // "-cl-finite-math-only -cl-fast-relaxed-math -cl-unsafe-math-optimizations" - error = clBuildProgram(program, 1, &device_id, "-cl-finite-math-only -cl-fast-relaxed-math -cl-unsafe-math-optimizations", NULL, NULL); + error = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL); // Check to see if it errored out if (vr_assert(error, "clBuildProgram")) {