Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Opengl support #5

Merged
merged 7 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ find_package(OpenGL REQUIRED)
find_package(GLEW REQUIRED)
find_package(assimp REQUIRED)

file(GLOB SOURCES "src/*.cpp" "src/*.cu")

add_executable(cuda_project src/main.cu)
file(GLOB_RECURSE SOURCES CONFIGURE_DEPENDS "src/*.cpp" "src/*.cu")
add_executable(cuda_project ${SOURCES})

target_link_libraries(cuda_project PRIVATE glfw OpenGL::GL GLEW::GLEW assimp::assimp)
23 changes: 23 additions & 0 deletions src/LocalRenderer/Renderer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

#include "Renderer.h"
#include "Utils.h"

Renderer::Renderer(Window& window)
: window_(window)
, width_(window.getWidth())
, height_(window.getHeight()) {

CheckedGLCall(glGenTextures(1, &texId_));
CheckedGLCall(glGenFramebuffers(1, &fboId_));
}

void Renderer::renderFrame(const uint8_t *frame) {
CheckedGLCall(glBindTexture(GL_TEXTURE_2D, texId_));
CheckedGLCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width_, height_, 0, GL_RGB, GL_UNSIGNED_BYTE, frame));

CheckedGLCall(glBindFramebuffer(GL_READ_FRAMEBUFFER, fboId_));
CheckedGLCall(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId_, 0));

CheckedGLCall(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0));
CheckedGLCall(glBlitFramebuffer(0, 0, width_, height_, 0, 0, width_, height_, GL_COLOR_BUFFER_BIT, GL_NEAREST));
}
21 changes: 21 additions & 0 deletions src/LocalRenderer/Renderer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#pragma once

#include <memory>
#include <ctime>
#include <vector>
#include "Window.h"
#include <GL/glew.h>
#include <GLFW/glfw3.h>

class Renderer {
public:
Renderer(Window& window);
~Renderer() = default;
void renderFrame(const uint8_t *frame);
private:
Window& window_;
std::uint32_t width_;
std::uint32_t height_;
GLuint fboId_;
GLuint texId_;
};
35 changes: 35 additions & 0 deletions src/LocalRenderer/Utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

#pragma once
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <string>

#define CheckedGLCall(x) do { printOpenGLErrors(">>BEFORE<< "#x, __FILE__, __LINE__); (x); printOpenGLErrors(#x, __FILE__, __LINE__); } while (0)
#define CheckedGLResult(x) (x); printOpenGLErrors(#x, __FILE__, __LINE__);
#define CheckExistingErrors(x) printOpenGLErrors(">>BEFORE<< "#x, __FILE__, __LINE__);

void printOpenGLErrors(char const * const function, char const * const file, int const line) {
bool succeeded = true;
GLenum error = glGetError();
if (error != GL_NO_ERROR) {
char const *errorString = (char const *) gluErrorString(error);
throw std::runtime_error(
"OpenGL Error in " + std::string(file) +
" at line" + std::to_string(line) +
" calling function " + std::string(function) +
": " + std::string(errorString));
}
}

void printShaderInfoLog(GLint const shader) {
int infoLogLength = 0;
int charsWritten = 0;
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLogLength);
if (infoLogLength > 0) {
GLchar * infoLog = new GLchar[infoLogLength];
glGetShaderInfoLog(shader, infoLogLength, &charsWritten, infoLog);
std::cout << "Shader Info Log:" << std::endl << infoLog << std::endl;
pklatka marked this conversation as resolved.
Show resolved Hide resolved
delete [] infoLog;
}
}
87 changes: 87 additions & 0 deletions src/LocalRenderer/Window.cpp
wojciechloboda marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include "Window.h"
#include <stdexcept>
#include <cstdio>

const std::unordered_map<MouseButton, int> mouseButtonToGlfwButton = {
{ MouseButton::Left, GLFW_MOUSE_BUTTON_LEFT },
{ MouseButton::Right, GLFW_MOUSE_BUTTON_RIGHT },
{ MouseButton::Middle, GLFW_MOUSE_BUTTON_MIDDLE },
};

Window::Window(std::uint32_t width, std::uint32_t height, const std::string& title)
: window_(nullptr, glfwDestroyWindow)
, width_(width)
, height_(height) {

if (!glfwInit()) {
throw std::runtime_error("glfwInit() failed");
}
// glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE);
window_.reset(glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr));
if (!window_.get()) {
throw std::runtime_error("Failed to create GLFW window!");
}

glfwMakeContextCurrent(window_.get());
glfwSetWindowUserPointer(window_.get(), this);
glfwSetScrollCallback(window_.get(), scrollCallback);

GLenum glew_status = glewInit();

// GLEW_ERROR_NO_GLX_DISPLAY occurs when running the program on a WSL system.
// This error is not critical and can be ignored.
if (glew_status != GLEW_OK && glew_status != GLEW_ERROR_NO_GLX_DISPLAY) {
fprintf(stderr, "Error: %s\n", glewGetErrorString(glew_status));
throw std::runtime_error("Failed to init GLEW");
}
}

Window::~Window() {
glfwTerminate();
}

std::uint32_t Window::getWidth() const {
return width_;
}

std::uint32_t Window::getHeight() const {
return height_;
}

void Window::pollEvents() {
glfwPollEvents();
}

bool Window::shouldClose() const {
return glfwWindowShouldClose(window_.get());
}

bool Window::getMouseButton(MouseButton button) const {
auto b = mouseButtonToGlfwButton.find(button);
return glfwGetMouseButton(window_.get(), b->second) == GLFW_PRESS;
}

void Window::getMousePos(int& x, int& y) const {
double xpos, ypos;
glfwGetCursorPos(window_.get(), &xpos, &ypos);
x = static_cast<int>(xpos);
y = static_cast<int>(ypos);
}

void Window::setMousePos(int x, int y) const {
glfwSetCursorPos(window_.get(), (double)x, (double)y);
}

void Window::swapBuffers() {
glfwSwapBuffers(window_.get());
}

void Window::scrollCallback(GLFWwindow* window, double xoffset, double yoffset) {
Window* this_window = (Window*)glfwGetWindowUserPointer(window);
for (auto callback : this_window->scroll_callbacks_)
{
callback(yoffset);
}
}
42 changes: 42 additions & 0 deletions src/LocalRenderer/Window.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <cstdint>
#include <memory>
#include <vector>
#include <functional>
#include <string>

enum class MouseButton {
Left,
Right,
Middle,
};


class Window {
public:
Window(Window const&) = delete;
Window& operator=(Window const&) = delete;

Window(std::uint32_t width, std::uint32_t height, const std::string& title);
~Window();

void getMousePos(int& x, int& y) const;
void setMousePos(int x, int y) const;
void pollEvents();
bool shouldClose() const;
void swapBuffers();
void addScrollCallback(std::function<void(float)> callback) { scroll_callbacks_.push_back(callback); }
std::uint32_t getWidth() const;
std::uint32_t getHeight() const;
bool getMouseButton(MouseButton button) const;

private:
static void scrollCallback(GLFWwindow* window, double xoffset, double yoffset);
std::unique_ptr<GLFWwindow, void(*)(GLFWwindow*)> window_;
std::vector<std::function<void(float)>> scroll_callbacks_;
std::uint32_t width_ = 0u;
std::uint32_t height_ = 0u;
};
34 changes: 24 additions & 10 deletions src/main.cu
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <stdio.h>
#include <iostream>
#include <float.h>
Expand All @@ -13,6 +15,8 @@
#include "obj_loader.h"
#include "object3d.h"
#include "triangle.h"
#include "LocalRenderer/Window.h"
#include "LocalRenderer/Renderer.h"

#define checkCudaErrors(val) check_cuda( (val), #val, __FILE__, __LINE__ )
void check_cuda(cudaError_t result, char const *const func, const char *const file, int const line) {
Expand Down Expand Up @@ -62,7 +66,7 @@ __global__ void render_init(int nx, int ny, curandState *rand_state) {
* @param world An array of hitable pointers representing the scene.
* @param rand_state The random state for each thread.
*/
__global__ void render(float3 *fb, int max_x, int max_y,int sample_per_pixel, camera **cam,hitable **world, curandState *rand_state) {
__global__ void render(uint8_t *fb, int max_x, int max_y,int sample_per_pixel, camera **cam,hitable **world, curandState *rand_state) {
int i = threadIdx.x + blockIdx.x * blockDim.x;
int j = threadIdx.y + blockIdx.y * blockDim.y;
if((i >= max_x) || (j >= max_y)) return;
Expand All @@ -76,8 +80,10 @@ __global__ void render(float3 *fb, int max_x, int max_y,int sample_per_pixel, ca
ray r = (*cam)->get_ray(u, v);
col += (*cam)->ray_color(r, world, &local_rand_state);
}

fb[pixel_index] = col/float(sample_per_pixel); //average color of samples
int3 color = make_int3(255.99 * col/float(sample_per_pixel)); //average color of samples
fb[3 * pixel_index] = color.x;
fb[3 * pixel_index + 1] = color.y;
fb[3 * pixel_index + 2] = color.z;
}

/**
Expand Down Expand Up @@ -141,15 +147,14 @@ int main()
float aspect_ratio = float(nx) / float(ny);

int num_pixels = nx*ny;
size_t fb_size = num_pixels*sizeof(float3);

dim3 blocks(nx/tx+1,ny/ty+1);
dim3 threads(tx,ty);
size_t fb_size = num_pixels*sizeof(uint8_t) * 3;

curandState *d_rand_state;
checkCudaErrors(cudaMalloc((void **)&d_rand_state, num_pixels*sizeof(curandState)));
// allocate FB
float3 *fb;
uint8_t *fb;
checkCudaErrors(cudaMallocManaged((void **)&fb, fb_size));

//create_world
Expand Down Expand Up @@ -218,13 +223,22 @@ int main()
myfile << "P3\n" << nx << " " << ny << "\n255\n";
for (int j = ny-1; j >= 0; j--) {
for (int i = 0; i < nx; i++) {
size_t pixel_index = j*nx + i;
int3 color = make_int3(255.99*fb[pixel_index].x, 255.99*fb[pixel_index].y, 255.99*fb[pixel_index].z);
myfile << color.x << " " << color.y << " " << color.z << "\n";
size_t pixel_index = 3 * (j*nx + i);
myfile << fb[pixel_index] << " " << fb[pixel_index + 1] << " " << fb[pixel_index + 2] << "\n";
}
}
myfile.close();
checkCudaErrors(cudaFree(fb));

Window window(nx, ny, "MultiGPU-PathTracer");
Renderer renderer(window);

while (!window.shouldClose()) {
window.pollEvents();
renderer.renderFrame(fb);
window.swapBuffers();

}

checkCudaErrors(cudaFree(fb));
return 0;
}