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"
-