diff --git a/Step 3/cmake-build-debug/.ninja_deps b/Step 3/cmake-build-debug/.ninja_deps index ef7e84d..d656f60 100644 Binary files a/Step 3/cmake-build-debug/.ninja_deps and b/Step 3/cmake-build-debug/.ninja_deps differ diff --git a/Step 3/cmake-build-debug/.ninja_log b/Step 3/cmake-build-debug/.ninja_log index ebb24fc..c643062 100644 --- a/Step 3/cmake-build-debug/.ninja_log +++ b/Step 3/cmake-build-debug/.ninja_log @@ -1,62 +1,38 @@ # ninja log v5 -3726 5450 1669143919820663215 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_tables.cpp.o 920916506d18de2c -2065 3173 1669143917540598963 CMakeFiles/Step_3.dir/src/graphics/gl/gl.c.o c243981994ce0811 -2904 4590 1669143918960638977 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_demo.cpp.o dc0c8b425019900b -2 1613 1669143915984555117 CMakeFiles/Step_3.dir/src/engine/mpi.cpp.o a59e814306d7978 -3 3465 1669143917832607191 CMakeFiles/Step_3.dir/src/engine/world.cpp.o 7d8b0912b2dcd105 -3 2904 1669143917272591413 CMakeFiles/Step_3.dir/src/engine/util/debug.cpp.o 41c6f1bdaa5e38f5 -1 4373 1669143918740632779 CMakeFiles/Step_3.dir/src/engine/image/image.cpp.o 74ebce9e3746476 -1614 4368 1669143918736632665 CMakeFiles/Step_3.dir/src/graphics/debug_gui.cpp.o 738602a72b552e04 -3465 4015 1669143918384622746 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_impl_x11.cpp.o 8002180f0368d0ae -1 2477 1669143916848579462 CMakeFiles/Step_3.dir/src/engine/globals.cpp.o 8fd37dd250c0c57b -2 2065 1669143916436567852 CMakeFiles/Step_3.dir/src/engine/math/colliders.cpp.o 49528379fc85b78 -3 2658 1669143917024584425 CMakeFiles/Step_3.dir/src/engine/util/models.cpp.o cb39ce8c856d1d8c -2658 6335 1669143920700688013 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui.cpp.o f512f3e5a828153f -1592 1847 1669144043192138832 Step_3 809bda9fd3dad622 -3174 3483 1669143917852607754 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_impl_glfw.cpp.o 310c2607009eba21 -2 3871 1669143918240618691 CMakeFiles/Step_3.dir/src/engine/raytracing.cpp.o afb5968833aed95e -4015 5091 1669143919460653068 CMakeFiles/Step_3.dir/src/graphics/input.cpp.o 572a0a724d80e2d3 -3016 5493 1669143919860664340 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_draw.cpp.o 8b0c755c9ee468e9 -3871 6494 1669143920864692632 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_widgets.cpp.o fe3a1955d79f977a -2477 5452 1669143919820663215 CMakeFiles/Step_3.dir/src/graphics/graphics.cpp.o 8f22bfe01b4af85f -2106 4455 1669143918824635146 CMakeFiles/Step_3.dir/src/graphics/gl/gl.cpp.o 27ebeccd2f38d7f7 -3484 3726 1669143918096614633 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_impl_opengl3.cpp.o f69d69f5fadcde41 -2429 4641 1669143919012640444 CMakeFiles/Step_3.dir/src/graphics/gl/shader.cpp.o cdbe2fcc55d335a9 -2 3016 1669143917384594567 CMakeFiles/Step_3.dir/src/engine/math/bvh.cpp.o c8d4462e974892bb -2 4046 1669143918412623536 CMakeFiles/Step_3.dir/src/engine/main.cpp.o 9026a4a98b896ce1 -1 1592 1669144042940131734 CMakeFiles/Step_3.dir/src/opencl/cl.cpp.o 45b82f6048f98464 -3 2106 1669143916476568980 CMakeFiles/Step_3.dir/src/engine/util/parser.cpp.o 80ee4e1261cd645e -3 2428 1669143916796577997 CMakeFiles/Step_3.dir/src/engine/util/loaders.cpp.o c81f0f24f2ebce49 -2 1424 1670561165675119419 CMakeFiles/Step_3.dir/src/engine/mpi.cpp.o 5d24537a85ed8416 -3 2110 1670561166359138173 CMakeFiles/Step_3.dir/src/engine/util/parser.cpp.o 98940b44ed977a44 -2 2124 1670561166375138611 CMakeFiles/Step_3.dir/src/engine/math/colliders.cpp.o e1cb3573834144bf -3 2150 1670561166379138721 CMakeFiles/Step_3.dir/src/engine/util/loaders.cpp.o 7aeb3d1871cf6703 -2 2568 1670561166819150786 CMakeFiles/Step_3.dir/src/engine/globals.cpp.o ef21dad2d7d55f95 -3 2626 1670561166875152322 CMakeFiles/Step_3.dir/src/engine/util/debug.cpp.o 6a4e11c94bba7102 -3 2850 1670561167099158461 CMakeFiles/Step_3.dir/src/engine/util/models.cpp.o a3c3944da9146668 -2 3232 1670561167479168881 CMakeFiles/Step_3.dir/src/engine/math/bvh.cpp.o bfaa9112c6c83140 +3039 4673 1670818921470590191 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_tables.cpp.o 98cb1b8b0c737d0d 2111 3258 1670561167507169650 CMakeFiles/Step_3.dir/src/graphics/gl/gl.c.o 1829c9b0491e17e -3 3345 1670561167595172063 CMakeFiles/Step_3.dir/src/engine/world.cpp.o c64baeb5ba601bb4 +2501 4061 1670818920858574640 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_demo.cpp.o 154c013a52483b59 +2 1393 1670818918194506956 CMakeFiles/Step_3.dir/src/engine/mpi.cpp.o 5d24537a85ed8416 +2 2070 1670825558196061243 CMakeFiles/Step_3.dir/src/engine/world.cpp.o c64baeb5ba601bb4 +3 2501 1670818919298535005 CMakeFiles/Step_3.dir/src/engine/util/debug.cpp.o 6a4e11c94bba7102 +2 3755 1670818920550566815 CMakeFiles/Step_3.dir/src/engine/image/image.cpp.o 27aa2206b4129a91 +1393 3888 1670818920686570270 CMakeFiles/Step_3.dir/src/graphics/debug_gui.cpp.o db185e4c05df35c6 +2559 3039 1670818919838548725 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_impl_x11.cpp.o affde06b41e3251b +2 2138 1670825558264063094 CMakeFiles/Step_3.dir/src/opencl/open_ray_tracing.cpp.o 1e13ffe3688667ce +2 2268 1670818919066529111 CMakeFiles/Step_3.dir/src/engine/globals.cpp.o ef21dad2d7d55f95 +2 2027 1670818918826523013 CMakeFiles/Step_3.dir/src/engine/math/colliders.cpp.o e1cb3573834144bf +3 2559 1670818919358536530 CMakeFiles/Step_3.dir/src/engine/util/models.cpp.o a3c3944da9146668 +2268 5802 1670818922598618848 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui.cpp.o 4939d3e79602c127 +1237 1467 1670825715064323231 Step_3 cf178136bfdaf811 3258 3505 1670561167755176449 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_impl_glfw.cpp.o 3708a9542084698e -2 3528 1670561167775176997 CMakeFiles/Step_3.dir/src/engine/raytracing.cpp.o f1ea987e58fdb6e +2 2500 1670825558628073004 CMakeFiles/Step_3.dir/src/engine/raytracing.cpp.o f1ea987e58fdb6e +3285 4389 1670818921190583075 CMakeFiles/Step_3.dir/src/graphics/input.cpp.o 78c22cd6c124c15f +2557 4753 1670818921550592224 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_draw.cpp.o 5fdd1c1c2474d086 +2 2306 1670825558432067666 CMakeFiles/Step_3.dir/src/graphics/graphics.cpp.o 3e9ee255e3b079b6 +3065 5675 1670818922474615699 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_widgets.cpp.o d66bb60c1727d1ac +1623 3745 1670818920542566612 CMakeFiles/Step_3.dir/src/graphics/gl/gl.cpp.o 60ee6de1376d9db2 3505 3710 1670561167959182040 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_impl_opengl3.cpp.o 11f263dd8d9ae8a1 -3345 3864 1670561168115186318 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_impl_x11.cpp.o affde06b41e3251b -2 4074 1670561168319191913 CMakeFiles/Step_3.dir/src/engine/image/image.cpp.o 27aa2206b4129a91 -2 4080 1670561168327192132 CMakeFiles/Step_3.dir/src/engine/main.cpp.o 9aae8e577719f01 -1424 4249 1670561168499196848 CMakeFiles/Step_3.dir/src/graphics/debug_gui.cpp.o db185e4c05df35c6 -2124 4486 1670561168735203318 CMakeFiles/Step_3.dir/src/graphics/gl/gl.cpp.o 60ee6de1376d9db2 -2150 4490 1670561168739203427 CMakeFiles/Step_3.dir/src/graphics/gl/shader.cpp.o 2a1ad2717bf993ad -2850 4510 1670561168759203978 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_demo.cpp.o 154c013a52483b59 -3864 5094 1670561169347220099 CMakeFiles/Step_3.dir/src/graphics/input.cpp.o 78c22cd6c124c15f -2568 5492 1670561169739230847 CMakeFiles/Step_3.dir/src/graphics/graphics.cpp.o 3e9ee255e3b079b6 -3528 5557 1670561169807232711 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_tables.cpp.o 98cb1b8b0c737d0d -3233 5811 1670561170059239620 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_draw.cpp.o 5fdd1c1c2474d086 -4074 6159 1670561170407249163 CMakeFiles/Step_3.dir/src/opencl/cl.cpp.o a2b56fe5c1c9fba8 -4081 6449 1670561170699257167 CMakeFiles/Step_3.dir/src/opencl/open_ray_tracing.cpp.o 1e13ffe3688667ce -2627 6575 1670561170819260459 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui.cpp.o 4939d3e79602c127 -3710 6749 1670561170995265284 CMakeFiles/Step_3.dir/src/graphics/imgui/imgui_widgets.cpp.o d66bb60c1727d1ac -6749 7044 1670561171291273400 Step_3 cf178136bfdaf811 -2 1863 1670561237929087985 CMakeFiles/Step_3.dir/src/opencl/open_ray_tracing.cpp.o 1e13ffe3688667ce -1863 2127 1670561238193095128 Step_3 cf178136bfdaf811 -2 1862 1670561278262179904 CMakeFiles/Step_3.dir/src/opencl/open_ray_tracing.cpp.o 1e13ffe3688667ce -1862 2142 1670561278538187380 Step_3 cf178136bfdaf811 +1975 3990 1670818920790572913 CMakeFiles/Step_3.dir/src/graphics/gl/shader.cpp.o 2a1ad2717bf993ad +2 2557 1670818919354536428 CMakeFiles/Step_3.dir/src/engine/math/bvh.cpp.o bfaa9112c6c83140 +1 2633 1670825558760076597 CMakeFiles/Step_3.dir/src/engine/main.cpp.o 9aae8e577719f01 +3745 5388 1670818922186608382 CMakeFiles/Step_3.dir/src/opencl/cl.cpp.o a2b56fe5c1c9fba8 +3 1623 1670818918422512748 CMakeFiles/Step_3.dir/src/engine/util/parser.cpp.o 98940b44ed977a44 +1 1237 1670825714832316941 CMakeFiles/Step_3.dir/src/engine/util/loaders.cpp.o 7aeb3d1871cf6703 +2 1224 1670825725604609094 CMakeFiles/Step_3.dir/src/engine/util/loaders.cpp.o 7aeb3d1871cf6703 +1224 1432 1670825725812614734 Step_3 cf178136bfdaf811 +1 1288 1670825808594857943 CMakeFiles/Step_3.dir/src/engine/util/loaders.cpp.o 7aeb3d1871cf6703 +1288 1515 1670825808818864011 Step_3 cf178136bfdaf811 +1 1258 1670825836395610588 CMakeFiles/Step_3.dir/src/engine/util/loaders.cpp.o 7aeb3d1871cf6703 +1258 1486 1670825836619616654 Step_3 cf178136bfdaf811 +1 1253 1670825921749919426 CMakeFiles/Step_3.dir/src/engine/util/loaders.cpp.o 7aeb3d1871cf6703 +1253 1464 1670825921957925050 Step_3 cf178136bfdaf811 diff --git a/Step 3/cmake-build-debug/Step_3 b/Step 3/cmake-build-debug/Step_3 index 9868598..ef898b6 100755 Binary files a/Step 3/cmake-build-debug/Step_3 and b/Step 3/cmake-build-debug/Step_3 differ diff --git a/Step 3/cmake-build-debug/Testing/Temporary/LastTest.log b/Step 3/cmake-build-debug/Testing/Temporary/LastTest.log index eada5c4..c18c1d9 100644 --- a/Step 3/cmake-build-debug/Testing/Temporary/LastTest.log +++ b/Step 3/cmake-build-debug/Testing/Temporary/LastTest.log @@ -1,3 +1,3 @@ -Start testing: Dec 09 00:54 EST +Start testing: Dec 12 01:18 EST ---------------------------------------------------------- -End testing: Dec 09 00:54 EST +End testing: Dec 12 01:18 EST diff --git a/Step 3/cmake-build-release-mpi/.ninja_deps b/Step 3/cmake-build-release-mpi/.ninja_deps index f4a4e9e..24abfa9 100644 Binary files a/Step 3/cmake-build-release-mpi/.ninja_deps and b/Step 3/cmake-build-release-mpi/.ninja_deps differ diff --git a/Step 3/cmake-build-release-mpi/.ninja_log b/Step 3/cmake-build-release-mpi/.ninja_log index a2bcef2..c29e1c2 100644 --- a/Step 3/cmake-build-release-mpi/.ninja_log +++ b/Step 3/cmake-build-release-mpi/.ninja_log @@ -13,3 +13,13 @@ 959 2684 1669735767860797367 CMakeFiles/Step_3.dir/src/opencl/cl.cpp.o 7e15a029d7ca916c 2 2038 1669735767212779629 CMakeFiles/Step_3.dir/src/engine/util/parser.cpp.o a8f47b5a2bce1b2a 2 2041 1669735767216779738 CMakeFiles/Step_3.dir/src/engine/util/loaders.cpp.o 971186349d935f91 +1 961 1670775820121593228 CMakeFiles/Step_3.dir/src/engine/globals.cpp.o ac7c6dc8b9dc3fd1 +2 1307 1670775820469601648 CMakeFiles/Step_3.dir/src/engine/math/colliders.cpp.o 8a7658a9bb94b79 +2 1551 1670775820713607554 CMakeFiles/Step_3.dir/src/engine/util/debug.cpp.o aec80b8424e96bfd +2 1789 1670775820949613264 CMakeFiles/Step_3.dir/src/engine/math/bvh.cpp.o 73e310373b3e9e3d +2 1790 1670775820949613264 CMakeFiles/Step_3.dir/src/engine/util/models.cpp.o 781ccf05f86a9476 +3 1867 1670775821029615201 CMakeFiles/Step_3.dir/src/engine/util/parser.cpp.o 49df7154b35ebe07 +3 2034 1670775821197619266 CMakeFiles/Step_3.dir/src/engine/world.cpp.o e08a39ed946f4838 +2 2167 1670775821329622462 CMakeFiles/Step_3.dir/src/engine/util/loaders.cpp.o f94d15a8dacd0fa7 +961 2807 1670775821969637949 CMakeFiles/Step_3.dir/src/opencl/cl.cpp.o c1eccdb992e8345f +2 7810 1670775826969758951 CMakeFiles/Step_3.dir/src/engine/image/image.cpp.o 1ef1b77523471449 diff --git a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/globals.cpp.o b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/globals.cpp.o index bf4054d..b9a47de 100644 Binary files a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/globals.cpp.o and b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/globals.cpp.o differ diff --git a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/image/image.cpp.o b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/image/image.cpp.o index 24f918f..4f06c96 100644 Binary files a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/image/image.cpp.o and b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/image/image.cpp.o differ diff --git a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/math/bvh.cpp.o b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/math/bvh.cpp.o index 56abcf7..a8dbe0d 100644 Binary files a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/math/bvh.cpp.o and b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/math/bvh.cpp.o differ diff --git a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/math/colliders.cpp.o b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/math/colliders.cpp.o index 56aec28..6a2b7f6 100644 Binary files a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/math/colliders.cpp.o and b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/math/colliders.cpp.o differ diff --git a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/debug.cpp.o b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/debug.cpp.o index c52b264..e0bc74e 100644 Binary files a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/debug.cpp.o and b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/debug.cpp.o differ diff --git a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/loaders.cpp.o b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/loaders.cpp.o index 117efed..f17187b 100644 Binary files a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/loaders.cpp.o and b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/loaders.cpp.o differ diff --git a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/models.cpp.o b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/models.cpp.o index 3ce97bc..161af3b 100644 Binary files a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/models.cpp.o and b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/models.cpp.o differ diff --git a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/parser.cpp.o b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/parser.cpp.o index 0ac253f..cefc920 100644 Binary files a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/parser.cpp.o and b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/util/parser.cpp.o differ diff --git a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/world.cpp.o b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/world.cpp.o index 7199f7d..99f865d 100644 Binary files a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/world.cpp.o and b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/engine/world.cpp.o differ diff --git a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/opencl/cl.cpp.o b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/opencl/cl.cpp.o index a09ea8a..f99b0d6 100644 Binary files a/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/opencl/cl.cpp.o and b/Step 3/cmake-build-release-mpi/CMakeFiles/Step_3.dir/src/opencl/cl.cpp.o differ diff --git a/Step 3/cmake-build-release-mpi/Testing/Temporary/LastTest.log b/Step 3/cmake-build-release-mpi/Testing/Temporary/LastTest.log index 0f161b1..b15b5cc 100644 --- a/Step 3/cmake-build-release-mpi/Testing/Temporary/LastTest.log +++ b/Step 3/cmake-build-release-mpi/Testing/Temporary/LastTest.log @@ -1,3 +1,3 @@ -Start testing: Dec 06 14:15 EST +Start testing: Dec 11 11:12 EST ---------------------------------------------------------- -End testing: Dec 06 14:15 EST +End testing: Dec 11 11:12 EST diff --git a/Step 3/include/engine/raytracing.h b/Step 3/include/engine/raytracing.h index 98d52a9..25e2a89 100644 --- a/Step 3/include/engine/raytracing.h +++ b/Step 3/include/engine/raytracing.h @@ -44,8 +44,9 @@ namespace Raytracing { Vec4 up{0, 1, 0}; public: - Camera(PRECISION_TYPE fov, const Image& image): image(image), - aspectRatio(double(image.getWidth()) / double(image.getHeight())) { + Camera(PRECISION_TYPE fov, const Image& image): + image(image), + aspectRatio(double(image.getWidth()) / double(image.getHeight())) { // scale the viewport height based on the camera's FOV tanFovHalf = tan(degreeeToRadian(fov) / 2); viewportHeight = (2.0 * tanFovHalf); @@ -72,8 +73,6 @@ namespace Raytracing { void setPosition(const Vec4& pos) { this->position = pos; } - void setRotation(PRECISION_TYPE yaw, PRECISION_TYPE pitch); - // the follow utility functions are actually taking forever to get right // I can't tell if my projection calculation is off or the view calc? // got to install GLM to test which function works and which does. Maybe they are both bad. or Maybe it's my matrix impl @@ -96,37 +95,6 @@ namespace Raytracing { //return Mat4x4{projectG}; } - [[nodiscard]] Mat4x4 view(const Vec4& lookAtPos) const { - Mat4x4 view; - - auto w = (position - lookAtPos).normalize(); // forward - auto u = (Vec4::cross(up, w)).normalize(); // right - auto v = Vec4::cross(w, u); // up - - view.m00(float(w.x())); - view.m01(float(w.y())); - view.m02(float(w.z())); - view.m03(float(w.w())); - - view.m10(float(u.x())); - view.m11(float(u.y())); - view.m12(float(u.z())); - view.m13(float(u.w())); - - view.m20(float(v.x())); - view.m21(float(v.y())); - view.m22(float(v.z())); - view.m23(float(v.w())); - - // view matrix are inverted, dot product to simulate translate matrix multiplication - view.m30(-float(Vec4::dot(u, position))); - view.m31(-float(Vec4::dot(v, position))); - view.m32(-float(Vec4::dot(w, position))); - view.m33(1); - - return view; - } - Mat4x4 view(PRECISION_TYPE yaw, PRECISION_TYPE pitch); [[nodiscard]] inline Vec4 getPosition() const { return position; }; @@ -205,7 +173,8 @@ namespace Raytracing { // likely due to not over generating unit vectors biased towards the corners } - RayCaster(Camera& c, Image& i, World& world, const Parser& p): camera(c), image(i), world(world) { + RayCaster(Camera& c, Image& i, World& world, const Parser& p): + camera(c), image(i), world(world) { world.generateBVH(); } diff --git a/Step 3/include/engine/util/memory_util.h b/Step 3/include/engine/util/memory_util.h index 158dc3b..9e0f81a 100644 --- a/Step 3/include/engine/util/memory_util.h +++ b/Step 3/include/engine/util/memory_util.h @@ -43,7 +43,8 @@ namespace Raytracing { auto x = getBytes((float) vec.x()); auto y = getBytes((float) vec.y()); auto z = getBytes((float) vec.z()); - auto w = getBytes((float) vec.w()); + // we don't really use the w vector but this is a TODO + //auto w = getBytes((float) vec.w()); // write the bytes as a packed vector. for (auto b: x) array[offset++] = b; @@ -51,8 +52,8 @@ namespace Raytracing { array[offset++] = b; for (auto b: z) array[offset++] = b; - for (auto b: w) - array[offset++] = b; + //for (auto b: w) + // array[offset++] = b; } /** diff --git a/Step 3/include/graphics/graphics.h b/Step 3/include/graphics/graphics.h index abcabb4..9868446 100644 --- a/Step 3/include/graphics/graphics.h +++ b/Step 3/include/graphics/graphics.h @@ -150,8 +150,10 @@ namespace Raytracing { RayCaster& mRaycaster, Parser& mParser, Camera& mCamera) - : m_window(mWindow), m_mainImage(mMainImage), m_imageShader(mImageShader), m_worldShader(mWorldShader), m_raycaster(mRaycaster), - m_parser(mParser), m_camera(mCamera), m_world(world) {} + : + m_window(mWindow), m_mainImage(mMainImage), m_imageShader(mImageShader), m_worldShader(mWorldShader), m_raycaster(mRaycaster), + m_parser(mParser), m_camera(mCamera), m_world(world) {} + std::pair getCameraMatrices(); void draw(); }; } diff --git a/Step 3/include/opencl/open_ray_tracing.h b/Step 3/include/opencl/open_ray_tracing.h index e214c05..f14f06b 100644 --- a/Step 3/include/opencl/open_ray_tracing.h +++ b/Step 3/include/opencl/open_ray_tracing.h @@ -27,6 +27,7 @@ namespace Raytracing { private: CLProgram* program; Image& image; + Camera& camera; size_t localWorks[2]{8, 8}; size_t maxTriangleSize = 0; size_t objectCount = 0; @@ -36,6 +37,7 @@ namespace Raytracing { ~OpenClRaytracer(); void storeObjects(unsigned char* buffer, size_t totalWorldBytes); + void updateCameraInformation(); unsigned char* createObjectBuffer(const std::vector& objects, size_t totalWorldBytes); diff --git a/Step 3/resources/opencl/randoms_git.cl b/Step 3/resources/opencl/randoms_git.cl new file mode 100644 index 0000000..7a0fdb5 --- /dev/null +++ b/Step 3/resources/opencl/randoms_git.cl @@ -0,0 +1,75 @@ +/** +@file +Implements a 64-bit Permutated Congruential generator (PCG-XSH-RR). +M. E. O’Neill, Pcg: A family of simple fast space-efficient statistically good algorithms for random number generation, ACM Transactions on Mathematical Software. +FROM: https://github.com/bstatcomp/RandomCL/blob/master/generators/pcg6432.cl +*/ + +#define RNG32 + +#define PCG6432_FLOAT_MULTI 2.3283064365386963e-10f +#define PCG6432_DOUBLE2_MULTI 2.3283064365386963e-10 +#define PCG6432_DOUBLE_MULTI 5.4210108624275221700372640e-20 + +/** +State of pcg6432 RNG. +*/ +typedef unsigned long pcg6432_state; + +#define PCG6432_XORSHIFTED(s) ((uint)((((s) >> 18u) ^ (s)) >> 27u)) +#define PCG6432_ROT(s) ((s) >> 59u) + +#define pcg6432_macro_uint(state) ( \ + state = state * 6364136223846793005UL + 0xda3e39cb94b95bdbUL, \ + (PCG6432_XORSHIFTED(state) >> PCG6432_ROT(state)) | (PCG6432_XORSHIFTED(state) << ((-PCG6432_ROT(state)) & 31)) \ +) + +/** +Generates a random 32-bit unsigned integer using pcg6432 RNG. +@param state State of the RNG to use. +*/ +#define pcg6432_uint(state) _pcg6432_uint(&state) +unsigned int _pcg6432_uint(pcg6432_state* state){ + ulong oldstate = *state; + *state = oldstate * 6364136223846793005UL + 0xda3e39cb94b95bdbUL; + uint xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u; + uint rot = oldstate >> 59u; + return (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); +} + +/** +Seeds pcg6432 RNG. +@param state Variable, that holds state of the generator to be seeded. +@param seed Value used for seeding. Should be randomly generated for each instance of generator (thread). +*/ +void pcg6432_seed(pcg6432_state* state, unsigned long j){ + *state=j; +} + +/** +Generates a random 64-bit unsigned integer using pcg6432 RNG. +@param state State of the RNG to use. +*/ +#define pcg6432_ulong(state) ((((ulong)pcg6432_uint(state)) << 32) | pcg6432_uint(state)) + +/** +Generates a random float using pcg6432 RNG. +@param state State of the RNG to use. +*/ +#define pcg6432_float(state) (pcg6432_uint(state)*PCG6432_FLOAT_MULTI) + +/** +Generates a random double using pcg6432 RNG. +@param state State of the RNG to use. +*/ +#define pcg6432_double(state) (pcg6432_ulong(state)*PCG6432_DOUBLE_MULTI) + +/** +Generates a random double using pcg6432 RNG. Generated using only 32 random bits. +@param state State of the RNG to use. +*/ +#define pcg6432_double2(state) (pcg6432_uint(state)*PCG6432_DOUBLE2_MULTI) + +/* + END OF SOURCED RANDOM GENERATOR +*/ \ No newline at end of file diff --git a/Step 3/resources/opencl/raytracer.cl b/Step 3/resources/opencl/raytracer.cl index ced3f07..6f02600 100644 --- a/Step 3/resources/opencl/raytracer.cl +++ b/Step 3/resources/opencl/raytracer.cl @@ -37,8 +37,8 @@ struct Ray { float4 inverseDirection; }; -float4 along(struct Ray ray, float length) { - return ray.start + length * ray.direction; +float4 along(struct Ray* ray, float length) { + return ray->start + length * ray->direction; } float magnitude(float4 vec){ @@ -64,7 +64,7 @@ struct ScatterResults { }; // as close to a 1 to 1 copy from the cpu ray tracer -bool checkForTriangleIntersection(struct HitData* data, struct Triangle theTriangle, float4 position, struct Ray ray, float min, float max) { +bool checkForTriangleIntersection(struct HitData* data, struct Triangle theTriangle, float4 position, struct Ray* ray, float min, float max) { const float EPSILON = 0.0000001f; float4 edge1, edge2, s, h, q; @@ -72,7 +72,7 @@ bool checkForTriangleIntersection(struct HitData* data, struct Triangle theTrian edge1 = (theTriangle.vertex2 + position) - (theTriangle.vertex1 + position); edge2 = (theTriangle.vertex3 + position) - (theTriangle.vertex1 + position); - h = cross(ray.direction, edge2); + h = cross(ray->direction, edge2); a = dot(edge1, h); if (a > -EPSILON && a < EPSILON) { @@ -80,7 +80,7 @@ bool checkForTriangleIntersection(struct HitData* data, struct Triangle theTrian } f = 1.0f / a; - s = ray.start - (theTriangle.vertex1 + position); + s = ray->start - (theTriangle.vertex1 + position); u = f * dot(s, h); if (u < 0.0f || u > 1.0f) { @@ -88,7 +88,7 @@ bool checkForTriangleIntersection(struct HitData* data, struct Triangle theTrian } q = cross(s, edge1); - v = f * dot(ray.direction, q); + v = f * dot(ray->direction, q); if (v < 0.0f || u + v > 1.0f) { return false; } @@ -155,19 +155,18 @@ float4 getVector(__global unsigned char* buffer, unsigned long* currentByte){ return val; } -struct Ray projectRay(float x, float y){ +struct Ray* projectRay(struct Ray* ray, float x, float y){ float transformedX = (x / (imageWidth - 1)); float transformedY = (y / (imageHeight - 1)); - struct Ray ray; - ray.start = cameraPosition; - ray.direction = imageOrigin + transformedX * horizontalAxis + transformedY * verticalAxis - cameraPosition; - ray.inverseDirection = 1.0f / ray.direction; + ray->start = cameraPosition; + ray->direction = imageOrigin + transformedX * horizontalAxis + transformedY * verticalAxis - cameraPosition; + ray->inverseDirection = 1.0f / ray->direction; return ray; } -bool checkForWorldIntersection(struct HitData* data, __global struct Object* objects, struct Ray ray, float min, float max){ +bool checkForWorldIntersection(struct HitData* data, __global struct Object* objects, struct Ray* ray, float min, float max){ data->length = max; bool hit = false; // brute-force check on all the objects in the world. @@ -182,7 +181,7 @@ bool checkForWorldIntersection(struct HitData* data, __global struct Object* obj return hit; } -bool scatter(struct ScatterResults* results, __global unsigned char* randoms, struct Ray ray, struct HitData data){ +bool scatter(struct ScatterResults* results, __global unsigned char* randoms, struct Ray* ray, struct HitData data){ const float EPSILON = 0.0000001f; int x = get_global_id(0); unsigned long cb = x * sizeof(float4); @@ -201,8 +200,7 @@ bool scatter(struct ScatterResults* results, __global unsigned char* randoms, st return true; } -float4 raycastI(__global unsigned char* randoms, __global struct Object* objects, struct Ray ray){ - struct Ray localRay = ray; +float4 raycastI(__global unsigned char* randoms, __global struct Object* objects, struct Ray* ray){ float4 color = (float4)(1.0f, 1.0f, 1.0f, 1.0f); for (int i = 0; i < MAX_DEPTH; i++){ struct HitData hit; @@ -236,9 +234,12 @@ __kernel void raycast(__write_only image2d_t outputImage, __global struct Object float4 randomVector = getVector(randoms, &cb); int y = get_global_id(1); + struct Ray casterRay; + projectRay(&casterRay, x + randomVector.x, y + randomVector.z); + float4 color = (float4)(0.0); //for (int i = 0; i < MAX_PER_PIXEL; i++){ - color = color + raycastI(randoms, objects, projectRay(x + randomVector.x, y + randomVector.z)); + color = color + raycastI(randoms, objects, &casterRay); //} float scaleFactor = 1.0 / MAX_PER_PIXEL; write_imagef(outputImage, (int2)(x, y), (float4)(sqrt(color.x * scaleFactor), sqrt(color.y * scaleFactor), sqrt(color.z * scaleFactor), 1.0f)); diff --git a/Step 3/resources/opencl/sphereray.cl b/Step 3/resources/opencl/sphereray.cl index a020f9a..9d8846d 100644 --- a/Step 3/resources/opencl/sphereray.cl +++ b/Step 3/resources/opencl/sphereray.cl @@ -3,78 +3,76 @@ #define objectCount 6 #define imageWidth 800 #define imageHeight 600 -#define imageOrigin (float4)(0,0,0,0) -#define horizontalAxis (float4)(0,0,0,0) -#define verticalAxis (float4)(0,0,0,0) -#define cameraPosition (float4)(0,0,0,0) +/*#define imageOrigin (float3)(0,0,0) +#define horizontalAxis (float3)(0,0,0) +#define verticalAxis (float3)(0,0,0) +#define cameraPosition (float3)(0,0,0) */ -#define MAX_DEPTH 500 -#define MAX_PER_PIXEL 500 +#define MAX_DEPTH 50 +#define MAX_PER_PIXEL 50 #define PI 3.1415926535897 +#include "randoms_git.cl" struct Ray { // the starting point for our ray - float4 start; + float3 start; // and the direction it is currently traveling - float4 direction; - float4 inverseDirection; + float3 direction; + float3 inverseDirection; }; struct HitData { // the hit point on the object - float4 hitPoint; + float3 hitPoint; // the normal of that hit point - float4 normal; + float3 normal; // the length of the vector from its origin in its direction. float length; - // Texture UV Coords. - float u, v; }; -struct ScatterResults { - // returns true to recast the ray with the provided ray - bool scattered; - // the new ray to be cast if scattered - struct Ray newRay; - // the color of the material - float4 attenuationColor; +// required because for some reason OpenCL stores vectors in a really weird byte order?? +// this prevents all of the graphical issues + allows us to assume the order *no platform dependance* +struct Vec { + float x, y, z; }; -float4 along(struct Ray ray, float length) { +float3 randomVector(unsigned long seed){ + return ((float3)(pcg6432_float(seed), pcg6432_float(seed), pcg6432_float(seed)) * 2) - 1; +} + +float3 along(struct Ray ray, float length) { return ray.start + length * ray.direction; } -float lengthSquared(float4 vec){ - return vec.x * vec.x + vec.y * vec.y + vec.z * vec.z + vec.w * vec.w; +float lengthSquared(float3 vec){ + return vec.x * vec.x + vec.y * vec.y + vec.z * vec.z; } -float magnitude(float4 vec){ +float magnitude(float3 vec){ return sqrt(lengthSquared(vec)); } -// // // reads one unsigned long of data from the objects buffer. -float4 getVector(__global unsigned char* buffer, unsigned long* currentByte){ - float4 val = *((global float4*)(buffer)); - *currentByte += sizeof(float4); - return val; -} - -struct Ray projectRay(float x, float y){ +struct Ray projectRay(__global struct Vec* cameraData, float x, float y){ float transformedX = (x / (imageWidth - 1)); float transformedY = (y / (imageHeight - 1)); + float3 cameraPosition = (float3)(cameraData[0].x, cameraData[0].y, cameraData[0].z); + float3 verticalAxis = (float3)(cameraData[1].x, cameraData[1].y, cameraData[1].z); + float3 horizontalAxis = (float3)(cameraData[2].x, cameraData[2].y, cameraData[2].z); + float3 imageOrigin = (float3)(cameraData[3].x, cameraData[3].y, cameraData[3].z); + struct Ray ray; ray.start = cameraPosition; - ray.direction = imageOrigin + transformedX * horizontalAxis + transformedY * verticalAxis - cameraPosition; + ray.direction = (imageOrigin + (transformedX * horizontalAxis) + (transformedY * verticalAxis)) - cameraPosition; ray.inverseDirection = 1.0f / ray.direction; return ray; } -bool checkIfHit(struct HitData* data, struct Ray ray, float4 position, float radius, float min, float max){ +bool checkIfHit(struct HitData* data, struct Ray ray, float3 position, float radius, float min, float max){ float radiusSquared = radius * radius; - float4 rayWRTSphere = ray.start - position; + float3 rayWRTSphere = ray.start - position; // now determine the discriminant for the quadratic formula for the function of line sphere intercept float a = lengthSquared(ray.direction); float b = dot(rayWRTSphere, ray.direction); @@ -101,39 +99,107 @@ bool checkIfHit(struct HitData* data, struct Ray ray, float4 position, float rad } } // the hit point is where the ray is when extended to the root - float4 RayAtRoot = along(ray,root); + float3 RayAtRoot = along(ray,root); // The normal of a sphere is just the point of the hit minus the center position - float4 normal = (RayAtRoot - position) / radius; + float3 normal = (RayAtRoot - position) / radius; - // calculate the uv coords and normalize to [0, 1] - float u = (atan2(-normal.z, normal.x) + PI) / (2 * PI); - float v = acos(normal.y) / PI; // have to invert the v since we have to invert the v again later due to triangles data->hitPoint = RayAtRoot; data->normal = normal; data->length = root; - data->u = u; - data->v = 1.0 - v; return true; } +bool scatter(struct Ray* ray, struct HitData data, int currentDepth){ + const float EPSILON = 0.0000001f; + int x = get_global_id(0); + int y = get_global_id(0); + pcg6432_state state; + unsigned long seed = x * y * currentDepth; + pcg6432_seed(&state, seed); + float3 newRay = data.normal + normalize(randomVector(state)); + // rays that are close to zero are liable to floating point precision errors + if (newRay.x < EPSILON && newRay.y < EPSILON && newRay.z < EPSILON) + newRay = data.normal; -__kernel void raycast(__write_only image2d_t outputImage, __global unsigned char* objects, __global unsigned char* randoms) { + ray->start = data.hitPoint; + ray->direction = newRay; + ray->inverseDirection = 1/ray->direction; + return true; +} + +int checkWorldForIntersection(struct HitData* hit, struct Ray ray){ + const float4 positions[] = { + (float4)(0, 1, -2, 1.0f), + (float4)(0, -100.0f, 0, 100.0f), + (float4)(0, 1, 0, 1.0f), + (float4)(0, 1, 5, 1.0f), + (float4)(10, 5, 5, 1.0f), + + }; + hit->length = 100000000.0f; + int hasHit = 0; + for (int i = 0; i < 5; i++){ + if (checkIfHit( hit, ray, (float3)(positions[i].x, positions[i].y, positions[i].z), positions[i].w, 0.001f, hit->length )){ + hasHit = i+1; + } + } + return hasHit; +} + +float4 raycastI(struct Ray ray){ + const float4 colors[] = { + (float4)(1.0f, 0.0f, 0.0f, 1.0f), + (float4)(0.0f,1.0f,0.0f, 1.0f), + (float4)(0.0f,0.0f,1.0f, 1.0f), + (float4)(0.0f,1.0f,1.0f, 1.0f), + (float4)(1.0f,0.0f,1.0f, 1.0f) + }; + struct Ray localRay = ray; + float4 localColor = (float4)(1.0f); + + int x = get_global_id(0); + int y = get_global_id(1); + + for (int _ = 0; _ < MAX_DEPTH; _++){ + struct HitData hit; + int hitIndex = checkWorldForIntersection(&hit, localRay); + if ( hitIndex ){ + if (scatter(&localRay, hit, _)){ + localColor = localColor * colors[hitIndex-1]; + } else { + localColor = (float4)(0.0,0.0,0.0,0.0); + break; + } + } else { + // since we didn't hit, we hit the sky. + localColor = localColor * (float4)(0.5, 0.7, 1.0, 1.0); + // if we don't hit we cannot keep looping. + break; + } + localColor += localColor; + } + return localColor; +} + +__kernel void raycast(__write_only image2d_t outputImage, __global unsigned char* objects, __global struct Vec* cameraData) { unsigned long currentByte = 0; int x = get_global_id(0); int y = get_global_id(1); float4 color = (float4)(0.0); - - struct HitData hitData1; - if (checkIfHit(&hitData1, projectRay(x, y), (float4)(0.0f, -10, 0.0f, 0.0f), 10, 0, 1000)){ - color = (float4)(hitData1.normal.x, hitData1.normal.y, hitData1.normal.z, 1.0f); + for (int i = 0; i < MAX_PER_PIXEL; i++){ + pcg6432_state state; + unsigned long seed = x * y * i; + pcg6432_seed(&state, seed); + color = color + raycastI(projectRay(cameraData, x + pcg6432_float(state), y + pcg6432_float(state))); } - struct HitData hitData2; - if (checkIfHit(&hitData2, projectRay(x, y), (float4)(0.0f, 0, 0.0f, 0.0f), 1, 0, 1000)){ - color = (float4)(0.0f, 1.0f, 0.0f, 1.0f); - } - - write_imagef(outputImage, (int2)(x, y), (float4)(sqrt(color.x), sqrt(color.y), sqrt(color.z), 1.0f)); + + float scaleFactor = 1.0 / MAX_PER_PIXEL; + write_imagef(outputImage, (int2)(x, y), (float4)(sqrt(color.x * scaleFactor), sqrt(color.y * scaleFactor), sqrt(color.z * scaleFactor), 1.0f)); + //pcg6432_state state; + //unsigned long seed = x * y; + //pcg6432_seed(&state, seed); + //write_imagef(outputImage, (int2)(x, y), (float4)(randomVector(state), 1.0f)); } \ No newline at end of file diff --git a/Step 3/src/engine/main.cpp b/Step 3/src/engine/main.cpp index e06aea8..3645b3d 100644 --- a/Step 3/src/engine/main.cpp +++ b/Step 3/src/engine/main.cpp @@ -206,17 +206,27 @@ int main(int argc, char** args) { #ifdef COMPILE_GUI Raytracing::RayCaster rayCaster{camera, image, world, parser}; Texture mainImage(&image); - - - OpenClRaytracer openClRaytracer{parser.getOptionValue("--resources") + "opencl/raytracer.cl", image, camera, world}; - openClRaytracer.run(); + + #ifdef COMPILE_OPENCL + OpenClRaytracer openClRaytracer{parser.getOptionValue("--resources") + "opencl/sphereray.cl", image, camera, world}; + int frameCounter = 0; + #endif Shader shader("../resources/shaders/basic.vs", "../resources/shaders/basic.fs"); Raytracing::DisplayRenderer renderer{*window, mainImage, world, shader, worldShader, rayCaster, parser, camera}; while (!window->shouldWindowClose()) { window->beginUpdate(); renderer.draw(); + +#ifdef COMPILE_OPENCL + openClRaytracer.updateCameraInformation(); + //frameCounter++; + //if (frameCounter % 5 == 0) { + openClRaytracer.run(); + // frameCounter = 0; + //} +#endif glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); world.drawBVH(worldShader); diff --git a/Step 3/src/engine/raytracing.cpp b/Step 3/src/engine/raytracing.cpp index 76c49a6..cf43e2a 100644 --- a/Step 3/src/engine/raytracing.cpp +++ b/Step 3/src/engine/raytracing.cpp @@ -10,8 +10,10 @@ #include #ifdef USE_MPI + #include #include + #else #ifdef USE_OPENMP #include @@ -41,10 +43,6 @@ namespace Raytracing { imageOrigin = position - horizontalAxis / 2 - verticalAxis / 2 - w; } - void Camera::setRotation(const PRECISION_TYPE yaw, const PRECISION_TYPE pitch) { - // TODO: - } - Mat4x4 Camera::view(PRECISION_TYPE yaw, PRECISION_TYPE pitch) { Mat4x4 view; @@ -204,7 +202,7 @@ namespace Raytracing { setupQueue(partitionScreen(threads)); #ifdef USE_OPENMP ilog << "Running OpenMP\n"; - #pragma omp parallel num_threads(threads+1) default(none) shared(threads) +#pragma omp parallel num_threads(threads+1) default(none) shared(threads) { int threadID = omp_get_thread_num(); // an attempt at making the omp command non-blocking. @@ -248,6 +246,7 @@ namespace Raytracing { } void RayCaster::runMPI(std::queue bounds) { +#ifdef USE_MPI ilog << "Running MPI\n"; dlog << "We have " << bounds.size() << " bounds currently pending!\n"; while (!bounds.empty()) { @@ -259,8 +258,9 @@ namespace Raytracing { } bounds.pop(); } -#ifdef USE_MPI dlog << "Finished running MPI on " << currentProcessID << "\n"; +#else + flog << "Not compiled with MPI!\n"; #endif } diff --git a/Step 3/src/engine/util/loaders.cpp b/Step 3/src/engine/util/loaders.cpp index 27c6c52..72a35f1 100644 --- a/Step 3/src/engine/util/loaders.cpp +++ b/Step 3/src/engine/util/loaders.cpp @@ -52,12 +52,15 @@ namespace Raytracing { throw std::runtime_error(""); } try { - // filter out the > | " at the end of the include statement. - std::string file = statement1.empty() ? statement2[1].substr(0, statement2[1].size() - 1) : statement1[1].substr( - 0, - statement1[1].size() - - 1 - ); + // filter out the > or " at the end of the include statement. + std::string file; + if (statement1.size() <= 1) { + // since " is one character, we don't need to substring since split already handles it. + file = statement2[1]; + } else { + tlog << statement1[1]; + file = statement1[1].substr(0, statement1[1].size() - 1); + } tlog << "Recusing into " << (pathOnly + "/" + file) << "\n"; @@ -105,6 +108,7 @@ namespace Raytracing { stringStream << "\n"; } + //tlog << stringStream.str(); return stringStream.str(); } diff --git a/Step 3/src/graphics/graphics.cpp b/Step 3/src/graphics/graphics.cpp index 8b28e7d..879ef47 100644 --- a/Step 3/src/graphics/graphics.cpp +++ b/Step 3/src/graphics/graphics.cpp @@ -60,410 +60,412 @@ namespace Raytracing { imager.pixels = stbi_load(file.c_str(), &imager.width, &imager.height, &channels, 4); return imager; } - - #ifdef USE_GLFW - XWindow::XWindow(int width, int height): m_displayWidth(width), m_displayHeight(height) { - // OpenGL 4.6 is like 5 years old at this point and most systems support it - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); - // We only generated GLAD headers for GL core profile. Plus renderdoc only support core profile. - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - // Apple stuff. Not like apple supports GL4.6 anyways :/ - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); - glfwWindowHint(GLFW_VISIBLE, GL_TRUE); - glfwWindowHint(GLFW_DECORATED, GL_TRUE); - glfwWindowHint(GLFW_FOCUSED, GL_TRUE); - - glfwSetErrorCallback([](int error_code, const char* description) -> void { - elog << "GLFW Error: " << error_code << "\n\t" << description << "\n"; - }); - - if (!glfwInit()) - throw std::runtime_error("Unable to init GLFW!\n"); - - // create a window using the above settings, - window = glfwCreateWindow(width, height, "GLFW 3P93 Raytracing Project", NULL, NULL); - if (!window) - throw std::runtime_error("Unable to create GLFW window!\n"); - glfwMakeContextCurrent(window); - // enable V-Sync. - glfwSwapInterval(1); - // setup the callbacks we might use. - auto imageData16 = getImageData("../resources/icon/icon16.png"); - auto imageData32 = getImageData("../resources/icon/icon32.png"); - GLFWimage images[2]; - // TODO: delete STBI_resize - images[0] = imageData16; - images[1] = imageData32; - - glfwSetWindowIcon(window, 2, images); - stbi_image_free(imageData16.pixels); - stbi_image_free(imageData32.pixels); - - - glfwSetKeyCallback(window, [](GLFWwindow* _window, int key, int scancode, int action, int mods) -> void { - if (action == GLFW_PRESS) - Input::keyPressed(key); - else if (action == GLFW_RELEASE) - Input::keyReleased(key); - }); - - glfwSetMouseButtonCallback(window, [](GLFWwindow* _window, int button, int action, int mods) -> void { - if (action == GLFW_PRESS) - Input::mousePressed(button); - else if (action == GLFW_RELEASE) - Input::mouseReleased(button); - }); - - glfwSetCursorPosCallback(window, [](GLFWwindow* _window, double x, double y) -> void { - Input::moveMove(x, y); - }); - - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); (void)io; - ImGui::StyleColorsDark(); - - // create ImGUI GLFW instance and install the callbacks - ImGui_ImplGlfw_InitForOpenGL(window, true); - ImGui_ImplOpenGL3_Init("#version 130"); - - int version = gladLoadGL(glfwGetProcAddress); - if(!version) - throw std::runtime_error("Unable to load Glad GL!\n"); - - glfwShowWindow(window); - ilog << "Loaded GL" << GLAD_VERSION_MAJOR(version) << "." << GLAD_VERSION_MINOR(version) << "!\n"; - } - void XWindow::closeWindow() { - if (isCloseRequested) - return; - tlog << "Closing window!\n"; - isCloseRequested = true; - ImGui_ImplOpenGL3_Shutdown(); - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); - - glfwDestroyWindow(window); - glfwTerminate(); - } - void XWindow::beginUpdate() { - // check for window events - isCloseRequested = glfwWindowShouldClose(window); - // reset the current key-pressed state. - Input::state(); - glfwPollEvents(); - // update window settings - glfwGetFramebufferSize(window, &m_displayWidth, &m_displayHeight); - glViewport(0, 0, m_displayWidth, m_displayHeight); - glClearColor(0.5, 0.7, 1.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_DEPTH_TEST); + +#ifdef USE_GLFW + XWindow::XWindow(int width, int height): + m_displayWidth(width), m_displayHeight(height) { + // OpenGL 4.6 is like 5 years old at this point and most systems support it + glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); + glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6); + // We only generated GLAD headers for GL core profile. Plus renderdoc only support core profile. + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + // Apple stuff. Not like apple supports GL4.6 anyways :/ + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + glfwWindowHint(GLFW_VISIBLE, GL_TRUE); + glfwWindowHint(GLFW_DECORATED, GL_TRUE); + glfwWindowHint(GLFW_FOCUSED, GL_TRUE); - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); + glfwSetErrorCallback([](int error_code, const char* description) -> void { + elog << "GLFW Error: " << error_code << "\n\t" << description << "\n"; + }); - ImGui::ShowDemoWindow(nullptr); - } - void XWindow::endUpdate() { - // Render ImGUI - ImGui::Render(); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + if (!glfwInit()) + throw std::runtime_error("Unable to init GLFW!\n"); - glfwSwapBuffers(window); - auto _p1 = std::chrono::high_resolution_clock::now(); - auto _now = std::chrono::duration_cast(_p1.time_since_epoch()).count(); - long currentFrameTime = _now; - delta = double(currentFrameTime - lastFrameTime); - lastFrameTime = currentFrameTime; - frameTimeMs = delta / 1000000.0; - frameTimeS = delta / 1000000000.0; - fps = 1000/frameTimeMs; - } - #else - XWindow::XWindow(int width, int height): m_width(width), m_height(height) { - // open the DEFAULT display. We don't want to open a specific screen as that is annoying. - dlog << "Creating X11 display!\n"; - display = XOpenDisplay(NULL); - if (display == NULL) - throw std::runtime_error("Unable to open an X11 display! Is the X server running?"); - // FBConfigs were added in GLX version 1.3. - if (!glXQueryVersion(display, &glx_major, &glx_minor)) - throw std::runtime_error("Unable to get GLX version!"); - if ((glx_major < 1) || (glx_major == 1 && glx_minor < 3)) - throw std::runtime_error("Invalid GLX Version. At least 1.3 is required!"); - // get the frame buffer config from the X11 window - frameBufferConfig = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &frameBufferCount); - if (!frameBufferConfig) - throw std::runtime_error("Unable to get window framebuffer configs!"); - dlog << "We have " << frameBufferCount << " framebuffers\n"; - // select the best config from available ones. - int bestConfigIndex = 0, bestSamples = -1; - for (int i = 0; i < frameBufferCount; i++) { - XVisualInfo* xVisualInfo = glXGetVisualFromFBConfig(display, frameBufferConfig[i]); - if (xVisualInfo) { - int sampleBuffer, samples; - glXGetFBConfigAttrib(display, frameBufferConfig[i], GLX_SAMPLE_BUFFERS, &sampleBuffer); - glXGetFBConfigAttrib(display, frameBufferConfig[i], GLX_SAMPLES, &samples); - - // if the sample buffer exists, and we have more samples in this config, make this config the one we use. - if (sampleBuffer && samples > bestSamples) { - bestConfigIndex = i; - bestSamples = samples; - } - } - XFree(xVisualInfo); - } - dlog << "We selected config: " << bestConfigIndex << " with " << bestSamples << "# of samples!\n"; - GLXFBConfig bestConfig = frameBufferConfig[bestConfigIndex]; - // we need to make sure we remember to free memory since we are working with c pointers! - XFree(frameBufferConfig); - // as I understand it every window in X11 is a sub-window of the root, or desktop window - // which is why I guess wayland was created, because X11 can't handle a bunch of stuff like VRF (variable refresh rate) - // because your say two monitors are treated as one big window, in effect limiting the refresh rate - // to whatever the lowest is. I still don't like Wayland though. Forced VSync and a fragmented design is annoying. - // plus needless security in a low level lib preventing stuff like discord screen sharing. Annoying as hell. /rant/. - desktop = DefaultRootWindow(display); - // try to open a gl visual context that meets our attributes' requirements - dlog << "Getting visual info!\n"; - visualInfo = glXChooseVisual(display, 0, OpenGLAttributes); - // if our attributes are too much for the display, let's try reducing them. (modern hardware should support 24bit depth though) - if (visualInfo == NULL) { - wlog << "Unable to open a window with a depth of 24. Trying 16 bits.\n"; - OpenGLAttributes[2] = 16; - visualInfo = glXChooseVisual(display, 0, OpenGLAttributes); - if (visualInfo == NULL) { - throw std::runtime_error("Unable to create window's visual context. Is your driver up to date?\n"); - } - } - ilog << visualInfo->visualid << ": With depth: " << visualInfo->depth << " and RGB: " << visualInfo->bits_per_rgb << "\n"; - // use our requirements to create a colormap for the screen. - colormap = XCreateColormap(display, desktop, visualInfo->visual, AllocNone); - // arguments used to open a window for us - xSetWindowAttributes.colormap = colormap; - // what kind of events we want to receive - xSetWindowAttributes.event_mask = - ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | KeyReleaseMask | LeaveWindowMask | - EnterWindowMask | FocusChangeMask | PointerMotionMask; - m_displayWidth = XDisplayWidth(display, 0); - m_displayHeight = XDisplayHeight(display, 0); - window = XCreateWindow(display, - desktop, - // center the display, even if the window manager ignores this. - m_displayWidth / 2 - width / 2, - m_displayHeight / 2 - height / 2, - width, - height, - 0, - visualInfo->depth, - InputOutput, - visualInfo->visual, - CWColormap | CWEventMask, - &xSetWindowAttributes); - // install a error handler - // maybe we should set back the old one but I'd rather it goto std:err than crash the window - XSetErrorHandler([](Display* displayPtr, XErrorEvent* eventPtr) -> int { - elog << "An error occurred while trying to setup X11: " << eventPtr->error_code << ";\n " << eventPtr->minor_code << ";\n " - << eventPtr->request_code << "\n"; - return 0; - }); - - XStoreName(display, window, "3P93 Raytracing Project"); - ImageInput image("../resources/icon/icon.png"); - auto* imageData = image.getImageAsIconBuffer(); - - auto hints = XAllocWMHints(); - hints->flags = IconPixmapHint | StateHint | IconPositionHint; - auto pixMapRob = XCreateBitmapFromData(display, window, (const char*) (icon_bits), 32, 32); - if (!pixMapRob) - flog << "Unable to create icon pixel map\n"; - hints->icon_pixmap = pixMapRob; - hints->initial_state = IconicState; - hints->icon_x = 0; - hints->icon_y = 0; - XSetWMHints(display, window, hints); - XFree(hints); - - int length = 32 * 32 + 2; - //int length = 16 * 16 * 4 + 32*32 * 4 + 4 * 4; - XChangeProperty(display, - window, - XInternAtom(display, "_NET_WM_ICON", False), - XInternAtom(display, "CARDINAL", False), - 32, - PropModeReplace, - (const unsigned char*) imageData, - length); - delete[](imageData); - // there might actually be an argument to be made about X11 being outdated.... - wmDelete = XInternAtom(display, "WM_DELETE_WINDOW", True); - XSetWMProtocols(display, window, &wmDelete, 1); - - // Now show the window - XMapWindow(display, window); - - // get the list of GLX extensions for this system - const char* glExtensions = glXQueryExtensionsString(display, DefaultScreen(display)); - // much in the same way that we get GL function pointers and use them we will do the same with the context creation - auto glXCreateContextAttribsARBPtr = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddressARB((unsigned char*) "glXCreateContextAttribsARB"); - // now we can finally create a OpenGL context for our window - int OpenGLContextAttributes[] = { - // OpenGL major version, we want GL4.5+ - GLX_CONTEXT_MAJOR_VERSION_ARB, 4, - // OpenGL minor version, - GLX_CONTEXT_MINOR_VERSION_ARB, 5, - // I don't remember what this does, but I know GLFW recommends that forward compatability be set true, (Pretty sure it's only an issue - // on MacOS but I've always included this in all my projects so :shrug: - GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, - // Core profile for better Renderdoc compatibility + I don't need non core extensions - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, - None - }; - // now we can actually create and acquire the context - glContext = glXCreateContextAttribsARBPtr(display, bestConfig, 0, True, OpenGLContextAttributes); - // make sure if there was any error we are notified - XSync(display, False); - if (!glContext) - flog << "Unable to create GL context!"; - if (glXIsDirect(display, glContext)) { - ilog << "A direct GL context was acquired!\n"; - } else // direct contexts are faster than indirect! - wlog << "Warning! Indirect context!\n"; - // make the currently executing thread the one current to the OpenGL context - // since OpenGL is a single threaded finite state machine if we want to do mutli-threading with OpenGL (we don't) - // this has to be called in each thread before we make use of any OpenGL function. - glXMakeCurrent(display, window, glContext); - // Now we can issue some OpenGL commands - // we want to respect depth - glEnable(GL_DEPTH_TEST); - - //assignGLFunctionPointers(); - //glEnableVertexArrayAttribPtr = glXGetProcAddress((unsigned char*)("glEnableVertexArrayAttrib")); - - // Setup Dear IMGUI - IMGUI_CHECKVERSION(); - ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); - - ImGui::StyleColorsDark(); - - ImGui_ImplGlfw_Init(); - ImGui_ImplOpenGL3_Init("#version 130"); - - - } - void XWindow::beginUpdate() { - // only try to check events if they are queued - while (XPending(display) > 0) { - XNextEvent(display, &events); + // create a window using the above settings, + window = glfwCreateWindow(width, height, "GLFW 3P93 Raytracing Project", NULL, NULL); + if (!window) + throw std::runtime_error("Unable to create GLFW window!\n"); + glfwMakeContextCurrent(window); + // enable V-Sync. + glfwSwapInterval(1); + // setup the callbacks we might use. + auto imageData16 = getImageData("../resources/icon/icon16.png"); + auto imageData32 = getImageData("../resources/icon/icon32.png"); + GLFWimage images[2]; + // TODO: delete STBI_resize + images[0] = imageData16; + images[1] = imageData32; + + glfwSetWindowIcon(window, 2, images); + stbi_image_free(imageData16.pixels); + stbi_image_free(imageData32.pixels); + + + glfwSetKeyCallback(window, [](GLFWwindow* _window, int key, int scancode, int action, int mods) -> void { + if (action == GLFW_PRESS) + Input::keyPressed(key); + else if (action == GLFW_RELEASE) + Input::keyReleased(key); + }); + + glfwSetMouseButtonCallback(window, [](GLFWwindow* _window, int button, int action, int mods) -> void { + if (action == GLFW_PRESS) + Input::mousePressed(button); + else if (action == GLFW_RELEASE) + Input::mouseReleased(button); + }); + + glfwSetCursorPosCallback(window, [](GLFWwindow* _window, double x, double y) -> void { + Input::moveMove(x, y); + }); + + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + (void) io; + ImGui::StyleColorsDark(); + + // create ImGUI GLFW instance and install the callbacks + ImGui_ImplGlfw_InitForOpenGL(window, true); + ImGui_ImplOpenGL3_Init("#version 130"); + + int version = gladLoadGL(glfwGetProcAddress); + if (!version) + throw std::runtime_error("Unable to load Glad GL!\n"); + + glfwShowWindow(window); + ilog << "Loaded GL" << GLAD_VERSION_MAJOR(version) << "." << GLAD_VERSION_MINOR(version) << "!\n"; + } + void XWindow::closeWindow() { + if (isCloseRequested) + return; + tlog << "Closing window!\n"; + isCloseRequested = true; + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + + glfwDestroyWindow(window); + glfwTerminate(); + } + void XWindow::beginUpdate() { + // check for window events + isCloseRequested = glfwWindowShouldClose(window); + // reset the current key-pressed state. + Input::state(); + glfwPollEvents(); + // update window settings + glfwGetFramebufferSize(window, &m_displayWidth, &m_displayHeight); + glViewport(0, 0, m_displayWidth, m_displayHeight); + glClearColor(0.5, 0.7, 1.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_DEPTH_TEST); + + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + + ImGui::ShowDemoWindow(nullptr); + } + void XWindow::endUpdate() { + // Render ImGUI + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + + glfwSwapBuffers(window); + auto _p1 = std::chrono::high_resolution_clock::now(); + auto _now = std::chrono::duration_cast(_p1.time_since_epoch()).count(); + long currentFrameTime = _now; + delta = double(currentFrameTime - lastFrameTime); + lastFrameTime = currentFrameTime; + frameTimeMs = delta / 1000000.0; + frameTimeS = delta / 1000000000.0; + fps = 1000 / frameTimeMs; + } +#else + XWindow::XWindow(int width, int height): m_width(width), m_height(height) { + // open the DEFAULT display. We don't want to open a specific screen as that is annoying. + dlog << "Creating X11 display!\n"; + display = XOpenDisplay(NULL); + if (display == NULL) + throw std::runtime_error("Unable to open an X11 display! Is the X server running?"); + // FBConfigs were added in GLX version 1.3. + if (!glXQueryVersion(display, &glx_major, &glx_minor)) + throw std::runtime_error("Unable to get GLX version!"); + if ((glx_major < 1) || (glx_major == 1 && glx_minor < 3)) + throw std::runtime_error("Invalid GLX Version. At least 1.3 is required!"); + // get the frame buffer config from the X11 window + frameBufferConfig = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &frameBufferCount); + if (!frameBufferConfig) + throw std::runtime_error("Unable to get window framebuffer configs!"); + dlog << "We have " << frameBufferCount << " framebuffers\n"; + // select the best config from available ones. + int bestConfigIndex = 0, bestSamples = -1; + for (int i = 0; i < frameBufferCount; i++) { + XVisualInfo* xVisualInfo = glXGetVisualFromFBConfig(display, frameBufferConfig[i]); + if (xVisualInfo) { + int sampleBuffer, samples; + glXGetFBConfigAttrib(display, frameBufferConfig[i], GLX_SAMPLE_BUFFERS, &sampleBuffer); + glXGetFBConfigAttrib(display, frameBufferConfig[i], GLX_SAMPLES, &samples); - // one of the few times I'll use a switch statement - switch (events.type) { - // called when the system thinks that the window should be updated - // so on window resize events and of course on actual window update - case Expose: - // update window information - XGetWindowAttributes(display, window, &windowAttributes); - glViewport(0, 0, windowAttributes.width, windowAttributes.height); - this->m_width = windowAttributes.width; - this->m_height = windowAttributes.height; - break; - case KeyPress: { - // translates xkeycodes to ascii keys - KeySym _key = XLookupKeysym(&events.xkey, 0); - ImGui_ImplGlfw_KeyCallback(_key, 0, true, 0); - break; - } - case KeyRelease: { - KeySym _key = XLookupKeysym(&events.xkey, 0); - ImGui_ImplGlfw_KeyCallback(_key, 0, false, 0); - break; - } - case ButtonPress: - if (events.xbutton.button < 4) - ImGui_ImplGlfw_MouseButtonCallback(events.xbutton.button - 1, true, 0); - else { - if (events.xbutton.button == 4) - ImGui_ImplGlfw_ScrollCallback(0, 1); - else if (events.xbutton.button == 5) - ImGui_ImplGlfw_ScrollCallback(0, -1); - else if (events.xbutton.button == 6) - ImGui_ImplGlfw_ScrollCallback(1, 0); - else if (events.xbutton.button == 7) - ImGui_ImplGlfw_ScrollCallback(-1, 0); - } - break; - case ButtonRelease: - if (events.xbutton.button < 4) - ImGui_ImplGlfw_MouseButtonCallback(events.xbutton.button - 1, false, 0); - else { - ImGui_ImplGlfw_ScrollCallback(0, 0); - } - break; - case MotionNotify: - ImGui_ImplGlfw_CursorPosCallback(events.xmotion.x, events.xmotion.y, true); - break; - case EnterNotify: - ImGui_ImplGlfw_CursorEnterCallback(1, true); - break; - case LeaveNotify: - ImGui_ImplGlfw_CursorEnterCallback(0, true); - break; - case FocusIn: - ImGui_ImplGlfw_WindowFocusCallback(1); - break; - case FocusOut: - ImGui_ImplGlfw_WindowFocusCallback(0); - break; - case ClientMessage: - if (events.xclient.data.l[0] == wmDelete) { - closeWindow(); - return; - } - break; + // if the sample buffer exists, and we have more samples in this config, make this config the one we use. + if (sampleBuffer && samples > bestSamples) { + bestConfigIndex = i; + bestSamples = samples; } } - glClearColor(0, 0, 0, 1); - glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplGlfw_NewFrame((double) std::chrono::duration_cast( - std::chrono::high_resolution_clock::now().time_since_epoch()).count(), - m_width, - m_height, - m_width, - m_height); - ImGui::NewFrame(); - - static bool t = true; - if (t) - ImGui::ShowDemoWindow(&t); + XFree(xVisualInfo); } - void XWindow::endUpdate() { - ImGui::Render(); - ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); - ImGui_ImplGlfw_UpdateMouseData(true, true); - - // we use double buffering to prevent screen tearing and other visual disturbances - glXSwapBuffers(display, window); + dlog << "We selected config: " << bestConfigIndex << " with " << bestSamples << "# of samples!\n"; + GLXFBConfig bestConfig = frameBufferConfig[bestConfigIndex]; + // we need to make sure we remember to free memory since we are working with c pointers! + XFree(frameBufferConfig); + // as I understand it every window in X11 is a sub-window of the root, or desktop window + // which is why I guess wayland was created, because X11 can't handle a bunch of stuff like VRF (variable refresh rate) + // because your say two monitors are treated as one big window, in effect limiting the refresh rate + // to whatever the lowest is. I still don't like Wayland though. Forced VSync and a fragmented design is annoying. + // plus needless security in a low level lib preventing stuff like discord screen sharing. Annoying as hell. /rant/. + desktop = DefaultRootWindow(display); + // try to open a gl visual context that meets our attributes' requirements + dlog << "Getting visual info!\n"; + visualInfo = glXChooseVisual(display, 0, OpenGLAttributes); + // if our attributes are too much for the display, let's try reducing them. (modern hardware should support 24bit depth though) + if (visualInfo == NULL) { + wlog << "Unable to open a window with a depth of 24. Trying 16 bits.\n"; + OpenGLAttributes[2] = 16; + visualInfo = glXChooseVisual(display, 0, OpenGLAttributes); + if (visualInfo == NULL) { + throw std::runtime_error("Unable to create window's visual context. Is your driver up to date?\n"); + } } - void XWindow::closeWindow() { - // since this is called in the destructor, we don't want to double delete our window - if (isCloseRequested) - return; - tlog << "Closing window!\n"; - isCloseRequested = true; - ImGui_ImplOpenGL3_Shutdown(); - ImGui_ImplGlfw_Shutdown(); - ImGui::DestroyContext(); + ilog << visualInfo->visualid << ": With depth: " << visualInfo->depth << " and RGB: " << visualInfo->bits_per_rgb << "\n"; + // use our requirements to create a colormap for the screen. + colormap = XCreateColormap(display, desktop, visualInfo->visual, AllocNone); + // arguments used to open a window for us + xSetWindowAttributes.colormap = colormap; + // what kind of events we want to receive + xSetWindowAttributes.event_mask = + ExposureMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | KeyReleaseMask | LeaveWindowMask | + EnterWindowMask | FocusChangeMask | PointerMotionMask; + m_displayWidth = XDisplayWidth(display, 0); + m_displayHeight = XDisplayHeight(display, 0); + window = XCreateWindow(display, + desktop, + // center the display, even if the window manager ignores this. + m_displayWidth / 2 - width / 2, + m_displayHeight / 2 - height / 2, + width, + height, + 0, + visualInfo->depth, + InputOutput, + visualInfo->visual, + CWColormap | CWEventMask, + &xSetWindowAttributes); + // install a error handler + // maybe we should set back the old one but I'd rather it goto std:err than crash the window + XSetErrorHandler([](Display* displayPtr, XErrorEvent* eventPtr) -> int { + elog << "An error occurred while trying to setup X11: " << eventPtr->error_code << ";\n " << eventPtr->minor_code << ";\n " + << eventPtr->request_code << "\n"; + return 0; + }); + + XStoreName(display, window, "3P93 Raytracing Project"); + ImageInput image("../resources/icon/icon.png"); + auto* imageData = image.getImageAsIconBuffer(); + + auto hints = XAllocWMHints(); + hints->flags = IconPixmapHint | StateHint | IconPositionHint; + auto pixMapRob = XCreateBitmapFromData(display, window, (const char*) (icon_bits), 32, 32); + if (!pixMapRob) + flog << "Unable to create icon pixel map\n"; + hints->icon_pixmap = pixMapRob; + hints->initial_state = IconicState; + hints->icon_x = 0; + hints->icon_y = 0; + XSetWMHints(display, window, hints); + XFree(hints); + + int length = 32 * 32 + 2; + //int length = 16 * 16 * 4 + 32*32 * 4 + 4 * 4; + XChangeProperty(display, + window, + XInternAtom(display, "_NET_WM_ICON", False), + XInternAtom(display, "CARDINAL", False), + 32, + PropModeReplace, + (const unsigned char*) imageData, + length); + delete[](imageData); + // there might actually be an argument to be made about X11 being outdated.... + wmDelete = XInternAtom(display, "WM_DELETE_WINDOW", True); + XSetWMProtocols(display, window, &wmDelete, 1); + + // Now show the window + XMapWindow(display, window); + + // get the list of GLX extensions for this system + const char* glExtensions = glXQueryExtensionsString(display, DefaultScreen(display)); + // much in the same way that we get GL function pointers and use them we will do the same with the context creation + auto glXCreateContextAttribsARBPtr = (PFNGLXCREATECONTEXTATTRIBSARBPROC) glXGetProcAddressARB((unsigned char*) "glXCreateContextAttribsARB"); + // now we can finally create a OpenGL context for our window + int OpenGLContextAttributes[] = { + // OpenGL major version, we want GL4.5+ + GLX_CONTEXT_MAJOR_VERSION_ARB, 4, + // OpenGL minor version, + GLX_CONTEXT_MINOR_VERSION_ARB, 5, + // I don't remember what this does, but I know GLFW recommends that forward compatability be set true, (Pretty sure it's only an issue + // on MacOS but I've always included this in all my projects so :shrug: + GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + // Core profile for better Renderdoc compatibility + I don't need non core extensions + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + None + }; + // now we can actually create and acquire the context + glContext = glXCreateContextAttribsARBPtr(display, bestConfig, 0, True, OpenGLContextAttributes); + // make sure if there was any error we are notified + XSync(display, False); + if (!glContext) + flog << "Unable to create GL context!"; + if (glXIsDirect(display, glContext)) { + ilog << "A direct GL context was acquired!\n"; + } else // direct contexts are faster than indirect! + wlog << "Warning! Indirect context!\n"; + // make the currently executing thread the one current to the OpenGL context + // since OpenGL is a single threaded finite state machine if we want to do mutli-threading with OpenGL (we don't) + // this has to be called in each thread before we make use of any OpenGL function. + glXMakeCurrent(display, window, glContext); + // Now we can issue some OpenGL commands + // we want to respect depth + glEnable(GL_DEPTH_TEST); + + //assignGLFunctionPointers(); + //glEnableVertexArrayAttribPtr = glXGetProcAddress((unsigned char*)("glEnableVertexArrayAttrib")); + + // Setup Dear IMGUI + IMGUI_CHECKVERSION(); + ImGui::CreateContext(); + ImGuiIO& io = ImGui::GetIO(); + + ImGui::StyleColorsDark(); + + ImGui_ImplGlfw_Init(); + ImGui_ImplOpenGL3_Init("#version 130"); + + + } + void XWindow::beginUpdate() { + // only try to check events if they are queued + while (XPending(display) > 0) { + XNextEvent(display, &events); - XFree(visualInfo); - glXMakeCurrent(display, None, NULL); - glXDestroyContext(display, glContext); - XDestroyWindow(display, window); - XCloseDisplay(display); + // one of the few times I'll use a switch statement + switch (events.type) { + // called when the system thinks that the window should be updated + // so on window resize events and of course on actual window update + case Expose: + // update window information + XGetWindowAttributes(display, window, &windowAttributes); + glViewport(0, 0, windowAttributes.width, windowAttributes.height); + this->m_width = windowAttributes.width; + this->m_height = windowAttributes.height; + break; + case KeyPress: { + // translates xkeycodes to ascii keys + KeySym _key = XLookupKeysym(&events.xkey, 0); + ImGui_ImplGlfw_KeyCallback(_key, 0, true, 0); + break; + } + case KeyRelease: { + KeySym _key = XLookupKeysym(&events.xkey, 0); + ImGui_ImplGlfw_KeyCallback(_key, 0, false, 0); + break; + } + case ButtonPress: + if (events.xbutton.button < 4) + ImGui_ImplGlfw_MouseButtonCallback(events.xbutton.button - 1, true, 0); + else { + if (events.xbutton.button == 4) + ImGui_ImplGlfw_ScrollCallback(0, 1); + else if (events.xbutton.button == 5) + ImGui_ImplGlfw_ScrollCallback(0, -1); + else if (events.xbutton.button == 6) + ImGui_ImplGlfw_ScrollCallback(1, 0); + else if (events.xbutton.button == 7) + ImGui_ImplGlfw_ScrollCallback(-1, 0); + } + break; + case ButtonRelease: + if (events.xbutton.button < 4) + ImGui_ImplGlfw_MouseButtonCallback(events.xbutton.button - 1, false, 0); + else { + ImGui_ImplGlfw_ScrollCallback(0, 0); + } + break; + case MotionNotify: + ImGui_ImplGlfw_CursorPosCallback(events.xmotion.x, events.xmotion.y, true); + break; + case EnterNotify: + ImGui_ImplGlfw_CursorEnterCallback(1, true); + break; + case LeaveNotify: + ImGui_ImplGlfw_CursorEnterCallback(0, true); + break; + case FocusIn: + ImGui_ImplGlfw_WindowFocusCallback(1); + break; + case FocusOut: + ImGui_ImplGlfw_WindowFocusCallback(0); + break; + case ClientMessage: + if (events.xclient.data.l[0] == wmDelete) { + closeWindow(); + return; + } + break; + } } - #endif + glClearColor(0, 0, 0, 1); + glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame((double) std::chrono::duration_cast( + std::chrono::high_resolution_clock::now().time_since_epoch()).count(), + m_width, + m_height, + m_width, + m_height); + ImGui::NewFrame(); + + static bool t = true; + if (t) + ImGui::ShowDemoWindow(&t); + } + void XWindow::endUpdate() { + ImGui::Render(); + ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); + ImGui_ImplGlfw_UpdateMouseData(true, true); + + // we use double buffering to prevent screen tearing and other visual disturbances + glXSwapBuffers(display, window); + } + void XWindow::closeWindow() { + // since this is called in the destructor, we don't want to double delete our window + if (isCloseRequested) + return; + tlog << "Closing window!\n"; + isCloseRequested = true; + ImGui_ImplOpenGL3_Shutdown(); + ImGui_ImplGlfw_Shutdown(); + ImGui::DestroyContext(); + + XFree(visualInfo); + glXMakeCurrent(display, None, NULL); + glXDestroyContext(display, glContext); + XDestroyWindow(display, window); + XCloseDisplay(display); + } +#endif XWindow::~XWindow() { closeWindow(); deleteKeys(); @@ -480,13 +482,65 @@ namespace Raytracing { static int raysPerPixel = 50; static float yaw = 0, pitch = 0; + std::pair DisplayRenderer::getCameraMatrices() { + auto projection = m_camera.project(); + if (m_window.isMouseGrabbed()) { + yaw += (float) Input::getMouseDelta().x * (1000.0f / ImGui::GetIO().Framerate / 1000.0f) * 3; + pitch += (float) Input::getMouseDelta().y * (1000.0f / ImGui::GetIO().Framerate / 1000.0f) * 1.5f; + + const PRECISION_TYPE turnSpeed = 50; + + if (Input::isKeyDown(GLFW_KEY_LEFT)) + yaw += float(turnSpeed * m_window.getFrameTimeSeconds()); + if (Input::isKeyDown(GLFW_KEY_RIGHT)) + yaw -= float(turnSpeed * m_window.getFrameTimeSeconds()); + if (Input::isKeyDown(GLFW_KEY_UP)) + pitch += float(turnSpeed * m_window.getFrameTimeSeconds()); + if (Input::isKeyDown(GLFW_KEY_DOWN)) + pitch -= float(turnSpeed * m_window.getFrameTimeSeconds()); + + PRECISION_TYPE moveAtX = 0, moveAtY = 0, moveAtZ = 0; + PRECISION_TYPE speed = 40.0f; + + if (Input::isKeyDown(GLFW_KEY_LEFT_ALT)) + speed = 5.0f; + if (Input::isKeyDown(GLFW_KEY_LEFT_CONTROL)) + speed = speed * 2; + + if (Input::isKeyDown(GLFW_KEY_W)) + moveAtX = speed * m_window.getFrameTimeSeconds(); + else if (Input::isKeyDown(GLFW_KEY_S)) + moveAtX = -speed * m_window.getFrameTimeSeconds(); + + if (Input::isKeyDown(GLFW_KEY_A)) + moveAtZ = -speed * m_window.getFrameTimeSeconds(); + else if (Input::isKeyDown(GLFW_KEY_D)) + moveAtZ = speed * m_window.getFrameTimeSeconds(); + + if (Input::isKeyDown(GLFW_KEY_SPACE)) + moveAtY = speed * m_window.getFrameTimeSeconds(); + else if (Input::isKeyDown(GLFW_KEY_LEFT_SHIFT)) + moveAtY = -speed * m_window.getFrameTimeSeconds(); + + PRECISION_TYPE radYaw = degreeeToRadian(yaw); + + PRECISION_TYPE deltaX = -moveAtX * std::sin(radYaw) + moveAtZ * std::cos(radYaw); + PRECISION_TYPE deltaY = moveAtY; + PRECISION_TYPE deltaZ = -moveAtX * std::cos(radYaw) + -moveAtZ * std::sin(radYaw); + + m_camera.setPosition(m_camera.getPosition() + Vec4{deltaX, deltaY, deltaZ}); + } + auto view = m_camera.view(yaw, pitch); + return {projection, view}; + } + void DisplayRenderer::draw() { - if (RTSignal->haltExecution){m_window.closeWindow();} + if (RTSignal->haltExecution) { m_window.closeWindow(); } if (Input::isKeyDown(GLFW_KEY_ESCAPE) && Input::isState(GLFW_KEY_ESCAPE)) m_window.setMouseGrabbed(!m_window.isMouseGrabbed()); - + DebugUI::render([this]() -> void { - if (ImGui::Button("Start") && !started){ + if (ImGui::Button("Start") && !started) { started = true; RTSignal->haltRaytracing = false; ilog << "Running raycaster!\n"; @@ -494,14 +548,14 @@ namespace Raytracing { int threads = std::stoi(m_parser.getOptionValue("--threads")); if (m_parser.hasOption("--mpi")) { //m_raycaster.runMPI(raycaster.partitionScreen()); - } else if(m_parser.hasOption("--openmp")){ + } else if (m_parser.hasOption("--openmp")) { m_raycaster.runOpenMP(threads); } else { m_raycaster.runSTDThread(threads); } } - if (ImGui::Checkbox("Pause", &RTSignal->pauseRaytracing)){} - if (ImGui::Button("Stop") && started){ + if (ImGui::Checkbox("Pause", &RTSignal->pauseRaytracing)) {} + if (ImGui::Button("Stop") && started) { RTSignal->haltRaytracing = true; started = false; m_raycaster.deleteThreads(); @@ -512,55 +566,13 @@ namespace Raytracing { m_raycaster.updateRayInfo(maxRayBounce, raysPerPixel); ImGui::Checkbox("Debug", &debug); }); - - if (debug){ - auto projection = m_camera.project(); - if (m_window.isMouseGrabbed()) { - yaw += (float) Input::getMouseDelta().x * (1000.0f / ImGui::GetIO().Framerate / 1000.0f) * 3; - pitch += (float) Input::getMouseDelta().y * (1000.0f / ImGui::GetIO().Framerate / 1000.0f) * 1.5f; - - const PRECISION_TYPE turnSpeed = 50; - - if (Input::isKeyDown(GLFW_KEY_LEFT)) - yaw += float(turnSpeed * m_window.getFrameTimeSeconds()); - if (Input::isKeyDown(GLFW_KEY_RIGHT)) - yaw -= float(turnSpeed * m_window.getFrameTimeSeconds()); - if (Input::isKeyDown(GLFW_KEY_UP)) - pitch += float(turnSpeed * m_window.getFrameTimeSeconds()); - if (Input::isKeyDown(GLFW_KEY_DOWN)) - pitch -= float(turnSpeed * m_window.getFrameTimeSeconds()); - - PRECISION_TYPE moveAtX = 0, moveAtY = 0, moveAtZ = 0; - PRECISION_TYPE speed = 40.0f; - - if (Input::isKeyDown(GLFW_KEY_LEFT_ALT)) - speed = 5.0f; - if (Input::isKeyDown(GLFW_KEY_LEFT_CONTROL)) - speed = speed * 2; - - if (Input::isKeyDown(GLFW_KEY_W)) - moveAtX = speed * m_window.getFrameTimeSeconds(); - else if (Input::isKeyDown(GLFW_KEY_S)) - moveAtX = -speed * m_window.getFrameTimeSeconds(); - - if (Input::isKeyDown(GLFW_KEY_A)) - moveAtZ = -speed * m_window.getFrameTimeSeconds(); - else if (Input::isKeyDown(GLFW_KEY_D)) - moveAtZ = speed * m_window.getFrameTimeSeconds(); - - if (Input::isKeyDown(GLFW_KEY_SPACE)) - moveAtY = speed * m_window.getFrameTimeSeconds(); - else if (Input::isKeyDown(GLFW_KEY_LEFT_SHIFT)) - moveAtY = -speed * m_window.getFrameTimeSeconds(); - - PRECISION_TYPE radYaw = degreeeToRadian(yaw); - - PRECISION_TYPE deltaX = -moveAtX * std::sin(radYaw) + moveAtZ * std::cos(radYaw); - PRECISION_TYPE deltaY = moveAtY; - PRECISION_TYPE deltaZ = -moveAtX * std::cos(radYaw) + -moveAtZ * std::sin(radYaw); - - m_camera.setPosition(m_camera.getPosition() + Vec4{deltaX, deltaY, deltaZ}); - } + + // we want to be able to move around, and the camera matrix functions automatically recalculate image region & projection data. + if (m_parser.hasOption("--gpu")) { + getCameraMatrices(); + } + + if (debug) { // if (Input::isKeyDown(GLFW_KEY_E) && Input::isState(GLFW_KEY_E)) { // auto ray = m_camera.projectRay((PRECISION_TYPE) m_window.displayWidth() / 2, (PRECISION_TYPE) m_window.displayHeight() / 2); // @@ -577,12 +589,12 @@ namespace Raytracing { // } // if (Input::isKeyDown(GLFW_KEY_R) && Input::isState(GLFW_KEY_R)) // m_world.getBVH()->resetNodes(); - auto view = m_camera.view(yaw, pitch); - m_worldShader.setMatrix("projectMatrix", projection); - m_worldShader.setMatrix("viewMatrix", view); + auto matrices = getCameraMatrices(); + m_worldShader.setMatrix("projectMatrix", matrices.first); + m_worldShader.setMatrix("viewMatrix", matrices.second); m_worldShader.use(); auto objs = m_world.getObjectsInWorld(); - for (auto obj : objs) { + for (auto obj: objs) { if (obj->getVAO() != nullptr) { obj->getVAO()->bind(); obj->getVAO()->draw(m_worldShader, {obj->getPosition()}); @@ -596,7 +608,7 @@ namespace Raytracing { m_mainImage.enableGlTextures(1); drawQuad(); } - + m_mainImage.updateImage(); } } \ No newline at end of file diff --git a/Step 3/src/opencl/open_ray_tracing.cpp b/Step 3/src/opencl/open_ray_tracing.cpp index 324e2c4..131336a 100644 --- a/Step 3/src/opencl/open_ray_tracing.cpp +++ b/Step 3/src/opencl/open_ray_tracing.cpp @@ -3,6 +3,8 @@ * Copyright (c) 2022 Brett Terpstra. All Rights Reserved. */ #include + +#include #include "engine/util/loaders.h" namespace Raytracing { @@ -13,7 +15,7 @@ namespace Raytracing { constexpr size_t vecBytes = sizeof(float) * 4; OpenClRaytracer::OpenClRaytracer(const std::string& programLocation, Image& image, Camera& camera, World& world): - image(image) { + image(image), camera(camera) { auto objectsInWorld = world.getObjectsInWorld(); objectCount = 0; // pre-calculate the space needed for objects, since every object must statically store these number of triangles, even if not used. @@ -31,7 +33,7 @@ namespace Raytracing { // 3 vectors per object, 1 size type per object, maxTriangleSize triangles. size_t totalWorldBytes = (vecBytes * 3) * objectCount + sizeof(unsigned long) * objectCount + triangleNumOfBytes * maxTriangleSize * objectCount; - auto objectBuffer = createObjectBuffer(objectsInWorld, totalWorldBytes); + //auto objectBuffer = createObjectBuffer(objectsInWorld, totalWorldBytes); ShaderLoader::define("maxTriangleCount", std::to_string(maxTriangleSize)); ShaderLoader::define("objectCount", std::to_string(objectCount)); @@ -40,30 +42,26 @@ namespace Raytracing { // load up information about the camera. Since these don't generally chance at runtime we can load them up at compile time // however this means that changes made in debug mode do not transfer. - auto origin = camera.getImageOrigin(); - ShaderLoader::define( - "imageOrigin", - "(float4)(" + std::to_string(origin.x()) + ", " + std::to_string(origin.y()) + ", " + std::to_string(origin.z()) + ", " + - std::to_string(origin.w()) + ")" - ); - auto horiz = camera.getHorizontalAxis(); - ShaderLoader::define( - "horizontalAxis", - "(float4)(" + std::to_string(horiz.x()) + ", " + std::to_string(horiz.y()) + ", " + std::to_string(horiz.z()) + ", " + - std::to_string(horiz.w()) + ")" - ); - auto vert = camera.getHorizontalAxis(); - ShaderLoader::define( - "verticalAxis", - "(float4)(" + std::to_string(vert.x()) + ", " + std::to_string(vert.y()) + ", " + std::to_string(vert.z()) + ", " + - std::to_string(vert.w()) + ")" - ); - auto pos = camera.getPosition(); - ShaderLoader::define( - "cameraPosition", - "(float4)(" + std::to_string(pos.x()) + ", " + std::to_string(pos.y()) + ", " + std::to_string(pos.z()) + ", " + - std::to_string(pos.w()) + ")" - ); +// auto origin = camera.getImageOrigin(); +// ShaderLoader::define( +// "imageOrigin", +// "(float3)(" + std::to_string(origin.x()) + ", " + std::to_string(origin.y()) + ", " + std::to_string(origin.z()) + ")" +// ); +// auto horiz = camera.getHorizontalAxis(); +// ShaderLoader::define( +// "horizontalAxis", +// "(float3)(" + std::to_string(horiz.x()) + ", " + std::to_string(horiz.y()) + ", " + std::to_string(horiz.z()) + ")" +// ); +// auto vert = camera.getVerticalAxis(); +// ShaderLoader::define( +// "verticalAxis", +// "(float3)(" + std::to_string(vert.x()) + ", " + std::to_string(vert.y()) + ", " + std::to_string(vert.z()) + ")" +// ); +// auto pos = camera.getPosition(); +// ShaderLoader::define( +// "cameraPosition", +// "(float3)(" + std::to_string(pos.x()) + ", " + std::to_string(pos.y()) + ", " + std::to_string(pos.z()) + ")" +// ); program = new CLProgram(programLocation); OpenCL::createCLProgram(*program); @@ -72,19 +70,13 @@ namespace Raytracing { program->createImage("outputImage", image.getWidth(), image.getHeight()); program->createBuffer("objects", CL_MEM_READ_WRITE, totalWorldBytes); - program->createBuffer("randoms", CL_MEM_READ_ONLY, image.getWidth() * vecBytes); - // the raytracing algorithm needs a good supply of random numbers. This creates it for us on the CPU as to prevent needing to generate on GPU. - auto randomsBufferBytes = new unsigned char[image.getWidth() * vecBytes]; - size_t currentPos = 0; - for (int i = 0; i < image.getWidth(); i++) { - MemoryConvert::writeVectorBytes(randomsBufferBytes, currentPos, Raytracing::RayCaster::randomUnitVector().normalize()); - } - program->writeBuffer("randoms", image.getWidth() * vecBytes, randomsBufferBytes); - storeObjects(objectBuffer, totalWorldBytes); + program->createBuffer("cameraData", CL_MEM_READ_WRITE, sizeof(float) * 3 * 4); + //storeObjects(objectBuffer, totalWorldBytes); program->setKernelArgument("raycast", "outputImage", 0); program->setKernelArgument("raycast", "objects", 1); - program->setKernelArgument("raycast", "randoms", 2); + program->setKernelArgument("raycast", "cameraData", 2); + updateCameraInformation(); } OpenClRaytracer::~OpenClRaytracer() { @@ -167,4 +159,13 @@ namespace Raytracing { // } return buffer; } + void OpenClRaytracer::updateCameraInformation() { + unsigned char buffer[sizeof(float) * 3 * 4]; + size_t currentIndex = 0; + MemoryConvert::writeVectorBytes(buffer, currentIndex, camera.getPosition()); + MemoryConvert::writeVectorBytes(buffer, currentIndex, camera.getVerticalAxis()); + MemoryConvert::writeVectorBytes(buffer, currentIndex, camera.getHorizontalAxis()); + MemoryConvert::writeVectorBytes(buffer, currentIndex, camera.getImageOrigin()); + program->writeBuffer("cameraData", sizeof(float) * 3 * 4, buffer); + } } \ No newline at end of file