Skip to content
Snippets Groups Projects
Commit 8b9c6360 authored by Susanne Dötsch's avatar Susanne Dötsch
Browse files

[94] Added comments and explanations

Added some comments and renamed variables and functions to be more specific or in line with our conventions
parent 75217dfb
No related branches found
No related tags found
1 merge request!77Resolve "SAF-R Module"
Pipeline #26658 passed
...@@ -10,13 +10,18 @@ ...@@ -10,13 +10,18 @@
#include <vector> #include <vector>
#include <string.h> // memcpy(3) #include <string.h> // memcpy(3)
/*
* Light struct with a position and intensity of the light source
*/
struct Light { struct Light {
Light(const glm::vec3 &p, const float &i) : position(p), intensity(i) {} Light(const glm::vec3 &p, const float &i) : position(p), intensity(i) {}
glm::vec3 position; glm::vec3 position;
float intensity; float intensity;
}; };
/*
* Material struct with defuse color, albedo and specular component
*/
struct Material { struct Material {
Material(const glm::vec3 &a, const glm::vec3 &color, const float &spec) : albedo(a), diffuse_color(color), specular_exponent(spec) {} Material(const glm::vec3 &a, const glm::vec3 &color, const float &spec) : albedo(a), diffuse_color(color), specular_exponent(spec) {}
Material() : albedo(1,0, 0), diffuse_color(), specular_exponent() {} Material() : albedo(1,0, 0), diffuse_color(), specular_exponent() {}
...@@ -25,6 +30,15 @@ struct Material { ...@@ -25,6 +30,15 @@ struct Material {
float specular_exponent; float specular_exponent;
}; };
/*
* the sphere is defined by it's center, the radius and the material
*
* the ray_intersect function checks, if a ray from the raytracer passes through the sphere, hits the sphere or passes by the the sphere
* @param vec3: origin of ray
* @param vec3: direction of ray
* @param float: distance of the ray to the sphere
* @return bool: if ray interesects sphere or not
*/
struct Sphere { struct Sphere {
glm::vec3 center; glm::vec3 center;
float radius; float radius;
...@@ -46,58 +60,95 @@ struct Sphere { ...@@ -46,58 +60,95 @@ struct Sphere {
} }
}; };
glm::vec3 reflect(const glm::vec3 &I, const glm::vec3 &N) { /*
return I - N*2.f*(glm::dot(I,N)); * @param vec3 dir: direction of the ray
* @param vec3 hit_center: normalized vector between hit on the sphere and center of the sphere
* @return vec3: returns reflected vector for the new direction of the ray
*/
glm::vec3 reflect(const glm::vec3 &dir, const glm::vec3 & hit_center) {
return dir - hit_center*2.f*(glm::dot(dir, hit_center));
} }
bool scene_intersect(const glm::vec3 &orig, const glm::vec3 &dir, const std::vector<Sphere> &spheres, glm::vec3 &hit, glm::vec3 &N, Material &material) { /*
* @param orig: Origin of the ray
* @param dir: direction of the ray
* @param vector: vector of all spheres in the scene
* @param vec3 hit: returns the vector from the origin of the ray to the closest sphere
* @param vec3 N: normalizes the vector from the origin of the ray to the closest sphere center
* @param Material: returns the material of the closest sphere
* @return: closest sphere distance if it's < 1000
*/
bool sceneIntersect(const glm::vec3 &orig, const glm::vec3 &dir, const std::vector<Sphere> &spheres,
glm::vec3 &hit, glm::vec3 &hit_center, Material &material) {
float spheres_dist = std::numeric_limits<float>::max(); float spheres_dist = std::numeric_limits<float>::max();
for (size_t i=0; i < spheres.size(); i++) { for (size_t i=0; i < spheres.size(); i++) {
float dist_i; float dist_i;
if (spheres[i].ray_intersect(orig, dir, dist_i) && dist_i < spheres_dist) { if (spheres[i].ray_intersect(orig, dir, dist_i) && dist_i < spheres_dist) {
spheres_dist = dist_i; spheres_dist = dist_i;
hit = orig + dir*dist_i; hit = orig + dir*dist_i;
N = glm::normalize(hit - spheres[i].center); hit_center = glm::normalize(hit - spheres[i].center);
material = spheres[i].material; material = spheres[i].material;
} }
} }
return spheres_dist<1000; return spheres_dist<1000;
} }
glm::vec3 cast_ray(const glm::vec3 &orig, const glm::vec3 &dir, const std::vector<Sphere> &spheres, const std::vector<Light> &lights, size_t depth = 0) { /*
glm::vec3 point, N; * @param vec3 orig: origin of the ray
* @param vec3 dir: direction of the ray
* @param vector: all spheres in the scene
* @param vector: all light sources of the scene
* @param depth = 0: initial recrusive depth
* @return color of the pixel depending on material and light
*/
glm::vec3 castRay(const glm::vec3 &orig, const glm::vec3 &dir, const std::vector<Sphere> &spheres,
const std::vector<Light> &lights, size_t depth = 0) {
glm::vec3 point, hit_center;
Material material; Material material;
if (depth > 4 || !scene_intersect(orig, dir, spheres, point, N, material)) { //return background color if a max recursive depth is reached
return glm::vec3(0.2, 0.7, 0.8); // background color if (depth > 4 || !sceneIntersect(orig, dir, spheres, point, hit_center, material)) {
return glm::vec3(0.2, 0.7, 0.8);
} }
glm::vec3 reflect_dir = glm::normalize(reflect(dir, N)); //compute recursive directions and origins of rays and then call the function
glm::vec3 reflect_orig = (glm::dot(reflect_dir,N) < 0) ? point - N*static_cast<float>(1e-3) : point + N*static_cast<float>(1e-3); // offset the original point to avoid occlusion by the object itself glm::vec3 reflect_dir = glm::normalize(reflect(dir, hit_center));
glm::vec3 reflect_color = cast_ray(reflect_orig, reflect_dir, spheres, lights, depth + 1); glm::vec3 reflect_orig = (glm::dot(reflect_dir, hit_center) < 0) ? point - hit_center *static_cast<float>(1e-3) :
point + hit_center *static_cast<float>(1e-3); // offset the original point to avoid occlusion by the object itself
glm::vec3 reflect_color = castRay(reflect_orig, reflect_dir, spheres, lights, depth + 1);
//compute shadows and other light properties for the returned ray color
float diffuse_light_intensity = 0, specular_light_intensity = 0; float diffuse_light_intensity = 0, specular_light_intensity = 0;
for (size_t i=0; i<lights.size(); i++) { for (size_t i=0; i<lights.size(); i++) {
glm::vec3 light_dir = glm::normalize(lights[i].position - point); glm::vec3 light_dir = glm::normalize(lights[i].position - point);
float light_distance = glm::distance(lights[i].position,point); float light_distance = glm::distance(lights[i].position, point);
glm::vec3 shadow_orig = (glm::dot(light_dir,N) < 0) ? point - N*static_cast<float>(1e-3) : point + N*static_cast<float>(1e-3); // checking if the point lies in the shadow of the lights[i] glm::vec3 shadow_orig = (glm::dot(light_dir, hit_center) < 0) ? point - hit_center *static_cast<float>(1e-3) :
glm::vec3 shadow_pt, shadow_N; point + hit_center*static_cast<float>(1e-3); // checking if the point lies in the shadow of the lights[i]
glm::vec3 shadow_pt, shadow_hit_center;
Material tmpmaterial; Material tmpmaterial;
if (scene_intersect(shadow_orig, light_dir, spheres, shadow_pt, shadow_N, tmpmaterial) && glm::distance(shadow_pt, shadow_orig) < light_distance) if (sceneIntersect(shadow_orig, light_dir, spheres, shadow_pt, shadow_hit_center, tmpmaterial)
&& glm::distance(shadow_pt, shadow_orig) < light_distance)
continue; continue;
diffuse_light_intensity += lights[i].intensity * std::max(0.f, glm::dot(light_dir,N)); diffuse_light_intensity += lights[i].intensity * std::max(0.f, glm::dot(light_dir, hit_center));
specular_light_intensity += powf(std::max(0.f, glm::dot(reflect(light_dir, N),dir)), material.specular_exponent)*lights[i].intensity; specular_light_intensity += powf(std::max(0.f, glm::dot(reflect(light_dir, hit_center),dir)), material.specular_exponent)*lights[i].intensity;
} }
return material.diffuse_color * diffuse_light_intensity * material.albedo[0] + glm::vec3(1., 1., 1.)*specular_light_intensity * material.albedo[1] + reflect_color*material.albedo[2]; return material.diffuse_color * diffuse_light_intensity * material.albedo[0] +
glm::vec3(1., 1., 1.)*specular_light_intensity * material.albedo[1] + reflect_color*material.albedo[2];
} }
/*
* @param vector: all spheres in the scene
* @param vector: all light sources in the scene
* @return TextureData: texture data for the buffers
*/
vkcv::asset::TextureData render(const std::vector<Sphere> &spheres, const std::vector<Light> &lights) { vkcv::asset::TextureData render(const std::vector<Sphere> &spheres, const std::vector<Light> &lights) {
//constants for the image data
const int width = 800; const int width = 800;
const int height = 600; const int height = 600;
const int fov = M_PI/2.; const int fov = M_PI/2.;
//compute image format for the framebuffer and compute the ray colors for the image
std::vector<glm::vec3> framebuffer(width*height); std::vector<glm::vec3> framebuffer(width*height);
#pragma omp parallel for #pragma omp parallel for
for (size_t j = 0; j<height; j++) { for (size_t j = 0; j<height; j++) {
...@@ -106,7 +157,7 @@ vkcv::asset::TextureData render(const std::vector<Sphere> &spheres, const std::v ...@@ -106,7 +157,7 @@ vkcv::asset::TextureData render(const std::vector<Sphere> &spheres, const std::v
float x = (2*(i + 0.5f)/(float)width - 1)*tan(fov/2.f)*width/(float)height; float x = (2*(i + 0.5f)/(float)width - 1)*tan(fov/2.f)*width/(float)height;
float y = -(2*(j + 0.5f)/(float)height - 1)*tan(fov/2.f); float y = -(2*(j + 0.5f)/(float)height - 1)*tan(fov/2.f);
glm::vec3 dir = glm::normalize(glm::vec3(x, y, -1)); glm::vec3 dir = glm::normalize(glm::vec3(x, y, -1));
framebuffer[i+j*width] = cast_ray(glm::vec3(0,0,0), dir, spheres, lights); framebuffer[i+j*width] = castRay(glm::vec3(0,0,0), dir, spheres, lights);
} }
} }
...@@ -133,7 +184,7 @@ vkcv::asset::TextureData render(const std::vector<Sphere> &spheres, const std::v ...@@ -133,7 +184,7 @@ vkcv::asset::TextureData render(const std::vector<Sphere> &spheres, const std::v
int main(int argc, const char** argv) { int main(int argc, const char** argv) {
const char* applicationName = "First Triangle"; const char* applicationName = "SAF_R";
const int windowWidth = 800; const int windowWidth = 800;
const int windowHeight = 600; const int windowHeight = 600;
...@@ -153,40 +204,44 @@ int main(int argc, const char** argv) { ...@@ -153,40 +204,44 @@ int main(int argc, const char** argv) {
{ "VK_KHR_swapchain" } { "VK_KHR_swapchain" }
); );
vkcv::ShaderProgram triangleShaderProgram; vkcv::ShaderProgram safrShaderProgram;
vkcv::shader::GLSLCompiler compiler; vkcv::shader::GLSLCompiler compiler;
compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("shaders/shader.vert"), compiler.compile(vkcv::ShaderStage::VERTEX, std::filesystem::path("shaders/shader.vert"),
[&triangleShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { [&safrShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
triangleShaderProgram.addShader(shaderStage, path); safrShaderProgram.addShader(shaderStage, path);
}); });
compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("shaders/shader.frag"), compiler.compile(vkcv::ShaderStage::FRAGMENT, std::filesystem::path("shaders/shader.frag"),
[&triangleShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) { [&safrShaderProgram](vkcv::ShaderStage shaderStage, const std::filesystem::path& path) {
triangleShaderProgram.addShader(shaderStage, path); safrShaderProgram.addShader(shaderStage, path);
}); });
uint32_t setID = 0; uint32_t setID = 0;
std::vector<vkcv::DescriptorBinding> descriptorBindings = { triangleShaderProgram.getReflectedDescriptors()[setID] }; std::vector<vkcv::DescriptorBinding> descriptorBindings = { safrShaderProgram.getReflectedDescriptors()[setID] };
vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorBindings); vkcv::DescriptorSetHandle descriptorSet = core.createDescriptorSet(descriptorBindings);
Material ivory(glm::vec3(0.6, 0.3, 0.1), glm::vec3(0.4, 0.4, 0.3), 50.); //materials for the spheres
Material red_rubber(glm::vec3(0.9, 0.1, 0.0), glm::vec3(0.3, 0.1, 0.1), 10.); Material ivory(glm::vec3(0.6, 0.3, 0.1), glm::vec3(0.4, 0.4, 0.3), 50.);
Material mirror(glm::vec3(0.0, 10.0, 0.8), glm::vec3(1.0, 1.0, 1.0), 1425.); Material red_rubber(glm::vec3(0.9, 0.1, 0.0), glm::vec3(0.3, 0.1, 0.1), 10.);
Material mirror(glm::vec3(0.0, 10.0, 0.8), glm::vec3(1.0, 1.0, 1.0), 1425.);
//spheres for the scene
std::vector<Sphere> spheres; std::vector<Sphere> spheres;
spheres.push_back(Sphere(glm::vec3(-3, 0, -16), 2, ivory)); spheres.push_back(Sphere(glm::vec3(-3, 0, -16), 2, ivory));
spheres.push_back(Sphere(glm::vec3(-1.0, -1.5, -12), 2, mirror)); spheres.push_back(Sphere(glm::vec3(-1.0, -1.5, -12), 2, mirror));
spheres.push_back(Sphere(glm::vec3( 1.5, -0.5, -18), 3, red_rubber)); spheres.push_back(Sphere(glm::vec3( 1.5, -0.5, -18), 3, red_rubber));
spheres.push_back(Sphere(glm::vec3( 7, 5, -18), 4, mirror)); spheres.push_back(Sphere(glm::vec3( 7, 5, -18), 4, mirror));
//lights for the scene
std::vector<Light> lights; std::vector<Light> lights;
lights.push_back(Light(glm::vec3(-20, 20, 20), 1.5)); lights.push_back(Light(glm::vec3(-20, 20, 20), 1.5));
lights.push_back(Light(glm::vec3( 30, 50, -25), 1.8)); lights.push_back(Light(glm::vec3( 30, 50, -25), 1.8));
lights.push_back(Light(glm::vec3( 30, 20, 30), 1.7)); lights.push_back(Light(glm::vec3( 30, 20, 30), 1.7));
//create the raytracer image for rendering
vkcv::asset::TextureData texData = render(spheres, lights); vkcv::asset::TextureData texData = render(spheres, lights);
// texData = vkcv::asset::loadTexture("textures/texture.png"); // texData = vkcv::asset::loadTexture("textures/texture.png");
vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Unorm, texData.width, texData.height); vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Unorm, texData.width, texData.height);
texture.fill( texData.data.data()); texture.fill( texData.data.data());
texture.generateMipChainImmediate(); texture.generateMipChainImmediate();
...@@ -201,16 +256,16 @@ int main(int argc, const char** argv) { ...@@ -201,16 +256,16 @@ int main(int argc, const char** argv) {
vkcv::DescriptorWrites setWrites; vkcv::DescriptorWrites setWrites;
setWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) }; setWrites.sampledImageWrites = { vkcv::SampledImageDescriptorWrite(0, texture.getHandle()) };
setWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, sampler) }; setWrites.samplerWrites = { vkcv::SamplerDescriptorWrite(1, sampler) };
core.writeDescriptorSet(descriptorSet, setWrites); core.writeDescriptorSet(descriptorSet, setWrites);
const auto& context = core.getContext(); const auto& context = core.getContext();
auto triangleIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3, vkcv::BufferMemoryType::DEVICE_LOCAL); auto safrIndexBuffer = core.createBuffer<uint16_t>(vkcv::BufferType::INDEX, 3, vkcv::BufferMemoryType::DEVICE_LOCAL);
uint16_t indices[3] = { 0, 1, 2 }; uint16_t indices[3] = { 0, 1, 2 };
triangleIndexBuffer.fill(&indices[0], sizeof(indices)); safrIndexBuffer.fill(&indices[0], sizeof(indices));
// an example attachment for passes that output to the window // an example attachment for passes that output to the window
const vkcv::AttachmentDescription present_color_attachment( const vkcv::AttachmentDescription present_color_attachment(
...@@ -218,10 +273,10 @@ int main(int argc, const char** argv) { ...@@ -218,10 +273,10 @@ int main(int argc, const char** argv) {
vkcv::AttachmentOperation::CLEAR, vkcv::AttachmentOperation::CLEAR,
core.getSwapchain().getFormat()); core.getSwapchain().getFormat());
vkcv::PassConfig trianglePassDefinition({ present_color_attachment }); vkcv::PassConfig safrPassDefinition({ present_color_attachment });
vkcv::PassHandle trianglePass = core.createPass(trianglePassDefinition); vkcv::PassHandle safrPass = core.createPass(safrPassDefinition);
if (!trianglePass) if (!safrPass)
{ {
std::cout << "Error. Could not create renderpass. Exiting." << std::endl; std::cout << "Error. Could not create renderpass. Exiting." << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
...@@ -229,19 +284,19 @@ int main(int argc, const char** argv) { ...@@ -229,19 +284,19 @@ int main(int argc, const char** argv) {
const vkcv::PipelineConfig trianglePipelineDefinition { const vkcv::PipelineConfig safrPipelineDefinition {
triangleShaderProgram, safrShaderProgram,
(uint32_t)windowWidth, (uint32_t)windowWidth,
(uint32_t)windowHeight, (uint32_t)windowHeight,
trianglePass, safrPass,
{}, {},
{ core.getDescriptorSet(descriptorSet).layout }, { core.getDescriptorSet(descriptorSet).layout },
false false
}; };
vkcv::PipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition); vkcv::PipelineHandle safrPipeline = core.createGraphicsPipeline(safrPipelineDefinition);
if (!trianglePipeline) if (!safrPipeline)
{ {
std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl; std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
...@@ -249,8 +304,8 @@ int main(int argc, const char** argv) { ...@@ -249,8 +304,8 @@ int main(int argc, const char** argv) {
auto start = std::chrono::system_clock::now(); auto start = std::chrono::system_clock::now();
const vkcv::Mesh renderMesh({}, triangleIndexBuffer.getVulkanHandle(), 3); const vkcv::Mesh renderMesh({}, safrIndexBuffer.getVulkanHandle(), 3);
vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle); vkcv::DescriptorSetUsage descriptorUsage(0, core.getDescriptorSet(descriptorSet).vulkanHandle);
vkcv::DrawcallInfo drawcall(renderMesh, { descriptorUsage },1); vkcv::DrawcallInfo drawcall(renderMesh, { descriptorUsage },1);
const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle(); const vkcv::ImageHandle swapchainInput = vkcv::ImageHandle::createSwapchainImageHandle();
...@@ -287,8 +342,8 @@ int main(int argc, const char** argv) { ...@@ -287,8 +342,8 @@ int main(int argc, const char** argv) {
core.recordDrawcallsToCmdStream( core.recordDrawcallsToCmdStream(
cmdStream, cmdStream,
trianglePass, safrPass,
trianglePipeline, safrPipeline,
pushConstants, pushConstants,
{ drawcall }, { drawcall },
{ swapchainInput }); { swapchainInput });
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment