diff --git a/imgui.ini b/imgui.ini index 9b2fbdf..370b726 100644 --- a/imgui.ini +++ b/imgui.ini @@ -3,6 +3,36 @@ Pos=60,-9 Size=400,400 [Window][Menu] -Pos=781,339 -Size=173,154 +Pos=-7,17 +Size=276,693 + +[Window][Dear ImGui Demo] +Pos=329,142 +Size=550,680 + +[Window][Dear ImGui Demo/ResizableChild_D5443E47] +IsChild=1 +Size=499,136 + +[Window][Dear ImGui Demo/Red_1D4E05CE] +IsChild=1 +Size=200,100 + +[Window][Menu/ChildR_46923D70] +IsChild=1 +Size=260,243 + +[Window][Menu/Child1_92290D92] +IsChild=1 +Size=246,600 + +[Table][0xC9935533,3] +Column 0 Weight=1.0000 +Column 1 Weight=1.0000 +Column 2 Weight=1.0000 + +[Table][0xE0773582,3] +Column 0 Weight=1.0000 +Column 1 Weight=1.0000 +Column 2 Weight=1.0000 diff --git a/pro2.vcxproj b/pro2.vcxproj index ab9ff35..dc03c75 100644 --- a/pro2.vcxproj +++ b/pro2.vcxproj @@ -43,12 +43,12 @@ true - F:\studia\semestr 5\gpu\pro2\dependencies\include;$(IncludePath) - F:\studia\semestr 5\gpu\pro2\dependencies\lib;$(LibraryPath) + $(SolutionDir)dependencies\include;$(SolutionDir)src\headers;$(IncludePath) + $(SolutionDir)dependencies\lib;$(LibraryPath) - F:\studia\semestr 5\gpu\pro2\dependencies\include;$(IncludePath) - F:\studia\semestr 5\gpu\pro2\dependencies\lib;$(LibraryPath) + $(SolutionDir)dependencies\include;$(SolutionDir)src\headers;$(IncludePath) + $(SolutionDir)dependencies\lib;$(LibraryPath) @@ -87,13 +87,6 @@ - - - - - - - @@ -105,17 +98,17 @@ - - - - - - - + + + + + + + + + - - @@ -124,14 +117,20 @@ - - - - + + + + + + + + + + - - + + diff --git a/pro2.vcxproj.filters b/pro2.vcxproj.filters index 1d9c41e..b7e912f 100644 --- a/pro2.vcxproj.filters +++ b/pro2.vcxproj.filters @@ -1,10 +1,10 @@  - - + + Source - + Source @@ -39,39 +39,36 @@ Include\ImGUI - - Headers + + Include\GLAD - + Headers - + Headers - + Headers - + Headers - + Headers - + Headers - + Headers - + Headers - + Headers - - Include\GLAD - @@ -118,30 +115,30 @@ Include\ImGUI - + Include\GLAD - + Source - + Source - + Source - + Source - + Source - + Shaders - + Shaders diff --git a/scene.cpp b/scene.cpp deleted file mode 100644 index 8fafebe..0000000 --- a/scene.cpp +++ /dev/null @@ -1,12 +0,0 @@ -//#include "scene.hpp" - -// todo: why not constructor? -//void Scene::create() -//{ -// -//} -// -//// it can't be a destructor, because it would be undefined in device code -//void Scene::free() { -// -//} \ No newline at end of file diff --git a/scene.hpp b/scene.hpp deleted file mode 100644 index f4d4a52..0000000 --- a/scene.hpp +++ /dev/null @@ -1,151 +0,0 @@ -#pragma once - -#include "framework.hpp" - -#include -#include - -#ifndef GPU_ERRCHK -#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); } -#endif - -struct Sphere -{ - glm::vec3 center; - float radius; - glm::vec3 albedo; -}; - -struct Light -{ - glm::vec3 position; - //const float radius = 0.2f; - glm::vec3 color; -}; - -struct Scene -{ - //std::vector spheres; - //std::vector lights; - - // todo: those pointers are const - - glm::vec3* spherePositions; - glm::vec3* sphereAlbedos; - float* sphereRadii; - - glm::vec3* lightPositions; - glm::vec3* lightColors; - const float lightRadius = 0.2f; - - // todo: idk, dry, maybe do sth like SceneGPU and SceneCPU? - glm::vec3* cudaSpherePositions; - glm::vec3* cudaSphereAlbedos; - float* cudaSphereRadii; - - glm::vec3* cudaLightPositions; - glm::vec3* cudaLightColors; - - const int sphereCount = 15; - const int lightCount = 10; - - const glm::vec3 ambientColor{ - 1.0f, 1.0f, 1.0f - }; - const glm::vec3 skyColor{ - 0.0f, 0.0f, 0.0f }; - - const float kDiffuse = 0.9f; - const float kSpecular = 0.4f; - const float kAmbient = 0.2f; - const float kShininess = 40; - - void create() - { - static std::vector colorPalette; - static std::vector lightColorPalette; - { - colorPalette.push_back(glm::vec3(0.5, 0.5, 0.5)); - /*colorPalette.push_back(glm::vec3(155.0f / 255.0f, 34.0f / 255.0f, 38.0f / 255.0f)); - colorPalette.push_back(glm::vec3(0.0f / 255.0f, 18.0f / 255.0f, 25.0f / 255.0f)); - colorPalette.push_back(glm::vec3(0.0f / 255.0f, 95.0f / 255.0f, 115.0f / 255.0f)); - colorPalette.push_back(glm::vec3(10.0f / 255.0f, 147.0f / 255.0f, 150.0f / 255.0f)); - colorPalette.push_back(glm::vec3(148.0f / 255.0f, 210.0f / 255.0f, 189.0f / 255.0f)); - colorPalette.push_back(glm::vec3(233.0f / 255.0f, 216.0f / 255.0f, 166.0f / 255.0f)); - colorPalette.push_back(glm::vec3(238.0f / 255.0f, 155.0f / 255.0f, 0.0f / 255.0f)); - colorPalette.push_back(glm::vec3(202.0f / 255.0f, 103.0f / 255.0f, 2.0f / 255.0f)); - colorPalette.push_back(glm::vec3(187.0f / 255.0f, 62.0f / 255.0f, 3.0f / 255.0f)); - colorPalette.push_back(glm::vec3(174.0f / 255.0f, 32.0f / 255.0f, 18.0f / 255.0f));*/ - - lightColorPalette.push_back(glm::vec3(1.0f, 1.0f, 1.0f)); - lightColorPalette.push_back(glm::vec3(1.0f, 0.0f, 0.0f)); - lightColorPalette.push_back(glm::vec3(0.0f, 1.0f, 0.0f)); - lightColorPalette.push_back(glm::vec3(0.0f, 0.0f, 1.0f)); - lightColorPalette.push_back(glm::vec3(1.0f, 0.0f, 1.0f)); - lightColorPalette.push_back(glm::vec3(0.0f, 1.0f, 1.0f)); - lightColorPalette.push_back(glm::vec3(1.0f, 1.0f, 0.0f)); - lightColorPalette.push_back(glm::vec3(0.5f, 1.0f, 0.2f)); - lightColorPalette.push_back(glm::vec3(0.0f, 0.5f, 0.1f)); - lightColorPalette.push_back(glm::vec3(0.3f, 0.1f, 0.8f)); - } - - spherePositions = new glm::vec3[sphereCount]; - sphereRadii = new float[sphereCount]; - sphereAlbedos = new glm::vec3[sphereCount]; - - lightPositions = new glm::vec3[lightCount]; - lightColors = new glm::vec3[lightCount]; - - //srand(time(NULL)); - for (int i = 0; i < sphereCount; i++) - { - spherePositions[i] = glm::vec3( - (float)rand() / RAND_MAX * 10.0f - 5.0f, - (float)rand() / RAND_MAX * 10.0f - 5.0f, - (float)rand() / RAND_MAX * 10.0f - 5.0f); - sphereRadii[i] = 0.2f * (i % 5 + 1); - sphereAlbedos[i] = colorPalette[i % colorPalette.size()]; - } - - for (int i = 0; i < lightCount; i++) - { - lightPositions[i] = glm::vec3( - 5.0f * (float)rand() / RAND_MAX - 2.5f, - 5.0f * (float)rand() / RAND_MAX - 2.5f, - 5.0f * (float)rand() / RAND_MAX - 2.5f); - lightColors[i] = lightColorPalette[i % lightColorPalette.size()]; - } - - size_t sphereVec3ArrSize = sphereCount * sizeof(glm::vec3); - size_t sphereFloatArrSize = sphereCount * sizeof(float); - size_t lightVec3ArrSize = lightCount * sizeof(glm::vec3); - - gpuErrchk(cudaMalloc(&cudaSpherePositions, sphereVec3ArrSize)); - gpuErrchk(cudaMalloc(&cudaSphereAlbedos, sphereVec3ArrSize)); - gpuErrchk(cudaMalloc(&cudaSphereRadii, sphereFloatArrSize)); - gpuErrchk(cudaMalloc(&cudaLightPositions, lightVec3ArrSize)); - gpuErrchk(cudaMalloc(&cudaLightColors, lightVec3ArrSize)); - - gpuErrchk(cudaMemcpy(cudaSpherePositions, spherePositions, sphereVec3ArrSize, cudaMemcpyHostToDevice)); - gpuErrchk(cudaMemcpy(cudaSphereAlbedos, sphereAlbedos, sphereVec3ArrSize, cudaMemcpyHostToDevice)); - gpuErrchk(cudaMemcpy(cudaSphereRadii, sphereRadii, sphereFloatArrSize, cudaMemcpyHostToDevice)); - gpuErrchk(cudaMemcpy(cudaLightPositions, lightPositions, lightVec3ArrSize, cudaMemcpyHostToDevice)); - gpuErrchk(cudaMemcpy(cudaLightColors, lightColors, lightVec3ArrSize, cudaMemcpyHostToDevice)); - } - void free() - { - delete[] spherePositions; - delete[] sphereRadii; - delete[] sphereAlbedos; - delete[] lightPositions; - delete[] lightColors; - - gpuErrchk(cudaFree(cudaSpherePositions)); - gpuErrchk(cudaFree(cudaSphereAlbedos)); - gpuErrchk(cudaFree(cudaSphereRadii)); - gpuErrchk(cudaFree(cudaLightPositions)); - gpuErrchk(cudaFree(cudaLightColors)); - } - - -}; \ No newline at end of file diff --git a/application.hpp b/src/headers/application.hpp similarity index 88% rename from application.hpp rename to src/headers/application.hpp index 5ff02a2..2870607 100644 --- a/application.hpp +++ b/src/headers/application.hpp @@ -12,7 +12,7 @@ class Application Application(); ~Application(); - constexpr static int WIDTH = 800; + constexpr static int WIDTH = 1200; constexpr static int HEIGHT = 800; void run(); @@ -21,7 +21,7 @@ class Application void processKeyboard(int key); void processMouse(glm::vec2 offset); - enum solutionModes {CPU, GPU}; + enum solutionModes {CPU, GPU, GPUshadows}; solutionModes solutionMode = GPU; private: Window* window; diff --git a/camera.hpp b/src/headers/camera.hpp similarity index 61% rename from camera.hpp rename to src/headers/camera.hpp index 31ec207..dafbe48 100644 --- a/camera.hpp +++ b/src/headers/camera.hpp @@ -7,28 +7,38 @@ class Camera { public: - Camera(int width, int height, float fov = glm::radians(70.0), - float nearPlane = 0.01, float farPlane = 100); - //float left = -1.0f, float right = 1.0f, float bottom = -1.0f, float top = 1.0f); + Camera(int width, int height, + std::vector&, std::vector&, + glm::vec3 position = glm::vec3(-10.0f, 0.0f, 60.0f), + float fov = glm::radians(50.0), + float nearPlane = 0.01, + float farPlane = 100); std::vector& getOrthographicRayOrigins(); glm::vec3& getRayOrigin() { return position; } glm::vec3* getRayDirections(); void onResize(int width, int height); - void onUpdate(int key, float deltaTime); + void onKeyboardUpdate(int key, float deltaTime); void onMouseUpdate(glm::vec2 offset, float deltaTime); glm::vec3 position; void calculateRayDirections(); + glm::mat4& getInverseProjMatrix() { return inverseProjMatrix; } + glm::mat4& getInverseViewMatrix() { return inverseViewMatrix; } + private: - float speed, rotationSpeed; + const float speed = 15.0f; + const float rotationSpeed = 0.005f; glm::vec3 forwardDirection, rightDirection, upDirection; const glm::vec3 worldUpDirection = glm::vec3(0.0f, 1.0f, 0.0f); + std::vector& viewportHorizontalIter; + std::vector& viewportVerticalIter; + float fov, nearPlane, farPlane; //float left, right, bottom, top; diff --git a/cuda.cuh b/src/headers/cuda.cuh similarity index 74% rename from cuda.cuh rename to src/headers/cuda.cuh index a2b135e..dbf603b 100644 --- a/cuda.cuh +++ b/src/headers/cuda.cuh @@ -1,20 +1,20 @@ -#ifndef _CUDA_CUH -#define _CUDA_CUH +#pragma once #include "framework.hpp" #include "scene.hpp" #include -//struct Scene; - struct cudaArguments { unsigned int* cudaImage; const int width; const int height; - const struct Scene scene; + const class Scene scene; const glm::vec3 rayOrigin; const glm::vec3* rayDirections; const glm::vec3 cameraPos; + const glm::mat4 inverseProjMatrix; + const glm::mat4 inverseViewMatrix; + bool shadows; }; __host__ void callKernels(dim3 blocks_per_grid, dim3 max_threads, @@ -22,4 +22,3 @@ __host__ void callKernels(dim3 blocks_per_grid, dim3 max_threads, __global__ void rayTrace(cudaArguments args); -#endif \ No newline at end of file diff --git a/framework.hpp b/src/headers/framework.hpp similarity index 77% rename from framework.hpp rename to src/headers/framework.hpp index 264de4f..812f95a 100644 --- a/framework.hpp +++ b/src/headers/framework.hpp @@ -5,7 +5,6 @@ #include #include -#include #include #include @@ -20,6 +19,7 @@ #include "ImGUI/imgui_impl_opengl3.h" #ifndef GPU_ERRCHK +#define GPU_ERRCHK #define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); } #endif @@ -32,16 +32,5 @@ inline void gpuAssert(cudaError_t code, const char* file, int line, bool abort = } } -#include "utils.hpp" #include "ray.hpp" -#include "scene.hpp" - - -#include "cuda.cuh" -#include "camera.hpp" -#include "shader.hpp" -#include "renderer.hpp" -#include "window.hpp" -#include "application.hpp" - - +#include "scene.hpp" \ No newline at end of file diff --git a/ray.hpp b/src/headers/ray.hpp similarity index 100% rename from ray.hpp rename to src/headers/ray.hpp diff --git a/renderer.hpp b/src/headers/renderer.hpp similarity index 67% rename from renderer.hpp rename to src/headers/renderer.hpp index fae2d93..9fcd323 100644 --- a/renderer.hpp +++ b/src/headers/renderer.hpp @@ -1,47 +1,45 @@ #pragma once -#include "framework.hpp" - -class Application; -class Camera; -struct Scene; +#include "application.hpp" +#include "camera.hpp" class Renderer { public: - Renderer(int width, int height, Application *parent); + Renderer(int width, int height); ~Renderer(); void resize(int width, int height); void processKeyboard(int key, float dTime); void processMouse(glm::vec2 offset, float dTime); - // todo: this should be another class's responsibility - void update(float deltaTime); + void notifyCamera(); void renderCPU(); - void renderGPU(); + void renderGPU(bool shadows); GLuint* getImage(); int width, height; Scene scene; private: - Application* app; Camera* camera; - unsigned int* imageData; + std::vector viewportHorizontalIter; + std::vector viewportVerticalIter; + unsigned int* imageData; unsigned int* cudaImage; glm::vec3* cudaRayDirections; glm::vec4 rayGen(int i, int j); - // cast a ray and get hit information + + // casts a ray and gets hit information HitPayload traceRayFromPixel(const Ray& ray); HitPayload traceRayFromHitpoint(const Ray& ray, float diff); HitPayload lightHit(const Ray& ray, int lightIndex); HitPayload closestHit(const Ray& ray, int sphereIndex, float hitDistance); HitPayload miss(const Ray& ray); + glm::vec4 phong(HitPayload payload, int lightIndex, float d); - glm::vec4 phong(HitPayload payload, int lightIndex); unsigned int toRGBA(glm::vec4&); }; \ No newline at end of file diff --git a/src/headers/scene.hpp b/src/headers/scene.hpp new file mode 100644 index 0000000..976aa2e --- /dev/null +++ b/src/headers/scene.hpp @@ -0,0 +1,70 @@ +#pragma once + +#include "framework.hpp" + +#include +#include +#include +#include +#include + +struct SceneParams { + glm::vec3 ambientColor{ 1.0f, 1.0f, 1.0f }; + glm::vec3 skyColor{ 0.25f, 0.25f, 0.25f }; + + float kDiffuse = 0.9f; + float kSpecular = 0.4f; + float kAmbient = 0.2f; + float kShininess = 40; + + const float linearAttValues[13] = { + 0.7f, 0.35f, 0.22f, 0.14f, 0.09f, 0.07f, 0.045f, 0.027f, 0.022f, 0.014f, 0.007f, 0.0014f }; + const float quadraticAttValues[13] = { + 1.8f, 0.44f, 0.20f, 0.07f, 0.032f, 0.017f, 0.0075f, 0.0028f, 0.0019f, 0.0007f, 0.0002f, 0.000007f }; + + const int startAttIdx = 5; + + float linearAtt = linearAttValues[startAttIdx]; + float quadraticAtt = quadraticAttValues[startAttIdx]; + + const float worldBorder = 20; +}; + +class Scene +{ +public: + glm::vec3* spherePositions; + glm::vec3* sphereAlbedos; + float* sphereRadii; + + glm::vec3* lightPositions; + glm::vec3* lightColors; + const float lightRadius = 0.2f; + bool* lightBools; + + glm::vec3* cudaSpherePositions; + glm::vec3* cudaSphereAlbedos; + float* cudaSphereRadii; + + glm::vec3* cudaLightPositions; + glm::vec3* cudaLightColors; + bool* cudaLightBools; + + const int sphereCount = 1000; + const int lightCount = 10; + + SceneParams params; + + void create(); + void free(); + void updateScene(float deltaTime); + void updateCuda(); + void drawImGui(); + +private: + bool dirtyLightPos = false; + bool dirtyLightCol = false; + bool dirtyLightBools = false; + bool dirtySphereCol = false; +}; + diff --git a/shader.hpp b/src/headers/shader.hpp similarity index 100% rename from shader.hpp rename to src/headers/shader.hpp diff --git a/window.hpp b/src/headers/window.hpp similarity index 89% rename from window.hpp rename to src/headers/window.hpp index 22c3bbc..6328627 100644 --- a/window.hpp +++ b/src/headers/window.hpp @@ -2,7 +2,7 @@ #include "framework.hpp" -class Application; +#include "application.hpp"; class Window { diff --git a/fragment.glsl b/src/shaders/fragment.glsl similarity index 100% rename from fragment.glsl rename to src/shaders/fragment.glsl diff --git a/vertex.glsl b/src/shaders/vertex.glsl similarity index 100% rename from vertex.glsl rename to src/shaders/vertex.glsl diff --git a/application.cpp b/src/src/application.cpp similarity index 81% rename from application.cpp rename to src/src/application.cpp index 5730013..9ba474d 100644 --- a/application.cpp +++ b/src/src/application.cpp @@ -1,12 +1,13 @@ #include "application.hpp" - -#include +#include "window.hpp" +#include "shader.hpp" +#include "renderer.hpp" Application::Application() { window = new Window(this); - shader = new Shader("vertex.glsl", "fragment.glsl"); - renderer = new Renderer(WIDTH, HEIGHT, this); + shader = new Shader("src/shaders/vertex.glsl", "src/shaders/fragment.glsl"); + renderer = new Renderer(WIDTH, HEIGHT); deltaTime = 0; } @@ -31,10 +32,7 @@ void Application::run() double previousTime = glfwGetTime(); double previousFpsTime = previousTime; - if (freeCamera) - glfwSetInputMode(window->wndptr, GLFW_CURSOR, GLFW_CURSOR_DISABLED); - else - glfwSetInputMode(window->wndptr, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + freeCamera = false; static bool firstFrame = true; @@ -67,9 +65,40 @@ void Application::run() glfwSwapBuffers(window->wndptr); glfwPollEvents(); + } +} + +void Application::imGuiFrame(int fps) +{ + ImGui_ImplOpenGL3_NewFrame(); + ImGui_ImplGlfw_NewFrame(); + ImGui::NewFrame(); + + if (!ImGui::Begin("Menu", NULL, 0)) + { + ImGui::End(); + return; + } - //while (true); + ImGui::PushItemWidth(-ImGui::GetWindowWidth() * 0.45f); + + static const char* items[] = { "CPU no shadows", + "GPU no shadows", + "GPU shadows" }; + static int selectedItem = 1; + + if (ImGui::Combo("Solution", &selectedItem, items, IM_ARRAYSIZE(items))) + { + solutionMode = (solutionModes)selectedItem; + renderer->notifyCamera(); } + + ImGui::Text("%d fps", fps); + + renderer->scene.drawImGui(); + + ImGui::End(); + } void Application::resize(int width, int height) @@ -133,11 +162,15 @@ void Application::createTexture() void Application::updateAndRenderScene() { - renderer->update(deltaTime); + renderer->scene.updateScene(deltaTime); + if (solutionMode == CPU) renderer->renderCPU(); else - renderer->renderGPU(); + { + renderer->scene.updateCuda(); + renderer->renderGPU(solutionMode == GPUshadows); + } glTextureSubImage2D(texture, 0, 0, 0, renderer->width, renderer->height, GL_RGBA, @@ -145,35 +178,6 @@ void Application::updateAndRenderScene() glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0); } -void Application::imGuiFrame(int fps) -{ - ImGui_ImplOpenGL3_NewFrame(); - ImGui_ImplGlfw_NewFrame(); - ImGui::NewFrame(); - - if (!ImGui::Begin("Menu", NULL, 0)) - { - ImGui::End(); - return; - } - - ImGui::PushItemWidth(-ImGui::GetWindowWidth() * 0.45f); - - static const char* items[] = { "CPU", "GPU" }; - static int selectedItem = 1; - - if (ImGui::Combo("Solution", &selectedItem, items, IM_ARRAYSIZE(items))) - { - solutionMode = (solutionModes)selectedItem; - } - - ImGui::Text("%d fps", fps); - - ImGui::DragFloat3("Light", glm::value_ptr(renderer->scene.lightPositions[0]), 0.01f, -2.5f, 10.0f); - - ImGui::End(); -} - void Application::textureResizeStorage(int width, int height) { glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, @@ -182,6 +186,23 @@ void Application::textureResizeStorage(int width, int height) void Application::processKeyboard(int key) { + if (key == GLFW_KEY_F) + { + freeCamera = !freeCamera; + if (freeCamera) + glfwSetInputMode(window->wndptr, GLFW_CURSOR, GLFW_CURSOR_DISABLED); + else + glfwSetInputMode(window->wndptr, GLFW_CURSOR, GLFW_CURSOR_NORMAL); + + return; + } + + if (freeCamera && (key == GLFW_KEY_Q || + key == GLFW_KEY_E || + key == GLFW_KEY_1 || + key == GLFW_KEY_3)) + return; + renderer->processKeyboard(key, deltaTime); } diff --git a/camera.cpp b/src/src/camera.cpp similarity index 57% rename from camera.cpp rename to src/src/camera.cpp index 1c6fb83..a0df023 100644 --- a/camera.cpp +++ b/src/src/camera.cpp @@ -1,10 +1,19 @@ #include "camera.hpp" +#include +#include + #include #include #include -Camera::Camera(int width, int height, float fov, float nearPlane, float farPlane) +Camera::Camera(int width, int height, + std::vector& viewportHorizontalIter, + std::vector& viewportVerticalIter, + glm::vec3 position, + float fov, float nearPlane, float farPlane) + : viewportHorizontalIter{ viewportHorizontalIter }, + viewportVerticalIter{ viewportVerticalIter } { viewportWidth = width; viewportHeight = height; @@ -12,16 +21,7 @@ Camera::Camera(int width, int height, float fov, float nearPlane, float farPlane this->fov = fov; this->nearPlane = nearPlane; this->farPlane = farPlane; - - /*this->left = left; - this->right = right; - this->bottom = bottom; - this->top = top;*/ - - position = glm::vec3(0.0f, 0.0f, 6.0f); - - speed = 3.0f; - rotationSpeed = 0.005f; + this->position = position; forwardDirection = glm::vec3(0.0f, 0.0f, -1.0f); rightDirection = glm::normalize(glm::cross(forwardDirection, worldUpDirection)); @@ -29,9 +29,6 @@ Camera::Camera(int width, int height, float fov, float nearPlane, float farPlane rayDirections = new glm::vec3[width * height]; - calculateProjMatrix(); - calculateViewMatrix(); - calculateRayDirections(); } @@ -46,15 +43,13 @@ void Camera::onResize(int width, int height) delete[] rayDirections; rayDirections = new glm::vec3[width * height]; - //float aspectRatio = (float)width / (float)height; - //bottom = -aspectRatio; - //top = aspectRatio; - - calculateProjMatrix(); + calculateRayDirections(); } -void Camera::onUpdate(int key, float deltaTime) +void Camera::onKeyboardUpdate(int key, float deltaTime) { + float rotationSpeed = speed / 3; + switch (key) { case GLFW_KEY_D: @@ -75,9 +70,21 @@ void Camera::onUpdate(int key, float deltaTime) case GLFW_KEY_W: position += forwardDirection * speed * deltaTime; break; + case GLFW_KEY_Q: + onMouseUpdate(glm::vec2(-rotationSpeed, 0), deltaTime); + break; + case GLFW_KEY_E: + onMouseUpdate(glm::vec2(rotationSpeed, 0), deltaTime); + break; + case GLFW_KEY_1: + onMouseUpdate(glm::vec2(0, rotationSpeed), deltaTime); + break; + case GLFW_KEY_3: + onMouseUpdate(glm::vec2(0, -rotationSpeed), deltaTime); + break; } - calculateViewMatrix(); + calculateRayDirections(); } void Camera::onMouseUpdate(glm::vec2 offset, float deltaTime) @@ -91,6 +98,8 @@ void Camera::onMouseUpdate(glm::vec2 offset, float deltaTime) forwardDirection = glm::normalize(glm::rotate(q, forwardDirection)); rightDirection = glm::normalize(glm::cross(forwardDirection, worldUpDirection)); upDirection = glm::normalize(glm::cross(rightDirection, forwardDirection)); + + calculateRayDirections(); } std::vector& Camera::getOrthographicRayOrigins() @@ -105,57 +114,37 @@ glm::vec3* Camera::getRayDirections() void Camera::calculateRayDirections() { - //rayOrigins.resize(viewportWidth * viewportHeight); - //rayDirections.resize(viewportWidth * viewportHeight); - + calculateProjMatrix(); calculateViewMatrix(); - for (int i = 0; i < viewportHeight; ++i) - { - for (int j = 0; j < viewportWidth; ++j) + std::for_each(std::execution::par, viewportVerticalIter.begin(), viewportVerticalIter.end(), + [this](uint32_t i) { - glm::vec2 coord{ - (float)j / viewportWidth, - (float)i / viewportHeight - }; - - coord = coord * 2.0f - 1.0f; - - //glm::vec4 origin = inverseProjMatrix * glm::vec4(coord.x, coord.y, -2.0f, 1.0f); - //glm::vec3 rayOrigin = glm::vec3(inverseViewMatrix * origin);//glm::vec4(glm::normalize(glm::vec3(origin) / origin.w), 1)); - - glm::vec4 target = inverseProjMatrix * glm::vec4(coord.x, coord.y, 1.0f, 1.0f); - glm::vec3 rayDirection = glm::vec3(inverseViewMatrix * glm::vec4(glm::normalize(glm::vec3(target) / target.w), 0)); - //rayDirection = glm::normalize(rayDirection); - - /*rayOrigins[i * viewportWidth + j] = rayOrigin;*/ - rayDirections[i * viewportWidth + j] = rayDirection; - } - } + std::for_each(std::execution::par, viewportHorizontalIter.begin(), viewportHorizontalIter.end(), + [this, i](uint32_t j) + { + glm::vec2 coord{ + (float)j / viewportWidth, + (float)i / viewportHeight + }; + + coord = coord * 2.0f - 1.0f; + + glm::vec4 target = inverseProjMatrix * glm::vec4(coord.x, coord.y, 1.0f, 1.0f); + glm::vec3 rayDirection = glm::vec3(inverseViewMatrix * glm::vec4(glm::normalize(glm::vec3(target) / target.w), 0)); + rayDirections[i * viewportWidth + j] = rayDirection; + }); + }); } void Camera::calculateProjMatrix() { - /*projMatrix = glm::ortho(left, right, bottom, top);*/ projMatrix = glm::perspective(fov, (float)viewportWidth / (float)viewportHeight, nearPlane, farPlane); inverseProjMatrix = glm::inverse(projMatrix); } void Camera::calculateViewMatrix() { - /*viewMatrix = glm::mat4( - glm::vec4(rightDirection, 0.0f), - glm::vec4(upDirection, 0.0f), - glm::vec4(forwardDirection, 0.0f), - glm::vec4(position, 1.0) - );*/ viewMatrix = glm::lookAt(position, position + forwardDirection, worldUpDirection); inverseViewMatrix = glm::inverse(viewMatrix); - - /*inverseViewMatrix = glm::mat4( - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - position.x, position.y, position.z, 1.0f - );*/ } diff --git a/cuda.cu b/src/src/cuda.cu similarity index 73% rename from cuda.cu rename to src/src/cuda.cu index 35215a8..407ae48 100644 --- a/cuda.cu +++ b/src/src/cuda.cu @@ -46,7 +46,6 @@ __device__ HitPayload closestHit(const Ray& ray, int sphereIndex, float hitDista return payload; } -// todo: merge rayTrace functions __device__ HitPayload traceRayFromPixel(const Ray& ray, Scene scene) { int hitSphereIndex = -1; @@ -79,7 +78,10 @@ __device__ HitPayload traceRayFromPixel(const Ray& ray, Scene scene) } for (int k = 0; k < scene.lightCount; k++) - { + { + if (!scene.cudaLightBools[k]) + continue; + glm::vec3 origin = ray.origin - scene.cudaLightPositions[k]; glm::vec3 direction = ray.direction; @@ -100,7 +102,7 @@ __device__ HitPayload traceRayFromPixel(const Ray& ray, Scene scene) hitSphereIndex = -2; hitLightIndex = k; } - + } if (hitSphereIndex == -1) @@ -148,7 +150,7 @@ __device__ HitPayload traceRayFromHitpoint(Ray& ray, float diff, Scene scene) return closestHit(ray, hitSphereIndex, hitDistance, scene); } -__device__ glm::vec4 phong(HitPayload payload, int lightIndex, Scene scene, glm::vec3 cameraPos) +__device__ glm::vec4 phong(HitPayload payload, int lightIndex, Scene scene, glm::vec3 cameraPos, float d) { glm::vec3 lightDir = glm::normalize(scene.cudaLightPositions[lightIndex] - payload.hitPoint); glm::vec3 lightColor = scene.cudaLightColors[lightIndex]; @@ -158,19 +160,17 @@ __device__ glm::vec4 phong(HitPayload payload, int lightIndex, Scene scene, glm: float cosVR = glm::max(0.0f, glm::dot(reflectionVector, eyeVector)); glm::vec3 color = - scene.kDiffuse * cosNL * lightColor + - scene.kSpecular * glm::pow(cosVR, scene.kShininess) * lightColor; - - color *= scene.cudaSphereAlbedos[payload.objectIndex]; - - //return glm::vec4(1, 0, 0, 1); + scene.params.kDiffuse * cosNL * lightColor + + scene.params.kSpecular * glm::pow(cosVR, scene.params.kShininess) * lightColor; + + float attenuation = 1.0f / (1.0f + d * (scene.params.linearAtt + scene.params.quadraticAtt * d)); + color *= attenuation * scene.cudaSphereAlbedos[payload.objectIndex]; return glm::vec4(color, 1.0f); } -// todo: scene in shared memory? __device__ glm::vec4 rayGen(int i, int j, glm::vec3 origin, - glm::vec3 direction, Scene scene, glm::vec3 cameraPos) + glm::vec3 direction, Scene scene, bool shadows) { Ray ray; @@ -182,38 +182,59 @@ __device__ glm::vec4 rayGen(int i, int j, glm::vec3 origin, // no sphere detected if (payload.hitDistance < 0) - return glm::vec4(scene.skyColor, 1.0f); + return glm::vec4(scene.params.skyColor, 1.0f); // light source hit if (payload.hitDistance == 0) return glm::vec4(scene.cudaLightColors[idx], 1.0f); - glm::vec4 color = glm::vec4(scene.kAmbient * scene.ambientColor * scene.cudaSphereAlbedos[idx], 1.0f); - + glm::vec4 color = glm::vec4(scene.params.kAmbient * scene.params.ambientColor * scene.cudaSphereAlbedos[idx], 1.0f); + // cast rays from hitpoint to light sources for (int lightIdx = 0; lightIdx < scene.lightCount; lightIdx++) { - Ray rayToLight; + if (!scene.cudaLightBools[lightIdx]) + continue; - // cast ray a bit away from the sphere so that the ray doesn't hit it - rayToLight.origin = payload.hitPoint + payload.normal * 1e-4f; - // todo: avoid double calculating length float distanceToLight = glm::length(scene.cudaLightPositions[lightIdx] - payload.hitPoint); - rayToLight.direction = glm::normalize(scene.cudaLightPositions[lightIdx] - payload.hitPoint); - HitPayload payloadToLight = traceRayFromHitpoint(rayToLight, distanceToLight, scene); - - // no sphere hit on path to light - if (payloadToLight.hitDistance < 0) + if (shadows) { - //printf("chuj mi w dupe\n"); - color += phong(payload, lightIdx, scene, cameraPos); + Ray rayToLight; + + // cast ray a bit away from the sphere so that the ray doesn't hit it + rayToLight.origin = payload.hitPoint + payload.normal * 1e-3f; + rayToLight.direction = glm::normalize(scene.cudaLightPositions[lightIdx] - payload.hitPoint); + + HitPayload payloadToLight = traceRayFromHitpoint(rayToLight, distanceToLight, scene); + + // no sphere hit on path to light + if (payloadToLight.hitDistance < 0) + color += phong(payload, lightIdx, scene, origin, distanceToLight); } + else + color += phong(payload, lightIdx, scene, origin, distanceToLight); + } - + return glm::clamp(color, 0.0f, 1.0f); } +__device__ glm::vec3 getRayDirection(int i, int j, cudaArguments args) +{ + glm::vec2 coord{ + (float)j / args.width, + (float)i / args.height + }; + + coord = coord * 2.0f - 1.0f; + + glm::vec4 target = args.inverseProjMatrix * glm::vec4(coord.x, coord.y, 1.0f, 1.0f); + glm::vec3 rayDirection = glm::vec3(args.inverseViewMatrix * glm::vec4(glm::normalize(glm::vec3(target) / target.w), 0)); + + return rayDirection; +} + __global__ void rayTrace(cudaArguments args) { int x = threadIdx.x + blockIdx.x * blockDim.x; @@ -224,10 +245,9 @@ __global__ void rayTrace(cudaArguments args) int k = x + y * args.width; - //GLuint res = toRGBA(glm::vec4(0.0f, 0.0f, (float)x / args.width, 1.0f)); - - GLuint res = toRGBA(rayGen(y, x, - args.rayOrigin, args.rayDirections[k], args.scene, args.cameraPos)); - + GLuint res = toRGBA(rayGen(y, x, + args.rayOrigin, getRayDirection(y, x, args), + args.scene, args.shadows)); + args.cudaImage[k] = res; } \ No newline at end of file diff --git a/glad.c b/src/src/glad.c similarity index 100% rename from glad.c rename to src/src/glad.c diff --git a/main.cpp b/src/src/main.cu similarity index 79% rename from main.cpp rename to src/src/main.cu index c063667..d32972f 100644 --- a/main.cpp +++ b/src/src/main.cu @@ -1,9 +1,9 @@ #include "framework.hpp" -//#include "cuda.cuh" +#include "application.hpp" +#include "cuda.cuh" __host__ void callKernels(dim3 blocks_per_grid, dim3 max_threads, cudaArguments args) { - // todo: check if callable from renderer because my god rayTrace << > > (args); gpuErrchk(cudaPeekAtLastError()); gpuErrchk(cudaDeviceSynchronize()); diff --git a/renderer.cpp b/src/src/renderer.cpp similarity index 75% rename from renderer.cpp rename to src/src/renderer.cpp index 2a05052..8a1b65c 100644 --- a/renderer.cpp +++ b/src/src/renderer.cpp @@ -1,12 +1,12 @@ #include "renderer.hpp" +#include "cuda.cuh" #include #include #include -Renderer::Renderer(int width, int height, Application* parent) +Renderer::Renderer(int width, int height) { - app = parent; imageData = nullptr; scene.create(); @@ -14,7 +14,7 @@ Renderer::Renderer(int width, int height, Application* parent) gpuErrchk(cudaMalloc(&cudaImage, width * height * sizeof(unsigned int))); gpuErrchk(cudaMalloc(&cudaRayDirections, width * height * sizeof(glm::vec3))); - camera = new Camera(width, height); + camera = new Camera(width, height, viewportHorizontalIter, viewportVerticalIter); resize(width, height); } @@ -46,50 +46,35 @@ void Renderer::resize(int width, int height) gpuErrchk(cudaMalloc(&cudaImage, width * height * sizeof(unsigned int))); gpuErrchk(cudaMalloc(&cudaRayDirections, width * height * sizeof(glm::vec3))); + viewportHorizontalIter.resize(width); + viewportVerticalIter.resize(height); + for (uint32_t i = 0; i < width; i++) + viewportHorizontalIter[i] = i; + for (uint32_t i = 0; i < height; i++) + viewportVerticalIter[i] = i; + camera->onResize(width, height); } -void Renderer::update(float deltaTime) +void Renderer::notifyCamera() { - static float time = glfwGetTime(); - - scene.lightPositions[0] = glm::vec3( - //(glfwGetTime() - time), 0.0f, 0.0f - 2.5f * glm::sin(glfwGetTime()), - 2.5f * glm::cos(glfwGetTime()), - 1.5f * glm::sin(glfwGetTime()) - ); + camera->calculateRayDirections(); } void Renderer::renderCPU() { - // todo: cache the ray directions - camera->calculateRayDirections(); - - // todo: don't resize each time - std::vector horizontalIter; - std::vector verticalIter; - - horizontalIter.resize(width); - verticalIter.resize(height); - for (uint32_t i = 0; i < width; i++) - horizontalIter[i] = i; - for (uint32_t i = 0; i < height; i++) - verticalIter[i] = i; - - std::for_each(std::execution::par, verticalIter.begin(), verticalIter.end(), - [this, horizontalIter](uint32_t i) + std::for_each(std::execution::par, viewportVerticalIter.begin(), viewportVerticalIter.end(), + [this](uint32_t i) { - std::for_each(std::execution::par, horizontalIter.begin(), horizontalIter.end(), + std::for_each(std::execution::par, viewportHorizontalIter.begin(), viewportHorizontalIter.end(), [this, i](uint32_t j) { imageData[i * width + j] = toRGBA(rayGen(i, j)); }); }); - } -void Renderer::renderGPU() +void Renderer::renderGPU(bool shadows) { int pixelsCount = width * height; int size = pixelsCount * sizeof(unsigned int); @@ -101,16 +86,14 @@ void Renderer::renderGPU() dim3 blocks(width / tx + 1, height / ty + 1); dim3 threads(tx, ty); - // todo: temp - cuda probably should calculate ray directions - gpuErrchk(cudaMemcpy(cudaRayDirections, - camera->getRayDirections(), - vecSize, cudaMemcpyHostToDevice)); - cudaArguments args{ cudaImage, width, height, scene, camera->getRayOrigin(), cudaRayDirections, - camera->getRayOrigin() + camera->getRayOrigin(), + camera->getInverseProjMatrix(), + camera->getInverseViewMatrix(), + shadows }; callKernels(blocks, threads, args); @@ -126,8 +109,7 @@ GLuint* Renderer::getImage() glm::vec4 Renderer::rayGen(int i, int j) { Ray ray; - - ray.origin = camera->getRayOrigin(); //camera->getOrthographicRayOrigins()[i * width + j]; + ray.origin = camera->getRayOrigin(); ray.direction = camera->getRayDirections()[i * width + j]; HitPayload payload = traceRayFromPixel(ray); @@ -135,36 +117,40 @@ glm::vec4 Renderer::rayGen(int i, int j) // no sphere detected if (payload.hitDistance < 0) - return glm::vec4(scene.skyColor, 1.0f); + return glm::vec4(scene.params.skyColor, 1.0f); // light source hit if (payload.hitDistance == 0) return glm::vec4(scene.lightColors[idx], 1.0f); - glm::vec4 color = glm::vec4(scene.kAmbient * scene.ambientColor * scene.sphereAlbedos[idx], 1.0f); + glm::vec4 color = glm::vec4(scene.params.kAmbient + * scene.params.ambientColor + * scene.sphereAlbedos[idx], 1.0f); // cast rays from hitpoint to light sources for (int lightIdx = 0; lightIdx < scene.lightCount; lightIdx++) { - Ray rayToLight; - - // cast ray a bit away from the sphere so that the ray doesn't hit it - rayToLight.origin = payload.hitPoint + payload.normal * 1e-4f; - // todo: double calculated length float distanceToLight = glm::length(scene.lightPositions[lightIdx] - payload.hitPoint); - rayToLight.direction = glm::normalize(scene.lightPositions[lightIdx] - payload.hitPoint); + //if (!scene.lightBools[lightIdx]) + // continue; + + //Ray rayToLight; + + //// cast ray a bit away from the sphere so that the ray doesn't hit it + //rayToLight.origin = payload.hitPoint + payload.normal * 1e-4f; + //rayToLight.direction = glm::normalize(scene.lightPositions[lightIdx] - payload.hitPoint); - HitPayload payloadToLight = traceRayFromHitpoint(rayToLight, distanceToLight); + //HitPayload payloadToLight = traceRayFromHitpoint(rayToLight, distanceToLight); - // no sphere hit on path to light - if (payloadToLight.hitDistance < 0) - color += phong(payload, lightIdx); + //// no sphere hit on path to light + //if (payloadToLight.hitDistance < 0) + color += phong(payload, lightIdx, distanceToLight); } return glm::clamp(color, 0.0f, 1.0f); } -glm::vec4 Renderer::phong(HitPayload payload, int lightIndex) +glm::vec4 Renderer::phong(HitPayload payload, int lightIndex, float d) { glm::vec3 lightDir = glm::normalize(scene.lightPositions[lightIndex] - payload.hitPoint); glm::vec3 lightColor = scene.lightColors[lightIndex]; @@ -174,10 +160,11 @@ glm::vec4 Renderer::phong(HitPayload payload, int lightIndex) float cosVR = glm::max(0.0f, glm::dot(reflectionVector, eyeVector)); glm::vec3 color = - scene.kDiffuse * cosNL * lightColor + - scene.kSpecular * glm::pow(cosVR, scene.kShininess) * lightColor; + scene.params.kDiffuse * cosNL * lightColor + + scene.params.kSpecular * glm::pow(cosVR, scene.params.kShininess) * lightColor; - color *= scene.sphereAlbedos[payload.objectIndex]; + float attenuation = 1.0f / (1.0f + d * (scene.params.linearAtt + scene.params.quadraticAtt * d)); + color *= attenuation * scene.sphereAlbedos[payload.objectIndex]; return glm::vec4(color, 1.0f); } @@ -222,7 +209,7 @@ HitPayload Renderer::traceRayFromPixel(const Ray& ray) float a = glm::dot(direction, direction); float b = 2.0f * glm::dot(origin, direction); float c = glm::dot(origin, origin) - - 0.1f * 0.1f; + - scene.lightRadius * scene.lightRadius; float delta = b * b - 4.0f * a * c; if (delta < 0) @@ -315,7 +302,7 @@ HitPayload Renderer::closestHit(const Ray& ray, int sphereIndex, float hitDistan void Renderer::processKeyboard(int key, float deltaTime) { - camera->onUpdate(key, deltaTime); + camera->onKeyboardUpdate(key, deltaTime); } void Renderer::processMouse(glm::vec2 offset, float deltaTime) diff --git a/src/src/scene.cpp b/src/src/scene.cpp new file mode 100644 index 0000000..63c7ca9 --- /dev/null +++ b/src/src/scene.cpp @@ -0,0 +1,244 @@ +#include "scene.hpp" + + +void Scene::create() +{ + static std::vector colorPalette; + static std::vector lightColorPalette; + { + //colorPalette.push_back(glm::vec3(1,1,1)); + colorPalette.push_back(glm::vec3(155.0f / 255.0f, 34.0f / 255.0f, 38.0f / 255.0f)); + colorPalette.push_back(glm::vec3(0.0f / 255.0f, 18.0f / 255.0f, 25.0f / 255.0f)); + colorPalette.push_back(glm::vec3(0.0f / 255.0f, 95.0f / 255.0f, 115.0f / 255.0f)); + colorPalette.push_back(glm::vec3(10.0f / 255.0f, 147.0f / 255.0f, 150.0f / 255.0f)); + colorPalette.push_back(glm::vec3(148.0f / 255.0f, 210.0f / 255.0f, 189.0f / 255.0f)); + colorPalette.push_back(glm::vec3(233.0f / 255.0f, 216.0f / 255.0f, 166.0f / 255.0f)); + colorPalette.push_back(glm::vec3(238.0f / 255.0f, 155.0f / 255.0f, 0.0f / 255.0f)); + colorPalette.push_back(glm::vec3(202.0f / 255.0f, 103.0f / 255.0f, 2.0f / 255.0f)); + colorPalette.push_back(glm::vec3(187.0f / 255.0f, 62.0f / 255.0f, 3.0f / 255.0f)); + colorPalette.push_back(glm::vec3(174.0f / 255.0f, 32.0f / 255.0f, 18.0f / 255.0f)); + + //colorPalette.push_back(glm::vec3(128.0f / 255.0f, 93.0f / 255.0f, 147.0f / 255.0f)); + //colorPalette.push_back(glm::vec3(244.0f / 255.0f, 159.0f / 255.0f, 188.0f / 255.0f)); + //colorPalette.push_back(glm::vec3(255.0f / 255.0f, 211.0f / 255.0f, 186.0f / 255.0f)); + //colorPalette.push_back(glm::vec3(158.0f / 255.0f, 189.0f / 255.0f, 110.0f / 255.0f)); + //colorPalette.push_back(glm::vec3(22.0f / 255.0f, 152.0f / 255.0f, 115.0f / 255.0f)); + + lightColorPalette.push_back(glm::vec3(1.0f, 1.0f, 1.0f)); + lightColorPalette.push_back(glm::vec3(1.0f, 0.0f, 0.0f)); + lightColorPalette.push_back(glm::vec3(0.0f, 1.0f, 0.0f)); + lightColorPalette.push_back(glm::vec3(0.0f, 0.0f, 1.0f)); + lightColorPalette.push_back(glm::vec3(1.0f, 0.0f, 1.0f)); + lightColorPalette.push_back(glm::vec3(0.0f, 1.0f, 1.0f)); + lightColorPalette.push_back(glm::vec3(1.0f, 1.0f, 0.0f)); + lightColorPalette.push_back(glm::vec3(0.5f, 1.0f, 0.2f)); + lightColorPalette.push_back(glm::vec3(0.0f, 0.5f, 0.1f)); + lightColorPalette.push_back(glm::vec3(0.3f, 0.1f, 0.8f)); + } + + spherePositions = new glm::vec3[sphereCount]; + sphereRadii = new float[sphereCount]; + sphereAlbedos = new glm::vec3[sphereCount]; + + lightPositions = new glm::vec3[lightCount]; + lightColors = new glm::vec3[lightCount]; + lightBools = new bool[lightCount]; + + srand(time(NULL)); + for (int i = 0; i < sphereCount; i++) + { + // generate uniformly distributed points in a ball + glm::vec3 direction = glm::normalize(glm::gaussRand(glm::vec3(0.0f), glm::vec3(1.0f))); + float radius = glm::pow(glm::linearRand(0.0f, 1.0f), 1.0f / 3.0f) * params.worldBorder; + spherePositions[i] = radius * direction; + sphereRadii[i] = 0.2f * (i % 5 + 1); + sphereAlbedos[i] = colorPalette[i % colorPalette.size()]; + } + + for (int i = 0; i < lightCount; i++) + { + glm::vec3 direction = glm::normalize(glm::gaussRand(glm::vec3(0.0f), glm::vec3(1.0f))); + float radius = glm::pow(glm::linearRand(0.0f, 1.0f), 1.0f / 3.0f) * params.worldBorder; + lightPositions[i] = radius * direction; + lightColors[i] = lightColorPalette[i % lightColorPalette.size()]; + lightBools[i] = true; + } + + size_t sphereVec3ArrSize = sphereCount * sizeof(glm::vec3); + size_t sphereFloatArrSize = sphereCount * sizeof(float); + size_t lightVec3ArrSize = lightCount * sizeof(glm::vec3); + size_t lightBoolArrSize = lightCount * sizeof(bool); + + gpuErrchk(cudaMalloc(&cudaSpherePositions, sphereVec3ArrSize)); + gpuErrchk(cudaMalloc(&cudaSphereAlbedos, sphereVec3ArrSize)); + gpuErrchk(cudaMalloc(&cudaSphereRadii, sphereFloatArrSize)); + gpuErrchk(cudaMalloc(&cudaLightPositions, lightVec3ArrSize)); + gpuErrchk(cudaMalloc(&cudaLightColors, lightVec3ArrSize)); + gpuErrchk(cudaMalloc(&cudaLightBools, lightBoolArrSize)); + + gpuErrchk(cudaMemcpy(cudaSpherePositions, spherePositions, sphereVec3ArrSize, cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(cudaSphereAlbedos, sphereAlbedos, sphereVec3ArrSize, cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(cudaSphereRadii, sphereRadii, sphereFloatArrSize, cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(cudaLightPositions, lightPositions, lightVec3ArrSize, cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(cudaLightColors, lightColors, lightVec3ArrSize, cudaMemcpyHostToDevice)); + gpuErrchk(cudaMemcpy(cudaLightBools, lightBools, lightBoolArrSize, cudaMemcpyHostToDevice)); +} + +void Scene::free() +{ + delete[] spherePositions; + delete[] sphereRadii; + delete[] sphereAlbedos; + delete[] lightPositions; + delete[] lightColors; + delete[] lightBools; + + gpuErrchk(cudaFree(cudaSpherePositions)); + gpuErrchk(cudaFree(cudaSphereAlbedos)); + gpuErrchk(cudaFree(cudaSphereRadii)); + gpuErrchk(cudaFree(cudaLightPositions)); + gpuErrchk(cudaFree(cudaLightColors)); + gpuErrchk(cudaFree(cudaLightBools)); +} + +void Scene::updateScene(float deltaTime) +{ + lightPositions[0] = glm::vec3( + params.worldBorder * glm::sin(glfwGetTime()), + params.worldBorder * glm::cos(glfwGetTime()), + params.worldBorder * glm::sin(glfwGetTime()) * glm::cos(glfwGetTime()) + ); + + dirtyLightPos = true; +} + +void Scene::updateCuda() +{ + if (dirtyLightPos) + { + gpuErrchk(cudaMemcpy(cudaLightPositions, lightPositions, lightCount * sizeof(glm::vec3), cudaMemcpyHostToDevice)); + dirtyLightPos = false; + } + if (dirtyLightCol) + { + gpuErrchk(cudaMemcpy(cudaLightColors, lightColors, lightCount * sizeof(glm::vec3), cudaMemcpyHostToDevice)); + dirtyLightCol = false; + } + if (dirtyLightBools) + { + gpuErrchk(cudaMemcpy(cudaLightBools, lightBools, lightCount * sizeof(bool), cudaMemcpyHostToDevice)); + dirtyLightBools = false; + } + if (dirtySphereCol) + { + gpuErrchk(cudaMemcpy(cudaSphereAlbedos, sphereAlbedos, sphereCount * sizeof(glm::vec3), cudaMemcpyHostToDevice)); + dirtySphereCol = false; + + } +} + +void Scene::drawImGui() +{ + if (ImGui::CollapsingHeader("Information")) + { + ImGui::Text("Number of spheres: %d", sphereCount); + ImGui::Text("Number of light sources: %d", lightCount); + } + + if (ImGui::CollapsingHeader("Camera controls")) + { + ImGui::SeparatorText("Position"); + ImGui::BulletText("W - forward"); + ImGui::BulletText("S - backward"); + ImGui::BulletText("A - left"); + ImGui::BulletText("R - right"); + ImGui::BulletText("Space - up"); + ImGui::BulletText("LShift - down"); + + ImGui::SeparatorText("Angles"); + ImGui::BulletText("Q - look left"); + ImGui::BulletText("E - look right"); + ImGui::BulletText("1 - look up"); + ImGui::BulletText("3 - look down"); + + ImGui::SeparatorText("Misc"); + ImGui::BulletText("F - toggle mouse/keyboard"); + } + + if (ImGui::CollapsingHeader("Environment")) + { + ImGui::ColorEdit3("Sky color", glm::value_ptr(params.skyColor)); + ImGui::ColorEdit3("Ambient color", glm::value_ptr(params.ambientColor)); + } + + if (ImGui::CollapsingHeader("Sphere material")) + { + ImGui::SliderFloat("Diffuse", ¶ms.kDiffuse, 0.0f, 1.0f); + ImGui::SliderFloat("Specular", ¶ms.kSpecular, 0.0f, 1.0f); + ImGui::SliderFloat("Shininess", ¶ms.kShininess, 1.0f, 100.0f); + ImGui::SliderFloat("Ambient", ¶ms.kAmbient, 0.0f, 1.0f); + } + + if (ImGui::CollapsingHeader("Light sources")) + { + static int attenuationEnum = params.startAttIdx; + + ImGui::DragInt("Attenuation", &attenuationEnum, 0.1f, 0, 12); + + params.linearAtt = params.linearAttValues[attenuationEnum]; + params.quadraticAtt = params.quadraticAttValues[attenuationEnum]; + + if (ImGui::Button("Turn all lights on", ImVec2(150, 0))) + { + for (int i = 0; i < lightCount; i++) + lightBools[i] = true; + dirtyLightBools = true; + } + if (ImGui::Button("Turn all lights off", ImVec2(150, 0))) + { + for (int i = 0; i < lightCount; i++) + lightBools[i] = false; + dirtyLightBools = true; + } + + ImGuiWindowFlags window_flags = ImGuiWindowFlags_None; + + ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 5.0f); + ImGui::BeginChild("Child1", ImVec2(0, 600), ImGuiChildFlags_Border | ImGuiChildFlags_ResizeY, ImGuiWindowFlags_None); + if (ImGui::BeginMenuBar()) + { + if (ImGui::BeginMenu("Menu")) + { + ImGui::EndMenu(); + } + ImGui::EndMenuBar(); + } + if (ImGui::BeginTable("split1", 1, ImGuiTableFlags_Resizable | ImGuiTableFlags_NoSavedSettings)) + { + for (int i = 0; i < lightCount; ++i) + { + ImGui::TableNextColumn(); + + ImGui::SeparatorText(("Light " + std::to_string(i)).c_str()); + { + float border = params.worldBorder; + ImGui::PushID(i); + if (ImGui::DragFloat3("Position", glm::value_ptr(lightPositions[i]), 0.1f, -border - 5, border + 5)) + dirtyLightPos = true; + if (ImGui::ColorEdit3("Color", glm::value_ptr(lightColors[i]))) + dirtyLightCol = true; + + bool& on = lightBools[i]; + + if (ImGui::Checkbox(on ? "Turn off" : "Turn on", &on)) + dirtyLightBools = true; + } + } + + ImGui::EndTable(); + } + ImGui::EndChild(); + ImGui::PopStyleVar(); + + } +} \ No newline at end of file diff --git a/window.cpp b/src/src/window.cpp similarity index 73% rename from window.cpp rename to src/src/window.cpp index 13d3406..664488f 100644 --- a/window.cpp +++ b/src/src/window.cpp @@ -7,8 +7,8 @@ Window::Window(Application *parent) width = Application::WIDTH; height = Application::HEIGHT; - lastX = width / 2; - lastY = height / 2; + lastX = (float)width / 2; + lastY = (float)height / 2; glfwInit(); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); @@ -44,11 +44,6 @@ Window::Window(Application *parent) ImGuiIO& io = ImGui::GetIO(); io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; - ImGui_ImplGlfw_InitForOpenGL(wndptr, true); - ImGui_ImplOpenGL3_Init(); - - //glEnable(GL_MULTISAMPLE); - glfwSetWindowUserPointer(wndptr, this); glfwSetFramebufferSizeCallback(wndptr, [](GLFWwindow* window, int width, int height) @@ -62,28 +57,31 @@ Window::Window(Application *parent) glViewport(0, 0, width, height); }); - //glfwSetCursorPosCallback(wndptr, - // [](GLFWwindow* window, double xposIn, double yposIn) - // { - // Window& wnd = *(Window*)glfwGetWindowUserPointer(window); + glfwSetCursorPosCallback(wndptr, + [](GLFWwindow* window, double xposIn, double yposIn) + { + Window& wnd = *(Window*)glfwGetWindowUserPointer(window); + + float xpos = static_cast(xposIn); + float ypos = static_cast(yposIn); - // float xpos = static_cast(xposIn); - // float ypos = static_cast(yposIn); + if (wnd.firstMouse) + { + wnd.lastX = xpos; + wnd.lastY = ypos; + wnd.firstMouse = false; + } - // if (wnd.firstMouse) - // { - // wnd.lastX = xpos; - // wnd.lastY = ypos; - // wnd.firstMouse = false; - // } + float xoffset = xpos - wnd.lastX; + float yoffset = wnd.lastY - ypos; // reversed since y-coordinates go from bottom to top + wnd.lastX = xpos; + wnd.lastY = ypos; - // float xoffset = xpos - wnd.lastX; - // float yoffset = wnd.lastY - ypos; // reversed since y-coordinates go from bottom to top - // wnd.lastX = xpos; - // wnd.lastY = ypos; + wnd.app->processMouse(glm::vec2(xoffset, yoffset)); + }); - // wnd.app->processMouse(glm::vec2(xoffset, yoffset)); - // }); + ImGui_ImplGlfw_InitForOpenGL(wndptr, true); + ImGui_ImplOpenGL3_Init(); } diff --git a/utils.hpp b/utils.hpp deleted file mode 100644 index 46dbce1..0000000 --- a/utils.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#include "glm/glm.hpp" -