Tonemapping

This commit is contained in:
Ben
2019-10-01 22:35:35 +01:00
parent ac344343de
commit a8dc75e46b
9 changed files with 213 additions and 151 deletions

View File

@@ -35,8 +35,8 @@ find_package(OpenGL REQUIRED)
find_package(OpenMP)
if (OPENMP_FOUND)
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
endif()
if (UNIX)
@@ -48,31 +48,31 @@ if (UNIX)
endif (UNIX)
include_directories(${executable}
#${PNG_INCLUDE_DIR}
#${JPEG_INCLUDE_DIR}
${IncludeDIR}
#${PNG_INCLUDE_DIR}
#${JPEG_INCLUDE_DIR}
${IncludeDIR}
)
file(GLOB SourceFiles
${SrcDIR}/*
${SrcDIR}/acceleration/*
${SrcDIR}/core/*
${SrcDIR}/engine/*
${SrcDIR}/display/*
${SrcDIR}/definitions/*
${SrcDIR}/definitions/materials/*
${SrcDIR}/definitions/primatives/*
${SrcDIR}/denoise/*
${SrcDIR}/acceleration/*
${SrcDIR}/core/*
${SrcDIR}/engine/*
${SrcDIR}/display/*
${SrcDIR}/definitions/*
${SrcDIR}/definitions/materials/*
${SrcDIR}/definitions/primatives/*
${SrcDIR}/denoise/*
${SrcDIR}/util/*
${SrcDIR}/util/imgui/*
${TestDIR}/${CurrentTest}
${TestDIR}/${CurrentTest}
)
add_executable(${executable} ${SourceFiles})
set_target_properties(${executable} PROPERTIES
CXX_STANDARD 17
CXX_EXTENSIONS OFF
CXX_STANDARD 17
CXX_EXTENSIONS OFF
)
if (UNIX)
@@ -102,5 +102,5 @@ if (WIN32)
endif (WIN32)
target_link_libraries(${executable}
${CMAKE_DL_LIBS}
${CMAKE_DL_LIBS}
)

View File

@@ -14,16 +14,16 @@
#include <string>
enum OperationMode {
MODE_OPERATION_PROGRESSIVE_GUI,
MODE_OPERATION_PROGRESSIVE_IMG,
MODE_OPERATION_SAMPLES_IMG,
MODE_OPERATION_PROGRESSIVE_GUI,
MODE_OPERATION_PROGRESSIVE_IMG,
MODE_OPERATION_SAMPLES_IMG,
};
enum AccelerationMode {
MODE_ACCELERATION_NONE,
MODE_ACCELERATION_KD,
MODE_ACCELERATION_KD_SLOW,
MODE_ACCELERATION_BVH,
MODE_ACCELERATION_NONE,
MODE_ACCELERATION_KD,
MODE_ACCELERATION_KD_SLOW,
MODE_ACCELERATION_BVH,
};
enum RenderMode {
@@ -35,7 +35,8 @@ enum RenderMode {
enum ToneMapMode {
MODE_TONEMAP_REINHARD,
MODE_TONEMAP_EXP,
MODE_TONEMAP_ACES_FILMATIC,
MODE_TONEMAP_UNCHARTED2,
MODE_TONEMAP_CLAMP,
MODE_TONEMAP_BASIC
};

View File

@@ -2,32 +2,32 @@
#include "../ray.hpp"
bool Triangle::Intersect(Ray& ray, float& t) {
glm::vec3 vertex0 = points[0];
glm::vec3 vertex1 = points[1];
glm::vec3 vertex2 = points[2];
glm::vec3 edge1, edge2, h, s, q;
float a,f,u,v;
edge1 = vertex1 - vertex0;
edge2 = vertex2 - vertex0;
h = glm::cross(ray.direction, edge2);
a = glm::dot(edge1, h);
if (a > -EPSILON && a < EPSILON)
return false; // This ray is parallel to this triangle.
f = 1.0/a;
s = ray.origin - vertex0;
u = f * glm::dot(s, h);
if (u < 0.0 || u > 1.0)
return false;
q = glm::cross(s, edge1);
v = f * glm::dot(ray.direction, q);
if (v < 0.0 || u + v > 1.0)
return false;
// At this stage we can compute t to find out where the intersection point is on the line.
t = f * glm::dot(edge2, q);
if (t > EPSILON) // ray intersection
return true;
else // This means that there is a line intersection but not a ray intersection.
return false;
glm::vec3 vertex0 = points[0];
glm::vec3 vertex1 = points[1];
glm::vec3 vertex2 = points[2];
glm::vec3 edge1, edge2, h, s, q;
float a,f,u,v;
edge1 = vertex1 - vertex0;
edge2 = vertex2 - vertex0;
h = glm::cross(ray.direction, edge2);
a = glm::dot(edge1, h);
if (a > -EPSILON && a < EPSILON)
return false; // This ray is parallel to this triangle.
f = 1.0/a;
s = ray.origin - vertex0;
u = f * glm::dot(s, h);
if (u < 0.0 || u > 1.0)
return false;
q = glm::cross(s, edge1);
v = f * glm::dot(ray.direction, q);
if (v < 0.0 || u + v > 1.0)
return false;
// At this stage we can compute t to find out where the intersection point is on the line.
t = f * glm::dot(edge2, q);
if (t > EPSILON) // ray intersection
return true;
else // This means that there is a line intersection but not a ray intersection.
return false;
}
glm::vec3 Triangle::SurfaceTangent(glm::vec3 normal) {
@@ -35,19 +35,19 @@ glm::vec3 Triangle::SurfaceTangent(glm::vec3 normal) {
}
glm::vec3 Triangle::SurfaceNormal(glm::vec3 hitPoint) {
return ((normals[0] + normals[1] + normals[2]) / 3.0f);
return ((normals[0] + normals[1] + normals[2]) / 3.0f);
}
glm::vec2 Triangle::TexCoords(glm::vec3 hitPoint) {
return { 0.0f, 0.0f };
return { 0.0f, 0.0f };
}
void Triangle::Translate(glm::vec3 trans) {
points[0] += trans;
points[1] += trans;
points[2] += trans;
points[0] += trans;
points[1] += trans;
points[2] += trans;
}
glm::vec3 Triangle::Midpoint() {
return (points[0] + points[1] + points[2]) / 3.0f;
return (points[0] + points[1] + points[2]) / 3.0f;
}

View File

@@ -22,8 +22,8 @@ glm::vec3 GradientSky::Sample(Ray& ray) {
}
Scene::Scene(int width, int height) {
w = width;
h = height;
w = width;
h = height;
}
glm::vec3 Scene::SampleSky(Ray& ray) {

View File

@@ -66,55 +66,113 @@ void FrameBuffer::PostProcess(ToneMapMode mode) {
switch (mode) {
case MODE_TONEMAP_REINHARD:
{
for (int x = 0; x < XRes; x++)
for (int y = 0; y < YRes; y++) {
m_swapBuffer[y * this->XRes + x] = RenderPostProcess[y * this->XRes + x] /
(RenderPostProcess[y * this->XRes + x] + 1.0f);
}
break;
{
for (int x = 0; x < XRes; x++)
for (int y = 0; y < YRes; y++) {
m_swapBuffer[y * this->XRes + x] = RenderPostProcess[y * this->XRes + x] /
(RenderPostProcess[y * this->XRes + x] + 1.0f);
}
case MODE_TONEMAP_EXP:
{
for (int x = 0; x < XRes; x++)
for (int y = 0; y < YRes; y++) {
m_swapBuffer[y * this->XRes + x] = 1.0f - exp2(RenderPostProcess[y * this->XRes + x] * 1.0f);
}
break;
break;
}
case MODE_TONEMAP_ACES_FILMATIC:
{
static const glm::mat3 inputMat{
{0.59719, 0.35458, 0.04823},
{0.07600, 0.90834, 0.01566},
{0.02840, 0.13383, 0.83777}
};
static const glm::mat3 outputMat{
{ 1.60475, -0.53108, -0.07367},
{-0.10208, 1.10813, -0.00605},
{-0.00327, -0.07276, 1.07602}
};
auto ACES = [&](glm::vec3 v) -> glm::vec3 {
glm::vec3 a = v * (v + 0.0245786f) - 0.000090537f;
glm::vec3 b = v * (0.983729f * v + 0.4329510f) + 0.238081f;
return a / b;
};
for (int x = 0; x < XRes; x++)
for (int y = 0; y < YRes; y++) {
glm::vec3 col = RenderPostProcess[y * this->XRes + x];
col = col * inputMat;
col = ACES(col);
col = col * outputMat;
col = Clamp(col, 1.0f, 0.0f);
m_swapBuffer[y * this->XRes + x] = col;
}
break;
}
case MODE_TONEMAP_UNCHARTED2:
{
static const float exposure = 2.0f;
static const glm::vec3 W = { 11.2f, 11.2f, 11.2f };
auto Uncharted2 = [&](glm::vec3 x) -> glm::vec3 {
float A = 0.15f;
float B = 0.50f;
float C = 0.10f;
float D = 0.20f;
float E = 0.02f;
float F = 0.30f;
return ((x * (A * x + C * B) + D * E) / (x * (A * x + B) + D * F)) - E / F;
};
glm::vec3 white = glm::vec3{ 1.0f, 1.0f, 1.0f } / Uncharted2(W);
for (int x = 0; x < XRes; x++)
for (int y = 0; y < YRes; y++) {
glm::vec3 col = RenderPostProcess[y * this->XRes + x];
glm::vec3 cur = Uncharted2(col * exposure);
col = cur * white;
col = Clamp(col, 1.0f, 0.0f);
m_swapBuffer[y * this->XRes + x] = col;
}
break;
}
case MODE_TONEMAP_CLAMP:
{
for (int x = 0; x < XRes; x++)
for (int y = 0; y < YRes; y++) {
m_swapBuffer[y * this->XRes + x] = Clamp(RenderPostProcess[y * this->XRes + x], 1.0f, 0.0f);
}
break;
{
for (int x = 0; x < XRes; x++)
for (int y = 0; y < YRes; y++) {
m_swapBuffer[y * this->XRes + x] = Clamp(RenderPostProcess[y * this->XRes + x], 1.0f, 0.0f);
}
break;
}
case MODE_TONEMAP_BASIC:
{
float max = 0.0f;
{
float max = 0.0f;
for (int x = 0; x < XRes; x++)
for (int y = 0; y < YRes; y++) {
if (RenderPostProcess[y * this->XRes + x].r > max) max = RenderPostProcess[y * this->XRes + x].r;
if (RenderPostProcess[y * this->XRes + x].g > max) max = RenderPostProcess[y * this->XRes + x].g;
if (RenderPostProcess[y * this->XRes + x].b > max) max = RenderPostProcess[y * this->XRes + x].b;
}
for (int x = 0; x < XRes; x++)
for (int y = 0; y < YRes; y++) {
m_swapBuffer[y * this->XRes + x] = RenderPostProcess[y * this->XRes + x] / max;
}
break;
for (int x = 0; x < XRes; x++)
for (int y = 0; y < YRes; y++) {
if (RenderPostProcess[y * this->XRes + x].r > max) max = RenderPostProcess[y * this->XRes + x].r;
if (RenderPostProcess[y * this->XRes + x].g > max) max = RenderPostProcess[y * this->XRes + x].g;
if (RenderPostProcess[y * this->XRes + x].b > max) max = RenderPostProcess[y * this->XRes + x].b;
}
for (int x = 0; x < XRes; x++)
for (int y = 0; y < YRes; y++) {
m_swapBuffer[y * this->XRes + x] = RenderPostProcess[y * this->XRes + x] / max;
}
break;
}
default:
{
break;
}
{
break;
}
}
for (int x = 0; x < XRes; x++)

View File

@@ -29,7 +29,7 @@ void ProgressiveRenderer::Init(DisplayInterface* interface, Scene* scene) {
m_engine = new RenderEngine();
m_engine->Mode = MODE_RENDER_PATHTRACE;
m_engine->SetScene(scene);
m_interface = interface;
m_interface = interface;
m_scene = scene;
}
@@ -79,7 +79,7 @@ void ProgressiveRenderer::Input() {
ImGui::Combo("Render Mode", &m_renderModeSelected, renderItems, IM_ARRAYSIZE(renderItems));
m_mode = (RenderMode)m_renderModeSelected;
const char* toneMapItems[] = { "Reinhard Tonamap", "Exponential Tonemap", "Clamp", "Basic Tonemap" };
const char* toneMapItems[] = { "Reinhard Tonamap", "ACES Filmatic Tonemap", "Uncharted 2", "Clamp", "Basic Tonemap" };
ImGui::Combo("ToneMap Mode", &m_toneMapModeSelected, toneMapItems, IM_ARRAYSIZE(toneMapItems));
ImGui::SliderFloat("Gamma", &m_gamma, 1.0f, 4.0f);

View File

@@ -10,41 +10,41 @@
#include "../maths.hpp"
glm::vec3 getNormal(glm::vec3 p0, glm::vec3 p1, glm::vec3 p2) {
glm::vec3 u = p1 - p0;
glm::vec3 v = p2 - p0;
glm::vec3 u = p1 - p0;
glm::vec3 v = p2 - p0;
glm::vec3 normal;
normal.x = u.y * v.z - u.z * v.y;
normal.y = u.z * v.x - u.x * v.z;
normal.z = u.x * v.y - u.y * v.x;
glm::vec3 normal;
normal.x = u.y * v.z - u.z * v.y;
normal.y = u.z * v.x - u.x * v.z;
normal.z = u.x * v.y - u.y * v.x;
return normal;
}
std::vector<Triangle*> LoadTrianglesBasic(std::string path, std::string basePath, Material* baseMaterial) {
tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials;
tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials;
std::string warn, err;
std::string warn, err;
bool canLoad = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, path.c_str(), basePath.c_str());
if (!err.empty() || !canLoad) {
std::cerr << "Cannot load obj: '" << path << "': " << err << std::endl;
exit(0);
exit(0);
}
if (!warn.empty()) {
std::cerr << "Warning from obj loader while loading obj: '" << path << "': " << warn << std::endl;
}
std::vector<Triangle*> triangles;
std::vector<Triangle*> triangles;
for (size_t s = 0; s < shapes.size(); s++) {
size_t index_offset = 0;
for (size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) {
int fv = shapes[s].mesh.num_face_vertices[f];
for (size_t s = 0; s < shapes.size(); s++) {
size_t index_offset = 0;
for (size_t f = 0; f < shapes[s].mesh.num_face_vertices.size(); f++) {
int fv = shapes[s].mesh.num_face_vertices[f];
if (fv == 3) {
tinyobj::real_t avx[3];
tinyobj::real_t avy[3];
@@ -77,30 +77,30 @@ std::vector<Triangle*> LoadTrianglesBasic(std::string path, std::string basePath
mtl = baseMaterial;
}
// glm::vec3 normal = getNormal(
// {avx[0], avy[0], avz[0]},
// {avx[1], avy[1], avz[1]},
// {avx[2], avy[2], avz[2]}
// );
// glm::vec3 normal = getNormal(
// {avx[0], avy[0], avz[0]},
// {avx[1], avy[1], avz[1]},
// {avx[2], avy[2], avz[2]}
// );
Triangle* tmp = new Triangle {
{avx[0], avy[0], avz[0]},
{avx[1], avy[1], avz[1]},
{avx[2], avy[2], avz[2]},
Triangle* tmp = new Triangle {
{avx[0], avy[0], avz[0]},
{avx[1], avy[1], avz[1]},
{avx[2], avy[2], avz[2]},
// normal, normal, normal
{anx[0], any[0], anz[0]},
{anx[1], any[1], anz[1]},
{anx[2], any[2], anz[2]},
// normal, normal, normal
{anx[0], any[0], anz[0]},
{anx[1], any[1], anz[1]},
{anx[2], any[2], anz[2]},
mtl,
};
};
triangles.push_back(tmp);
}
triangles.push_back(tmp);
}
index_offset += fv;
}
}
return triangles;
}
}
return triangles;
}

View File

@@ -21,7 +21,7 @@ int main(int argc, char** argv) {
Sky* sky = new GradientSky({ 35.0f / 255.0f, 148.0f / 255.0f, 235.0f / 255.0f }, { 1.0f, 1.0f, 1.0f }, 5.0f);
scene->sky = sky;
scene->camera = new Camera(width, height);
scene->camera = new Camera(width, height);
//Sphere sphere1({ 1.3f, -0.8f, -5.0f }, 0.2f, new Material({ 0.817f, 0.374, 0.574 }));
//scene->objects.push_back(&sphere1);
@@ -41,8 +41,8 @@ int main(int argc, char** argv) {
inferno.SetScene(scene);
inferno.Ready();
inferno.Render();
inferno.Ready();
inferno.Render();
return 0;
}

View File

@@ -2,8 +2,8 @@
#include "../src/inferno.hpp"
static const int width = 2000;
static const int height = 2000;
static const int width = 600;
static const int height = 600;
int main(int argc, char** argv) {
InfernoEngine inferno;
@@ -18,20 +18,23 @@ int main(int argc, char** argv) {
Sky* sky = new SolidSky({ 0.0f, 0.0f, 0.0f }, 0.0f);
scene->sky = sky;
Sphere* sphere = new Sphere({ -0.302, -0.385999, -3.74202 }, 0.03f, new Material({ 0.345f, 0.133f, 0.050f }, 300.0f, 0.0f, 0.0f, 0.0f, false, true));
scene->objects.push_back(sphere);
//Sphere* sphere = new Sphere({ -0.302, -0.385999, -3.74202 }, 0.03f, new Material({ 0.345f, 0.133f, 0.050f }, 300.0f, 0.0f, 0.0f, 0.0f, false, true));
//scene->objects.push_back(sphere);
Plane* plane = new Plane({ 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 1.0f }, new Material({ 1.0f, 1.0f, 1.0f }, 0.0f, 0.0f, 0.0f, 0.0f, false, false));
scene->objects.push_back(plane);
Material* mat = new GlossyMaterial({ 1.3f, 1.3f, 1.3f }, 0.2f, fastDegreetoRadian(30.0f));
std::vector<Triangle*> tris = LoadTrianglesBasic("E://Projects//Inferno//resources//models//dragon-cornell-size.obj", "E://Projects//Inferno//resources//models", mat);
//std::vector<Triangle*> tris = LoadTrianglesBasic("E://Projects//Inferno//resources//models//dragon-cornell-size.obj", "E://Projects//Inferno//resources//models", mat);
// std::vector<Triangle*> tris = LoadTrianglesBasic("/home/ben/programming/inferno/resources/models/dragon-cornell-size.obj", "/home/ben/programming/inferno/resources/models/", mat);
Mesh* mesh = new Mesh(tris);
mesh->Translate({ 0.01f, -1.0, -3.6f });
mesh->Optimise();
scene->meshs.push_back(mesh);
Sphere* sphere = new Sphere({ 0.0f, -0.6f, -4.0f }, 0.4f, mat);
scene->objects.push_back(sphere);
//Mesh* mesh = new Mesh(tris);
//mesh->Translate({ 0.01f, -1.0, -3.6f });
//mesh->Optimise();
//scene->meshs.push_back(mesh);
std::vector<Triangle*> tris1 = LoadTrianglesBasic("E://Projects//Inferno//resources//models//cornell-box.obj", "E://Projects//Inferno//resources//models//");
//std::vector<Triangle*> tris1 = LoadTrianglesBasic("/home/ben/programming/inferno/resources/models/cornell-box.obj", "/home/ben/programming/inferno/resources/models/");