Commit 3845a2b2 authored by Bastian Krayer's avatar Bastian Krayer

added gpu trace solution

parent 9a21859b
cmake_minimum_required(VERSION 2.8)
include(${CMAKE_MODULE_PATH}/DefaultExecutable.cmake)
\ No newline at end of file
#include "Material.h"
\ No newline at end of file
#ifndef GPU_TRACE_MATERIAL_H
#define GPU_TRACE_MATERIAL_H
#include <glm/glm.hpp>
struct Material {
glm::vec3 diffuse;
float kd;
glm::vec3 specular;
float ks;
float specExponent;
int mirror;
int p0, p1;
};
#endif
\ No newline at end of file
#include "Object.h"
\ No newline at end of file
#ifndef GPU_TRACE_OBJECT_H
#define GPU_TRACE_OBJECT_H
struct Object {
int type;
int matIndex;
int geoIndex;
};
#endif
\ No newline at end of file
#include "PointLight.h"
PointLight::PointLight(const glm::vec3& pos, const glm::vec3& col)
: pos(pos), col(col) {}
#ifndef GPU_TRACE_POINTLIGHT_H
#define GPU_TRACE_POINTLIGHT_H
#include <glm/glm.hpp>
struct PointLight {
glm::vec3 pos;
float px;
glm::vec3 col;
float py;
PointLight(const glm::vec3& pos, const glm::vec3& col);
};
#endif
\ No newline at end of file
#include "Sphere.h"
\ No newline at end of file
#ifndef GPU_TRACE_SPHERE_H
#define GPU_TRACE_SPHERE_H
#include <glm/glm.hpp>
struct Sphere {
glm::vec3 pos;
float r;
};
#endif
\ No newline at end of file
#include "Material.h"
#include "Object.h"
#include "PointLight.h"
#include "Sphere.h"
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <CVK_2/CVK_CompatibilityTools.h>
#include <CVK_2/CVK_ShaderSet.h>
#include <CVK_2/CVK_Trackball.h>
#include <memory>
#include <vector>
int width = 800;
int height = 800;
const int SPHERE_TYPE = 0;
int main() {
// Data for fullscreen quad
std::vector<glm::vec2> quadData = {{-1.0, -1.0}, {1.0, -1.0}, {-1.0, 1.0},
{-1.0, 1.0}, {1.0, -1.0}, {1.0, 1.0}};
// Init
glfwInit();
CVK::useOpenGL33CoreProfile();
GLFWwindow* window =
glfwCreateWindow(width, height, "GPU Raytracer", nullptr, nullptr);
glfwSetWindowPos(window, 600, 50);
glfwMakeContextCurrent(window);
if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
std::cout << "Failed to initialize OpenGL context" << std::endl;
return -1;
}
// compile a shader program
std::vector<std::string> shadernames = {
CVK::State::getInstance()->getShaderPath() +
"/GPUTraceSolution/simple.vert",
CVK::State::getInstance()->getShaderPath() +
"/GPUTraceSolution/trace.frag"};
std::unique_ptr<CVK::ShaderSet> shader = std::make_unique<CVK::ShaderSet>(
VERTEX_SHADER_BIT | FRAGMENT_SHADER_BIT, shadernames);
// VAO and VBO for fullscreen quad
GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
GLuint vbo;
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(glm::vec2) * quadData.size(),
quadData.data(), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, nullptr);
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Set Shader and get uniforms
shader->useProgram();
GLint pLoc = glGetUniformLocation(shader->getProgramID(), "P");
GLint vLoc = glGetUniformLocation(shader->getProgramID(), "V");
// trackball camera
CVK::Perspective proj(glm::radians(45.f), float(width) / float(height),
0.01f, 100.f);
CVK::Trackball cam(window, width, height, &proj);
cam.setRadius(20);
// Some materials
Material red = {
glm::vec3(1.0, 0.0, 0.0), // diffuse
0.9f, // kd
glm::vec3(1.0), // specular
0.9f, // ks
16.f, // specExponent
0 // mirror
};
Material green = {
glm::vec3(0.0, 1.0, 0.0), // diffuse
0.9f, // kd
glm::vec3(1.0), // specular
0.9f, // ks
16.f, // specExponent
0 // mirror
};
Material blue = {
glm::vec3(0.0, 0.0, 1.0), // diffuse
0.9f, // kd
glm::vec3(1.0), // specular
0.9f, // ks
16.f, // specExponent
0 // mirror
};
Material whiteMirror = {
glm::vec3(0.0, 0.0, 0.0), // diffuse
0.9f, // kd
glm::vec3(1.0), // specular
0.9f, // ks
16.f, // specExponent
1 // mirror
};
// Vector containing ssbo ids
std::vector<GLuint> ssbos(4);
glGenBuffers(4, ssbos.data());
// vectors containing scene data
std::vector<Object> objects;
std::vector<PointLight> pointlights;
std::vector<Material> mats;
std::vector<Sphere> spheres;
// Add some spheres
spheres.push_back({
glm::vec3(0, 0, 0), // pos
1.0f // radius
});
spheres.push_back({
glm::vec3(0, -101, 0), // pos
100.0f // radius
});
spheres.push_back({
glm::vec3(0, 5, -10), // pos
4.0f // radius
});
spheres.push_back({
glm::vec3(10, 3, 0), // pos
3.0f // radius
});
// Add materials
mats.push_back(red);
mats.push_back(green);
mats.push_back(whiteMirror);
// Add lights
pointlights.emplace_back(glm::vec3(0, 4, 4), glm::vec3(0.9));
pointlights.emplace_back(glm::vec3(7, 9, -4), glm::vec3(0.1, 0.7, 0.5));
// Add objects
objects.push_back({
SPHERE_TYPE, // type
0, // matIndex
0 // geoIndex
});
objects.push_back({
SPHERE_TYPE, // type
1, // matIndex
1 // geoIndex
});
objects.push_back({
SPHERE_TYPE, // type
2, // matIndex
2 // geoIndex
});
objects.push_back({
SPHERE_TYPE, // type
0, // matIndex
3 // geoIndex
});
// Bind and upload data for buffers
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbos[0]);
glBufferData(GL_SHADER_STORAGE_BUFFER, objects.size() * sizeof(Object),
objects.data(), GL_STATIC_COPY);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbos[0]);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbos[1]);
glBufferData(GL_SHADER_STORAGE_BUFFER, mats.size() * sizeof(Material),
mats.data(), GL_STATIC_COPY);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ssbos[1]);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbos[2]);
glBufferData(GL_SHADER_STORAGE_BUFFER,
pointlights.size() * sizeof(PointLight), pointlights.data(),
GL_STATIC_COPY);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, ssbos[2]);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbos[3]);
glBufferData(GL_SHADER_STORAGE_BUFFER, spheres.size() * sizeof(Sphere),
spheres.data(), GL_STATIC_COPY);
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 3, ssbos[3]);
glBindBuffer(GL_SHADER_STORAGE_BUFFER, 3);
double lastTime = glfwGetTime();
double deltaTime = 0, nowTime = 0;
while (!glfwWindowShouldClose(window) &&
glfwGetKey(window, GLFW_KEY_Q) != GLFW_PRESS) {
nowTime = glfwGetTime();
deltaTime = nowTime - lastTime;
lastTime = nowTime;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
cam.update(deltaTime);
glUniformMatrix4fv(pLoc, 1, GL_FALSE,
glm::value_ptr(cam.getProjection().getProjMatrix()));
glUniformMatrix4fv(vLoc, 1, GL_FALSE, glm::value_ptr(cam.getView()));
glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteBuffers(1, &vao);
glDeleteVertexArrays(1, &vao);
glfwDestroyWindow(window);
glfwTerminate();
return 0;
}
......@@ -84,7 +84,7 @@ bool intersectSphere(Sphere s, vec3 from, vec3 dir, out float t) {
float discr = loc * loc - dot(oc, oc) + s.r * s.r;
if (discr < 0.0)
return false;
return false;
float tIn, tOut;
if (abs(discr) < 0.00001) {
......@@ -163,12 +163,11 @@ vec3 shade(vec3 p, vec3 V, vec3 N, Material mat) {
vec3 lcol = vec3(0.0);
float dotLN = dot(L, N);
lcol += dotLN * mat.diffuse * mat.kd;
;
vec3 R = reflect(-L, N);
lcol += pow(max(dot(R, V), 0.0), mat.specExponent) * mat.specular *
mat.ks * float(dotLN > 0.0);
mat.ks * float(dotLN > 0.0);
col += pl.col * lcol * shadow;
}
......
#version 330 core
layout(location = 0) in vec4 position;
out vec2 px;
void main() {
gl_Position = position;
px = position.xy;
}
\ No newline at end of file
#version 430
out vec4 fragmentColor;
// View and projection
uniform mat4 V;
uniform mat4 P;
// pixel in [-1,1]
in vec2 px;
const float INFINITY = 1E+37;
struct PointLight {
vec3 pos;
vec3 col;
};
// matindex is the index into the materials buffer
// geoindex is the index into the geometry buffer for the given type, i.e.
// Sphere
struct Object {
int type;
int matIndex;
int geoIndex;
};
struct Material {
vec3 diffuse;
float kd;
vec3 specular;
float ks;
float specExponent;
// 1, if mirror, 0 otherwise
int mirror;
};
// Identifier for sphere geometry
const int SPHERE_TYPE = 0;
struct Sphere {
vec3 pos;
float r;
};
// SSBOs
layout(std430, binding = 0) readonly buffer objects_ssbo { Object objects[]; };
layout(std430, binding = 1) readonly buffer material_ssbo {
Material materials[];
};
layout(std430, binding = 2) readonly buffer pointlights_ssbo {
PointLight pointlights[];
};
layout(std430, binding = 3) readonly buffer spheres_ssbo { Sphere spheres[]; };
// Generates a camera ray from pixels in NDS and View and Model matrices
void getCameraRay(in vec2 pxNDS, out vec3 from, out vec3 dir) {
mat4 PInv = inverse(P);
mat4 VInv = inverse(V);
vec3 pointNDS = vec3(pxNDS, -1.0);
vec4 pointNDSH = vec4(pointNDS, 1.0);
vec4 dirEye = PInv * pointNDSH;
dirEye.w = 0.0;
vec3 dirWorld = (VInv * dirEye).xyz;
from = VInv[3].xyz;
dir = normalize(dirWorld);
}
// Computes the normal on a sphere at a point
vec3 normalSphere(Sphere s, vec3 p) { return normalize(p - s.pos); }
// Computes the normal for some object
vec3 normal(int objIndex, vec3 p) {
Object o = objects[objIndex];
if (o.type == SPHERE_TYPE) {
return normalSphere(spheres[o.geoIndex], p);
}
return vec3(0.0);
}
// Intersection for sphere
bool intersectSphere(Sphere s, vec3 from, vec3 dir, out float t) {
vec3 oc = from - s.pos;
float loc = dot(dir, oc);
float discr = loc * loc - dot(oc, oc) + s.r * s.r;
if (discr < 0.0)
return false;
float tIn, tOut;
if (abs(discr) < 0.00001) {
tIn = -loc;
tOut = tIn;
} else {
float sq = sqrt(discr);
tIn = -loc - sq;
tOut = -loc + sq;
}
t = tIn >= 0.0 ? tIn : tOut;
return t >= 0.0;
}
// General closest intersection
bool closestIntersection(vec3 from, vec3 dir, out float t, out int id) {
float minT = INFINITY;
int minObj = -1;
for (int i = 0; i < objects.length(); i++) {
Object o = objects[i];
float ot = INFINITY;
if (o.type == SPHERE_TYPE) {
if (!intersectSphere(spheres[o.geoIndex], from, dir, ot)) {
continue;
}
}
if (ot < minT) {
minT = ot;
minObj = i;
}
}
id = minObj;
t = minT;
return minObj >= 0;
}
// Shadow test
float shadow(vec3 from, vec3 dir, float maxT) {
for (int i = 0; i < objects.length(); i++) {
Object o = objects[i];
float ot;
if (o.type == SPHERE_TYPE) {
if (!intersectSphere(spheres[o.geoIndex], from, dir, ot)) {
continue;
}
}
if (ot < maxT) {
return 0.0;
}
}
return 1.0;
}
// Simple shading
vec3 shade(vec3 p, vec3 V, vec3 N, Material mat) {
vec3 col = vec3(0.0);
for (int i = 0; i < pointlights.length(); i++) {
PointLight pl = pointlights[i];
vec3 poffset = p + 0.001 * N;
vec3 l = pl.pos - poffset;
float ll = length(l);
vec3 L = l / ll;
float shadow = shadow(poffset, L, ll);
vec3 lcol = vec3(0.0);
float dotLN = dot(L, N);
lcol += dotLN * mat.diffuse * mat.kd;
;
vec3 R = reflect(-L, N);
lcol += pow(max(dot(R, V), 0.0), mat.specExponent) * mat.specular *
mat.ks * float(dotLN > 0.0);
col += pl.col * lcol * shadow;
}
return col;
}
// Trace a ray through the scene
vec3 trace(vec3 from, vec3 dir, int maxIt) {
float t = INFINITY;
int id = -1;
vec3 mirrorColor = vec3(1.0);
for (int i = 0; i < maxIt; i++) {
int idtemp = -1;
float ttemp = INFINITY;
if (!closestIntersection(from, dir, ttemp, idtemp)) {
return mirrorColor * vec3(0.3, 0.2, 0.8);
}
vec3 p = from + ttemp * dir;
Object o = objects[idtemp];
Material mat = materials[o.matIndex];
vec3 N = normal(idtemp, p);
if (mat.mirror == 0) {
id = idtemp;
t = ttemp;
break;
}
from = p + 0.001 * N;
dir = reflect(dir, N);
mirrorColor *= mat.specular * mat.ks;
}
vec3 p = from + t * dir;
vec3 N = normal(id, p);
Material mat = materials[objects[id].matIndex];
return mirrorColor * shade(p, -dir, N, mat);
}
void main() {
vec3 from = vec3(0.0);
vec3 dir = vec3(0.0, 0.0, 1.0);
getCameraRay(px, from, dir);
vec3 col = trace(from, dir, 5);
fragmentColor = vec4(col, 1.0);
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment