diff --git a/README.md b/README.md index 2e90e0e..ba1285a 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,5 @@ Efficient Sparse Voxel Octrees, Laine et al. A fast voxel traversal algorithm for ray tracing, Woo et al. -![alt tag](https://github.com/MitchellHansen/voxel-raycaster/blob/master/assets/video.gif) - +![alt tag](https://github.com/MitchellHansen/voxel-raycaster/blob/master/assets/screenshot1.PNG) ![alt tag](https://github.com/MitchellHansen/voxel-raycaster/blob/master/assets/screenshot.PNG) diff --git a/assets/screenshot1.png b/assets/screenshot1.png new file mode 100644 index 0000000..6150dd1 Binary files /dev/null and b/assets/screenshot1.png differ diff --git a/assets/video.gif b/assets/video.gif deleted file mode 100644 index 305a74a..0000000 Binary files a/assets/video.gif and /dev/null differ diff --git a/include/util.hpp b/include/util.hpp index 5865d33..b8d1bbc 100644 --- a/include/util.hpp +++ b/include/util.hpp @@ -13,15 +13,6 @@ const double PI = 3.141592653589793238463; const float PI_F = 3.14159265358979f; -struct Light { - sf::Vector4f rgbi; - - // I believe that Vector3's get padded to Vector4's. Give them a non-garbage value - sf::Vector3f position; - - sf::Vector3f direction_cartesian; -}; - struct fps_counter { public: fps_counter(){ @@ -273,4 +264,27 @@ inline std::vector sfml_get_float_input(sf::RenderWindow *window) { return ret; -} \ No newline at end of file +} + +struct Light { + sf::Vector4f rgbi; + + // I believe that Vector3's get padded to Vector4's. Give them a non-garbage value + sf::Vector3f position; + + sf::Vector3f direction_cartesian; + + void look_at_center() { + direction_cartesian = SphereToCart(CartToNormalizedSphere(sf::Vector3f(256, 256, 256) - position)); + }; + + void orbit_around_center(double time) { + position = sf::Vector3f( + position.x * cos(time/1000) - position.y * sin(time/1000), + position.x * sin(time/1000) + position.y * cos(time/1000), + position.z + ); + + look_at_center(); + }; +}; \ No newline at end of file diff --git a/kernels/ray_caster_kernel.cl b/kernels/ray_caster_kernel.cl index e09edd4..86df0dd 100644 --- a/kernels/ray_caster_kernel.cl +++ b/kernels/ray_caster_kernel.cl @@ -76,8 +76,8 @@ bool cast_light_intersection_ray( voxel.xyz += voxel_step.xyz * face_mask.xyz; // If the ray went out of bounds - int3 overshoot = voxel <= *map_dim; - int3 undershoot = voxel > 0; + 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; @@ -95,6 +95,9 @@ 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); @@ -276,6 +279,7 @@ __kernel void raycaster( float4 fog_color = { 0.73, 0.81, 0.89, 0.8 }; float4 voxel_color = (float4)(0.50, 0.0, 0.50, 0.1); float4 overshoot_color = { 0.25, 0.48, 0.52, 0.8 }; + float4 overshoot_color_2 = { 0.25, 0.1, 0.52, 0.8 }; // Andrew Woo's raycasting algo @@ -287,15 +291,15 @@ __kernel void raycaster( voxel.xyz += voxel_step.xyz * face_mask.xyz; // If the ray went out of bounds - int3 overshoot = voxel <= *map_dim; - int3 undershoot = voxel > 0; + 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){ write_imagef(image, pixel, white_light(mix(fog_color, overshoot_color, 1.0 - max(dist / 700.0f, (float)0)), (float3)(lights[7], lights[8], lights[9]), face_mask)); return; } if (undershoot.z == 0) { - write_imagef(image, pixel, white_light(mix(fog_color, overshoot_color, 1.0 - max(dist / 700.0f, (float)0)), (float3)(lights[7], lights[8], lights[9]), face_mask)); + write_imagef(image, pixel, white_light(mix(fog_color, overshoot_color_2, 1.0 - max(dist / 700.0f, (float)0)), (float3)(lights[7], lights[8], lights[9]), face_mask)); return; } @@ -313,29 +317,41 @@ __kernel void raycaster( else if (voxel_data == 5) { voxel_color = (float4)(0.25, 0.52, 0.30, 0.1); } + else if (voxel_data == 1) { + voxel_color = (float4)(0.929, 0.957, 0.027, 0.7); + } + + // set to which face + float3 face_position = convert_float3(face_mask * voxel_step); + // 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)(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)), - lights, + (convert_float3(voxel) - convert_float3(face_mask * voxel_step)),//face_position),// + lights, light_count - )) { + )) { write_imagef(image, pixel, voxel_color); //write_imagef(image, pixel, voxel_color); return; } + // 0 1 2 3 4 5 6 7 8 9 + // {r, g, b, i, x, y, z, x', y', z'} + 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), + (convert_float3(voxel) ) - (float3)(lights[4], lights[5], lights[6]), + (convert_float3(voxel) ) - (*cam_pos), face_mask * voxel_step ) ); diff --git a/src/Camera.cpp b/src/Camera.cpp index f90a1c5..9de7db2 100644 --- a/src/Camera.cpp +++ b/src/Camera.cpp @@ -93,11 +93,13 @@ void Camera::recieve_event(VrEventPublisher* publisher, std::unique_ptr(event.get()); - default_impulse = 1.0f; - if (held_event->code == sf::Keyboard::LShift) { default_impulse = 0.2f; } + if (held_event->code == sf::Keyboard::RShift) { + default_impulse = 1.0f; + } + else if (held_event->code == sf::Keyboard::C) { look_at_center(); } diff --git a/src/Old_Map.cpp b/src/Old_Map.cpp index b19d52d..668b149 100644 --- a/src/Old_Map.cpp +++ b/src/Old_Map.cpp @@ -26,7 +26,8 @@ void Old_Map::generate_terrain() { voxel_data[i] = 0; } - set_voxel(sf::Vector3i(75, 75, 75), 5); + //set_voxel(sf::Vector3i(63, 63, 63), 1); + for (int i = 0; i < dimensions.x * dimensions.y; i++) { height_map[i] = 0; @@ -37,7 +38,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() % 30 + 55; + double SEED = rand() % 5 + 10; //seed the data set_sample(0, 0, SEED); @@ -45,7 +46,7 @@ void Old_Map::generate_terrain() { set_sample(dimensions.x, 0, SEED); set_sample(dimensions.x, dimensions.y, SEED); - double h = 30.0;//the range (-h -> +h) for the average offset + double h = 5.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 @@ -138,6 +139,16 @@ 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++) { + + voxel_data[x + dimensions.x * (y + dimensions.z * z)] = 6; + } + } + } + + for (int x = 0; x < dimensions.x; x++) { for (int y = 0; y < dimensions.y; y++) { // for (int z = 0; z < dimensions.z; z++) { diff --git a/src/main.cpp b/src/main.cpp index 904ee26..60704e1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,9 +40,9 @@ const int WINDOW_X = 1000; const int WINDOW_Y = 1000; const int WORK_SIZE = WINDOW_X * WINDOW_Y; -const int MAP_X = 512; -const int MAP_Y = 512; -const int MAP_Z = 512; +const int MAP_X = 128; +const int MAP_Y = 128; +const int MAP_Z = 128; float elap_time(){ static std::chrono::time_point start; @@ -115,8 +115,8 @@ int main() { // Light for the currently non functional Bling Phong shader Light l; - l.direction_cartesian = sf::Vector3f(-0.2f, -0.2f, -1.5f); - l.position = sf::Vector3f(100.0f, 500.0f, 100.0f); + l.direction_cartesian = sf::Vector3f(-1.0f, -1.0f, -1.5f); + l.position = sf::Vector3f(256.0f, 256.0f, 256.0f); l.rgbi = sf::Vector4f(0.3f, 0.4f, 0.3f, 1.0f); std::vector light_vec; @@ -157,6 +157,8 @@ int main() { bool reset = false; + double timer_accumulator = 0.0; + Input input_handler; camera->subscribe_to_publisher(&input_handler, vr::Event::EventType::KeyHeld); @@ -182,6 +184,19 @@ int main() { if (sf::Keyboard::isKeyPressed(sf::Keyboard::L)) { light_vec.at(0).position = camera->get_position(); } + if (sf::Keyboard::isKeyPressed(sf::Keyboard::N)) { + light_vec.at(0).orbit_around_center(timer_accumulator += delta_time); + } + + if (sf::Keyboard::isKeyPressed(sf::Keyboard::N)) { + std::string path = "../assets/"; + std::string filename; + std::getline(std::cin, filename); + filename += ".png"; + + sf::Image image = window.capture(); + image.saveToFile(path + filename); + } // Time keeping elapsed_time = elap_time(); @@ -196,6 +211,8 @@ int main() { // ==== DELTA TIME LOCKED ==== } + + // ==== FPS LOCKED ==== camera->update(delta_time);