mirror of
https://github.com/MartinOpat/cuda-based-raytrace.git
synced 2025-06-07 02:13:10 +02:00
feat (wip): real-time gui with rendering in opengl
This commit is contained in:
13
src/illumination/FrameBuffer.cu
Normal file
13
src/illumination/FrameBuffer.cu
Normal file
@@ -0,0 +1,13 @@
|
||||
#include "FrameBuffer.h"
|
||||
#include "linalg/linalg.h"
|
||||
|
||||
|
||||
__host__ FrameBuffer::FrameBuffer(unsigned int w, unsigned int h) : w(w), h(h) {}
|
||||
|
||||
|
||||
__device__ void FrameBuffer::writePixel(int x, int y, float r, float g, float b) {
|
||||
int i = y * this->w + x;
|
||||
|
||||
// the opengl buffer uses BGRA format; dunno why
|
||||
this->buffer[i] = packUnorm4x8(b, g, r, 1.0f);
|
||||
}
|
||||
20
src/illumination/FrameBuffer.h
Normal file
20
src/illumination/FrameBuffer.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef FRAMEBUFFER_H
|
||||
#define FRAMEBUFFER_H
|
||||
|
||||
#include "cuda_runtime.h"
|
||||
#include "linalg/linalg.h"
|
||||
#include <cstdint>
|
||||
|
||||
|
||||
class FrameBuffer {
|
||||
public:
|
||||
uint32_t* buffer;
|
||||
std::size_t buffer_size;
|
||||
unsigned int w;
|
||||
unsigned int h;
|
||||
|
||||
__host__ FrameBuffer(unsigned int w, unsigned int h);
|
||||
__device__ void writePixel(int x, int y, float r, float g, float b);
|
||||
};
|
||||
|
||||
#endif // FRAMEBUFFER_H
|
||||
@@ -1,14 +1,16 @@
|
||||
#ifndef RAYCASTER_H
|
||||
#define RAYCASTER_H
|
||||
#include "Raycaster.h"
|
||||
|
||||
#include "cuda_runtime.h"
|
||||
#include "device_launch_parameters.h"
|
||||
|
||||
#include <cuda_runtime.h>
|
||||
#include "linalg/linalg.h"
|
||||
#include "consts.h"
|
||||
#include "shading.h"
|
||||
#include <iostream>
|
||||
#include "objs/sphere.h"
|
||||
|
||||
|
||||
// Raycast + phong, TODO: Consider wrapping in a class
|
||||
__global__ void raycastKernel(float* volumeData, unsigned char* framebuffer) {
|
||||
__global__ void raycastKernel(float* volumeData, FrameBuffer framebuffer) {
|
||||
int px = blockIdx.x * blockDim.x + threadIdx.x;
|
||||
int py = blockIdx.y * blockDim.y + threadIdx.y;
|
||||
if (px >= IMAGE_WIDTH || py >= IMAGE_HEIGHT) return;
|
||||
@@ -117,10 +119,109 @@ __global__ void raycastKernel(float* volumeData, unsigned char* framebuffer) {
|
||||
accumB /= (float)SAMPLES_PER_PIXEL;
|
||||
|
||||
// Final colour
|
||||
int fbIndex = (py * IMAGE_WIDTH + px) * 3;
|
||||
framebuffer[fbIndex + 0] = (unsigned char)(fminf(accumR, 1.f) * 255);
|
||||
framebuffer[fbIndex + 1] = (unsigned char)(fminf(accumG, 1.f) * 255);
|
||||
framebuffer[fbIndex + 2] = (unsigned char)(fminf(accumB, 1.f) * 255);
|
||||
framebuffer.writePixel(px, py, accumR, accumG, accumB);
|
||||
// int fbIndex = (py * IMAGE_WIDTH + px) * 3;
|
||||
// framebuffer[fbIndex + 0] = (unsigned char)(fminf(accumR, 1.f) * 255);
|
||||
// framebuffer[fbIndex + 1] = (unsigned char)(fminf(accumG, 1.f) * 255);
|
||||
// framebuffer[fbIndex + 2] = (unsigned char)(fminf(accumB, 1.f) * 255);
|
||||
}
|
||||
|
||||
#endif // RAYCASTER_H
|
||||
|
||||
Raycaster::Raycaster(cudaGraphicsResource_t resources, int w, int h) {
|
||||
this->resources = resources;
|
||||
this->w = h;
|
||||
this->w = h;
|
||||
|
||||
this->fb = new FrameBuffer(w, h);
|
||||
|
||||
// camera_info = CameraInfo(Vec3(0.0f, 0.0f, 0.0f), Vec3(0.0f, 0.0f, 0.0f), 90.0f, (float) w, (float) h);
|
||||
// d_camera = thrust::device_new<Camera*>();
|
||||
|
||||
int res = cudaDeviceSynchronize();
|
||||
if (res) {
|
||||
std::cout << "CUDA error while synchronizing device: " << res;
|
||||
cudaDeviceReset();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
res = cudaDeviceSynchronize();
|
||||
if (res) {
|
||||
std::cout << "CUDA error while synchronizing device: " << res;
|
||||
cudaDeviceReset();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Raycaster::render() {
|
||||
int res = cudaGraphicsMapresources(1, this->resources);
|
||||
if (res) {
|
||||
std::cout << "CUDA error while mapping graphic resource: " << res;
|
||||
cudaDeviceReset();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// check_cuda_errors(cudaGraphicsResourceGetMappedPointer((void**)&(frame_buffer->device_ptr), &(frame_buffer->buffer_size), resources));
|
||||
res = cudaGraphicsResourceGetMappedPointer((void**)(this->fb->buffer), &this->fb->buffer_size, this->resources);
|
||||
if (res) {
|
||||
std::cout << "CUDA error while fetching resource pointer: " << res;
|
||||
cudaDeviceReset();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// FIXME: might not be the best parallelization configuraiton
|
||||
int tx = 32;
|
||||
int ty = 32;
|
||||
|
||||
dim3 blocks(this->w / tx + 1, this->h / ty + 1);
|
||||
dim3 threads(tx, ty);
|
||||
|
||||
// TODO: pass camera info at some point
|
||||
// TODO: pass float volume data.
|
||||
// frame buffer is implicitly copied to the device each frame
|
||||
raycastKernel<<<blocks, threads>>> (nullptr, this->fb);
|
||||
|
||||
res = cudaGetLastError();
|
||||
if (res) {
|
||||
std::cout << "CUDA error while raycasting: " << res;
|
||||
cudaDeviceReset();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
res = cudaDeviceSynchronize();
|
||||
if (res) {
|
||||
std::cout << "CUDA error while synchronizing device: " << res;
|
||||
cudaDeviceReset();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
res = cudaGraphicsUnmapResources(1, &this->resources);
|
||||
if (res) {
|
||||
std::cout << "CUDA error while unmapping a resource: " << res;
|
||||
cudaDeviceReset();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Raycaster::resize(int w, int h) {
|
||||
this->w = w;
|
||||
this->h = h;
|
||||
|
||||
delete fb;
|
||||
this->fb = new FrameBuffer(w, h);
|
||||
|
||||
// TODO: should be globals probably
|
||||
int tx = 8;
|
||||
int ty = 8;
|
||||
|
||||
dim3 blocks(w / tx + 1, h / ty + 1);
|
||||
dim3 threads(tx, ty);
|
||||
|
||||
int res = cudaDeviceSynchronize();
|
||||
if (res != 0) {
|
||||
std::cout << "CUDA error while synchronizing device: " << res;
|
||||
cudaDeviceReset();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
33
src/illumination/Raycaster.h
Normal file
33
src/illumination/Raycaster.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef RAYCASTER_H
|
||||
#define RAYCASTER_H
|
||||
|
||||
// #include "Camera.h"
|
||||
#include "cuda_runtime.h"
|
||||
#include "FrameBuffer.h"
|
||||
#include "linalg/linalg.h"
|
||||
|
||||
// #include <thrust/device_ptr.h>
|
||||
|
||||
__global__ void raycastKernel(float* volumeData, unsigned char* framebuffer);
|
||||
|
||||
struct Raycaster {
|
||||
|
||||
// thrust::device_ptr<Camera*> d_camera;
|
||||
// CameraInfo camera_info;
|
||||
|
||||
cudaGraphicsResource_t resources;
|
||||
FrameBuffer* fb;
|
||||
|
||||
int w;
|
||||
int h;
|
||||
|
||||
Raycaster() {};
|
||||
Raycaster(cudaGraphicsResource_t resources, int nx, int ny);
|
||||
// ~Raycaster();
|
||||
|
||||
void set_camera(Vec3 position, Vec3 forward, Vec3 up);
|
||||
void render();
|
||||
void resize(int nx, int ny);
|
||||
// void raycastKernel(float* volumeData, unsigned char* framebuffer); // TODO: proper framebuffer class
|
||||
};
|
||||
#endif // RAYCASTER_H
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef ILLUMINATION_H
|
||||
#define ILLUMINATION_H
|
||||
|
||||
#include "raycaster.h"
|
||||
#include "Raycaster.h"
|
||||
#include "shading.h"
|
||||
|
||||
#endif // ILLUMINATION_H
|
||||
#endif // ILLUMINATION_H
|
||||
|
||||
14
src/illumination/shading.cu
Normal file
14
src/illumination/shading.cu
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "shading.h"
|
||||
|
||||
// TODO: Consider wrapping this in a class (?)
|
||||
__device__ Vec3 phongShading(const Vec3& normal, const Vec3& lightDir, const Vec3& viewDir, const Vec3& baseColor) {
|
||||
Vec3 ambient = baseColor * ambientStrength;
|
||||
double diff = fmax(normal.dot(lightDir), 0.0);
|
||||
Vec3 diffuse = baseColor * (diffuseStrength * diff);
|
||||
|
||||
Vec3 reflectDir = (normal * (2.0 * normal.dot(lightDir)) - lightDir).normalize();
|
||||
double spec = pow(fmax(viewDir.dot(reflectDir), 0.0), shininess);
|
||||
Vec3 specular = Vec3::init(1.0, 1.0, 1.0) * (specularStrength * spec);
|
||||
|
||||
return ambient + diffuse + specular;
|
||||
};
|
||||
@@ -4,17 +4,7 @@
|
||||
#include "linalg/linalg.h"
|
||||
#include "consts.h"
|
||||
|
||||
// TODO: Consider wrapping this in a class (?)
|
||||
__device__ Vec3 phongShading(const Vec3& normal, const Vec3& lightDir, const Vec3& viewDir, const Vec3& baseColor) {
|
||||
Vec3 ambient = baseColor * ambientStrength;
|
||||
double diff = fmax(normal.dot(lightDir), 0.0);
|
||||
Vec3 diffuse = baseColor * (diffuseStrength * diff);
|
||||
__device__ Vec3 phongShading(const Vec3& normal, const Vec3& lightDir, const Vec3& viewDir, const Vec3& baseColor);
|
||||
|
||||
Vec3 reflectDir = (normal * (2.0 * normal.dot(lightDir)) - lightDir).normalize();
|
||||
double spec = pow(fmax(viewDir.dot(reflectDir), 0.0), shininess);
|
||||
Vec3 specular = Vec3::init(1.0, 1.0, 1.0) * (specularStrength * spec);
|
||||
|
||||
return ambient + diffuse + specular;
|
||||
}
|
||||
|
||||
#endif // SHADING_H
|
||||
#endif // SHADING_H
|
||||
|
||||
Reference in New Issue
Block a user