Raytraced Renderer compiles now

This commit is contained in:
Ben Kyd
2023-12-21 19:43:03 +00:00
parent 0155cb9804
commit 021e552f74
28 changed files with 241 additions and 210 deletions

View File

@@ -1,7 +1,8 @@
cmake_minimum_required(VERSION 3.13)
project(inferno)
file(GLOB SRC "src/*.cpp" "src/graphics/*.cpp" "src/preview_renderer/*.cpp" "src/scene/*.cpp" "src/thirdparty/imgui/*.cpp" "src/preview_renderer/*.cpp")
# file(GLOB SRC "src/*.cpp" "src/graphics/*.cpp" "src/preview_renderer/*.cpp" "src/scene/*.cpp" "src/thirdparty/imgui/*.cpp" "src/preview_renderer/*.cpp")
file(GLOB_RECURSE SRC "src/*.cpp")
add_subdirectory("thirdparty/assimp")

View File

@@ -31,6 +31,8 @@
#define GLM_FORCE_SWIZZLE
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/ext.hpp>
#include <glm/gtx/string_cast.hpp>
#include <vector>
namespace inferno {

View File

@@ -14,7 +14,7 @@
#include "graphics/shader.hpp"
#include "graphics/swapchain.hpp"
#include "graphics/vkrenderer.hpp"
#include "preview_renderer/debug.hpp"
#include "preview/debug.hpp"
#include "window.hpp"
// #include "preview_renderer/debug.hpp"
@@ -73,7 +73,7 @@ void inferno_timer_print(InfernoTimer* timer, bool time)
std::chrono::duration<double> inferno_timer_get_time(InfernoTimer* timer)
{
return timer->Time;
return timer->Times.back();
}
std::chrono::duration<double> inferno_timer_get_average(InfernoTimer* timer)
@@ -122,18 +122,15 @@ InfernoApp* inferno_create()
true);
scene::SceneObject* object = scene::scene_object_create(app->Device);
scene::scene_object_load(object, "res/Bistro.obj");
// scene::scene_object_load(object, "res/Bistro.obj");
// scene::scene_object_load(object, "res/sponza.obj");
// scene::mesh_load_obj(object, "res/cornell-box.obj");
scene::scene_object_load(object, "res/cornell-box.obj");
scene::scene_add_object(app->Scene, object);
// scene::Mesh* lucy = scene::mesh_create(app->Device);
// scene::mesh_load_obj(lucy, "res/lucy.obj");
// scene::mesh_ready(lucy);
// scene::SceneObject* lucyObject = scene::scene_object_create();
// scene::scene_object_add_mesh(lucyObject, lucy);
// scene::scene_add_object(app->Scene, lucyObject);
scene::SceneObject* lucy = scene::scene_object_create(app->Device);
scene::scene_object_load(lucy, "res/lucy.obj");
scene::scene_object_optimize(lucy);
scene::scene_add_object(app->Scene, lucy);
// app->PreviewRenderer = graphics::preview_create();
// graphics::preview_set_viewport(app->PreviewRenderer, app->Scene->Camera);
// app->RayRenderer = graphics::rayr_create(app->Scene);
@@ -251,6 +248,31 @@ void inferno_end(InfernoApp* app)
int inferno_run(InfernoApp* app)
{
// we weant to outline Lucy in lines
graphics::renderer_submit_repeat(
app->Renderer,
[&](graphics::VulkanRenderer* renderer, VkCommandBuffer* commandBuffer) {
const auto lucy = app->Scene->Objects[0];
for (auto& mesh : scene::scene_object_get_meshs(lucy)) {
for (int i = 0; i < mesh->Indicies.size() - 1; i += 3) {
graphics::debug_draw_line(
mesh->Verticies[mesh->Indicies[i]].Position,
mesh->Verticies[mesh->Indicies[i + 1]].Position,
{ 1, 0, 0 });
graphics::debug_draw_line(
mesh->Verticies[mesh->Indicies[i + 1]].Position,
mesh->Verticies[mesh->Indicies[i + 2]].Position,
{ 1, 0, 0 });
graphics::debug_draw_line(
mesh->Verticies[mesh->Indicies[i + 2]].Position,
mesh->Verticies[mesh->Indicies[i]].Position,
{ 1, 0, 0 });
}
}
},
false);
while (graphics::window_new_frame()) {
if (!inferno_pre(app))
continue;
@@ -325,7 +347,6 @@ int inferno_run(InfernoApp* app)
lastViewport = currentViewport;
graphics::preview_draw(app->PreviewRenderer, app->Scene);
graphics::debug_draw_line({ 0, 0, 0 }, { 1, 1, 0 }, { 1, 1, 0 });
graphics::debug_draw_to_preview(app->Scene);
ImTextureID texture
@@ -356,4 +377,4 @@ int inferno_run(InfernoApp* app)
return 1;
}
} // namespace inferno
} // namespace infern

View File

@@ -5,8 +5,7 @@
#include "scene/mesh.hpp"
#include "scene/scene.hpp"
// #include "scene/camera.hpp"
#include "preview_renderer/renderer.hpp"
#include "renderer/renderer.hpp"
#include "preview/renderer.hpp"
#include <memory>
@@ -60,7 +59,7 @@ typedef struct InfernoApp {
graphics::VulkanRenderer* Renderer;
graphics::PreviewRenderer* PreviewRenderer;
graphics::RayRenderer* RayRenderer;
// graphics::RayRenderer* RayRenderer;
InfernoTimer* MainTimer;
uint64_t FrameCount;

View File

@@ -5,7 +5,7 @@
#include "graphics/shader.hpp"
#include "graphics/vkrenderer.hpp"
#include "preview_renderer/renderer.hpp"
#include "preview/renderer.hpp"
#include "scene/camera.hpp"
#include "scene/mesh.hpp"
@@ -75,6 +75,9 @@ void debug_draw_to_preview(scene::Scene* scene)
if (!DebugDrawerInstance->DoShow)
return;
if (DebugDrawerInstance->LineElements.size() == 0)
return;
uint32_t bufferSize
= DebugDrawerInstance->LineElements.size() * sizeof(DebugLine) * 2;
scene::DebugLineVert* bufferData = new scene::DebugLineVert[bufferSize];

View File

@@ -2,7 +2,7 @@
#include <graphics.hpp>
#include "preview_renderer/debug.hpp"
#include "debug.hpp"
#include "graphics/buffer.hpp"
#include "graphics/rendertarget.hpp"
@@ -45,7 +45,9 @@ PreviewRenderer* preview_create(VulkanRenderer* vkrenderer)
return renderer;
}
void preview_cleanup(PreviewRenderer* renderer) { }
void preview_cleanup(PreviewRenderer* renderer) {
delete renderer;
}
void preview_draw_ui(PreviewRenderer* renderer) { }

View File

@@ -1,6 +1,6 @@
#include "object_tracer.hpp"
#include "preview_renderer/debug.hpp"
#include "preview/debug.hpp"
#include "scene/object.hpp"
#include <cmath>
@@ -50,11 +50,12 @@ HitInfo* object_ray_collide(scene::SceneObject* object, Ray* ray)
const uint32_t* ind;
const float* verts;
const float* norms;
mesh->getIndicies(&ind);
mesh->getVerticies(&verts, &norms);
// mesh->getIndicies(&ind);
// mesh->getVerticies(&verts, &norms);
float t = INFINITY;
for (int i = 0; i < mesh->getIndexCount(); i += 3) {
int i ;
// for (int i = 0; i < mesh->getIndexCount(); i += 3) {
uint32_t indexa = ind[i + 0];
uint32_t indexb = ind[i + 1];
uint32_t indexc = ind[i + 2];
@@ -71,7 +72,7 @@ HitInfo* object_ray_collide(scene::SceneObject* object, Ray* ray)
t = temp_t;
info->Distance = t;
}
}
// }
}
return info;
}

View File

@@ -1,9 +1,10 @@
#pragma once
#pragma once
#include <scene/object.hpp>
#include <scene/mesh.hpp>
#include <renderer/hit.hpp>
#include <renderer/ray.hpp>
#include <raytracing/hit.hpp>
#include <raytracing/ray.hpp>
namespace inferno::graphics::rays {

View File

@@ -5,7 +5,8 @@
#include <maths.hpp>
#include <scene/camera.hpp>
#include <renderer/ray.hpp>
#include <raytracing/ray.hpp>
namespace inferno::graphics::rays {

View File

@@ -5,7 +5,7 @@
#include <graphics.hpp>
#include <renderer/ray.hpp>
#include <raytracing/ray.hpp>
namespace inferno::graphics {
class Camera;

151
src/raytracing/renderer.cpp Normal file
View File

@@ -0,0 +1,151 @@
#include "renderer.hpp"
#include <graphics.hpp>
#include <graphics/rendertarget.hpp>
#include <graphics/vkrenderer.hpp>
#include <raytracing/hit.hpp>
#include <raytracing/object_tracer.hpp>
#include <raytracing/ray.hpp>
#include <scene/camera.hpp>
#include <scene/mesh.hpp>
#include <scene/scene.hpp>
// #include "preview/debug.hpp"
#include "ray_source.hpp"
#include <yolo/yolo.hpp>
#include <scene/camera.hpp>
#include <cstring>
#include <iostream>
namespace inferno::graphics {
RayRenderer* rayr_create(VulkanRenderer* renderer, scene::Scene* scene)
{
RayRenderer* ray = new RayRenderer;
ray->Scene = scene;
ray->Renderer = renderer;
auto camera = scene::scene_get_camera(scene);
glm::ivec2 viewport = camera_ray_get_viewport(camera);
ray->Viewport = { .extent
= { static_cast<uint32_t>(viewport.x), static_cast<uint32_t>(viewport.y) } };
ray->RenderData
= new glm::fvec4[ray->Viewport.extent.width * ray->Viewport.extent.height];
memset(ray->RenderData, 0,
ray->Viewport.extent.width * ray->Viewport.extent.height * sizeof(glm::fvec4));
// TODO: We need to upload RenderData to the GPU / maybe do a quad pass ? I think
// ImGui handels that
// ray->RayRenderTarget = graphics::rendertarget_create()
return ray;
}
void rayr_cleanup(RayRenderer* renderer) { delete[] renderer->RenderData; }
void rayr_draw_ui(RayRenderer* renderer) { }
void rayr_set_viewport(RayRenderer* renderer, Camera* camera)
{
auto viewport = camera_ray_get_viewport(camera);
renderer->Viewport.offset.x = 0;
renderer->Viewport.offset.y = 0;
renderer->Viewport.extent.width = viewport.x;
renderer->Viewport.extent.height = viewport.y;
renderer->HasViewportChanged = true;
}
GLuint rayr_get_rendered_texture(RayRenderer* renderer)
{
// return renderer->RenderTargetTexture;
}
glm::fvec4* rayr_get_render_data(RayRenderer* renderer) { return renderer->RenderData; }
void rayr_prepare(RayRenderer* renderer)
{
// TODO: This is TEMP
memset(renderer->RenderData, 0,
renderer->Viewport.extent.width * renderer->Viewport.extent.height
* sizeof(glm::fvec4));
assert(renderer->Scene != nullptr);
if (scene::scene_did_update(renderer->Scene)) {
yolo::debug("Scene updated, rebuilding acceleration structure");
// renderer->AccelerationInterface->newScene(renderer->CurrentScene);
}
}
void rayr_draw(RayRenderer* renderer)
{
rayr_prepare(renderer);
scene::scene_frame_tick(renderer->Scene);
// TODO: Rays should definately be bump allocated if possible, this is KBs of
// ray data and nothing else being reallocated every frame for no reason
rays::ReferencedRayField startRays
= rays::generate_initial_rays(scene::scene_get_camera(renderer->Scene), true);
// debug_draw_line({ 0, 0, 0 }, { 0, 0, 1 }, { 1, 0, 0 });
#pragma omp parallel for
for (int x = 0; x < renderer->Viewport.extent.width; x++) {
for (int y = 0; y < renderer->Viewport.extent.height; y++) {
rays::Ray* ray = startRays.Field[x * renderer->Viewport.extent.height + y];
rays::HitInfo* closest_hit = nullptr;
for (auto& obj : scene::scene_get_renderables(renderer->Scene)) {
rays::HitInfo* hit = rays::object_ray_collide(obj, ray);
if (hit->Did) {
if (closest_hit == nullptr) {
closest_hit = hit;
} else {
bool is_closer = hit->Distance < closest_hit->Distance;
if (is_closer) {
delete closest_hit;
closest_hit = hit;
} else {
delete hit;
}
}
}
if (hit->Did) {
glm::vec3 hit_distance = glm::vec3 { hit->Distance };
hit_distance /= 10;
renderer->RenderData[y * renderer->Viewport.extent.width + x]
= { hit_distance, 1.0 };
}
delete hit;
}
}
}
}
//
// void RayRenderer::computeHit(HitInfo* info)
// {
// static float mind = 100000.0f;
// static float maxd = 0.0f;
// // TODO: Make sure signal is started
// if (!(*mCurrentRefTable).count(info->Caller->Reference)) {
// yolo::warn("Why is the ray not in the map?!");
// return;
// }
// glm::ivec2 pos = (*mCurrentRefTable)[info->Caller->Reference];
// float d = info->Distance;
// if (d < mind)
// mind = d;
// if (d > maxd)
// maxd = d;
// float n = (d - mind) / (maxd - mind);
// mTarget[pos.y * mRenderTargetSize.x + pos.x] = { n, n, n, 1.0f };
// }
}

View File

@@ -13,32 +13,39 @@ namespace inferno::scene {
namespace inferno::graphics {
class VulkanRenderer;
class RenderTarget;
class Camera;
class HitInfo;
class RaySource;
class RenderDispatcher;
typedef struct RayRenderer {
glm::ivec2 Viewport;
VulkanRenderer* Renderer;
// TODO: Can this be direct to GPU?
// NOTE: Probably not
glm::fvec4* RenderData = nullptr;
GLuint RenderTargetTexture = 0;
RenderTarget* RayRenderTarget;
scene::Scene* Scene = nullptr;
VkRect2D Viewport;
bool HasViewportChanged;
} RayRenderer;
// Expects complete scene
RayRenderer* rayr_create(scene::Scene* scene);
// Expects complete scene as it will need to bake a lot of features
RayRenderer* rayr_create(VulkanRenderer* renderer, scene::Scene* scene);
void rayr_cleanup(RayRenderer* renderer);
void rayr_draw_ui(RayRenderer* renderer);
void rayr_set_viewport(RayRenderer* renderer, Camera* camera);
GLuint rayr_get_rendered_texture(RayRenderer* renderer);
// rayr_get_rendered_texture(RayRenderer* renderer);
glm::fvec4* rayr_get_render_data(RayRenderer* renderer);
void rayr_prepare(RayRenderer* renderer);
void rayr_draw(RayRenderer* renderer);
void raryr_compute_hit(HitInfo* info);

View File

@@ -1,172 +0,0 @@
#include "renderer.hpp"
#include <graphics.hpp>
#include <renderer/hit.hpp>
#include <renderer/object_tracer.hpp>
#include <renderer/ray.hpp>
#include <scene/camera.hpp>
#include <scene/mesh.hpp>
#include <scene/scene.hpp>
#include "preview_renderer/debug.hpp"
#include "ray_source.hpp"
#include <yolo/yolo.hpp>
#include <scene/camera.hpp>
#include <cstring>
#include <iostream>
namespace inferno::graphics {
RayRenderer* rayr_create(scene::Scene* scene)
{
RayRenderer* renderer = new RayRenderer;
renderer->Scene = scene;
auto camera = scene::scene_get_camera(scene);
auto viewport = camera_ray_get_viewport(camera);
renderer->Viewport = viewport;
yolo::debug("Raytracing Rendering {}x{} viewport", renderer->Viewport.x, renderer->Viewport.y);
renderer->RenderData = new glm::fvec4[renderer->Viewport.x * renderer->Viewport.y];
memset(renderer->RenderData, 0, renderer->Viewport.x * renderer->Viewport.y * sizeof(glm::fvec4));
glGenTextures(1, &renderer->RenderTargetTexture);
glBindTexture(GL_TEXTURE_2D, renderer->RenderTargetTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, renderer->Viewport.x, renderer->Viewport.y, 0, GL_RGBA, GL_FLOAT, renderer->RenderData);
glBindTexture(GL_TEXTURE_2D, 0);
return renderer;
}
void rayr_cleanup(RayRenderer* renderer)
{
delete[] renderer->RenderData;
}
void rayr_draw_ui(RayRenderer* renderer)
{
}
void rayr_set_viewport(RayRenderer* renderer, Camera* camera)
{
auto viewport = camera_ray_get_viewport(camera);
renderer->Viewport = viewport;
delete renderer->RenderData;
renderer->RenderData = new glm::fvec4[renderer->Viewport.x * renderer->Viewport.y];
glGenTextures(1, &renderer->RenderTargetTexture);
glBindTexture(GL_TEXTURE_2D, renderer->RenderTargetTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, renderer->Viewport.x, renderer->Viewport.y, 0, GL_RGBA, GL_FLOAT, renderer->RenderData);
glBindTexture(GL_TEXTURE_2D, 0);
}
GLuint rayr_get_rendered_texture(RayRenderer* renderer)
{
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindTexture(GL_TEXTURE_2D, renderer->RenderTargetTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, renderer->Viewport.x, renderer->Viewport.y, 0, GL_RGBA, GL_FLOAT, renderer->RenderData);
return renderer->RenderTargetTexture;
}
glm::fvec4* rayr_get_render_data(RayRenderer* renderer)
{
return renderer->RenderData;
}
void rayr_prepare(RayRenderer* renderer)
{
// TODO: This is TEMP
memset(renderer->RenderData, 0, renderer->Viewport.x * renderer->Viewport.y * sizeof(glm::fvec4));
assert(renderer->Scene != nullptr);
if (scene::scene_did_update(renderer->Scene)) {
yolo::debug("Scene updated, rebuilding acceleration structure");
// renderer->AccelerationInterface->newScene(renderer->CurrentScene);
}
}
void rayr_draw(RayRenderer* renderer)
{
rayr_prepare(renderer);
scene::scene_frame_tick(renderer->Scene);
// TODO: Rays should definately be bump allocated if possible, this is KBs of
// ray data and nothing else being reallocated every frame for no reason
rays::ReferencedRayField startRays = rays::generate_initial_rays(scene::scene_get_camera(renderer->Scene), true);
// debug_draw_line({ 0, 0, 0 }, { 0, 0, 1 }, { 1, 0, 0 });
#pragma omp parallel for
for (int x = 0; x < renderer->Viewport.x; x++) {
for (int y = 0; y < renderer->Viewport.y; y++) {
rays::Ray* ray = startRays.Field[x * renderer->Viewport.y + y];
rays::HitInfo* closest_hit = nullptr;
for (auto& obj : scene::scene_get_renderables(renderer->Scene)) {
rays::HitInfo* hit = rays::object_ray_collide(obj, ray);
if (hit->Did) {
if (closest_hit == nullptr) {
closest_hit = hit;
} else {
bool is_closer = hit->Distance < closest_hit->Distance;
if (is_closer) {
delete closest_hit;
closest_hit = hit;
} else {
delete hit;
}
}
}
if (hit->Did) {
glm::vec3 hit_distance = glm::vec3 { hit->Distance };
hit_distance /= 10;
renderer->RenderData[y * renderer->Viewport.x + x] = { hit_distance, 1.0 };
}
delete hit;
}
}
}
}
//
// void RayRenderer::computeHit(HitInfo* info)
// {
// static float mind = 100000.0f;
// static float maxd = 0.0f;
// // TODO: Make sure signal is started
// if (!(*mCurrentRefTable).count(info->Caller->Reference)) {
// yolo::warn("Why is the ray not in the map?!");
// return;
// }
// glm::ivec2 pos = (*mCurrentRefTable)[info->Caller->Reference];
// float d = info->Distance;
// if (d < mind)
// mind = d;
// if (d > maxd)
// maxd = d;
// float n = (d - mind) / (maxd - mind);
// mTarget[pos.y * mRenderTargetSize.x + pos.x] = { n, n, n, 1.0f };
// }
}

View File

@@ -56,9 +56,12 @@ void mesh_process(Mesh* out, aiMesh* mesh)
{
for (unsigned int i = 0; i < mesh->mNumVertices; i++) {
Vert vertex = {
.Position = glm::vec3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z),
.Normal = glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z),
.Position
= glm::vec3(mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z),
.Normal
= glm::vec3(mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z),
};
out->Verticies.push_back(vertex);
}
@@ -71,6 +74,8 @@ void mesh_process(Mesh* out, aiMesh* mesh)
}
}
void mesh_optimize(Mesh* mesh) { }
void mesh_ready(Mesh* mesh)
{
void* data = mesh->Verticies.data();

View File

@@ -50,6 +50,7 @@ void mesh_cleanup(Mesh* mesh);
void mesh_process(Mesh* out, aiMesh* mesh);
void mesh_optimize(Mesh* mesh);
void mesh_ready(Mesh* mesh);
uint32_t mesh_get_verticies(Mesh* mesh, const float** v, const float** n);

View File

@@ -40,7 +40,7 @@ void scene_object_load(SceneObject* object, std::filesystem::path file)
const aiScene* scene = importer.ReadFile(file.string(),
aiProcess_Triangulate | aiProcess_OptimizeMeshes | aiProcess_OptimizeGraph
| aiProcess_GenNormals);
| aiProcess_GenSmoothNormals);
if (!scene || scene->mFlags & AI_SCENE_FLAGS_INCOMPLETE || !scene->mRootNode) {
yolo::error("Assimp error: {}", importer.GetErrorString());
@@ -50,6 +50,13 @@ void scene_object_load(SceneObject* object, std::filesystem::path file)
processNode(object, scene->mRootNode, scene);
}
void scene_object_optimize(SceneObject* object)
{
for (auto& mesh : object->Meshs) {
mesh_optimize(mesh);
}
}
void scene_object_add_mesh(SceneObject* object, Mesh* mesh)
{
object->Meshs.push_back(mesh);

View File

@@ -23,6 +23,7 @@ SceneObject* scene_object_create(graphics::GraphicsDevice* device);
void scene_object_cleanup(SceneObject* object);
void scene_object_load(SceneObject* object, std::filesystem::path file);
void scene_object_optimize(SceneObject* object);
void scene_object_add_mesh(SceneObject* object, Mesh* mesh);
std::vector<Mesh*>& scene_object_get_meshs(SceneObject* object);