Skip to content

Commit

Permalink
Merge pull request #5 from 3DevApps/opengl-support
Browse files Browse the repository at this point in the history
Opengl support
  • Loading branch information
wojciechloboda authored Apr 23, 2024
2 parents fb996d8 + a96cf5f commit cf82d89
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 13 deletions.
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;
delete [] infoLog;
}
}
87 changes: 87 additions & 0 deletions src/LocalRenderer/Window.cpp
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;
}

0 comments on commit cf82d89

Please sign in to comment.