diff --git a/includes/RT/ObjParser.hpp b/includes/RT/ObjParser.hpp index 19f04c0..cc53fd2 100644 --- a/includes/RT/ObjParser.hpp +++ b/includes/RT/ObjParser.hpp @@ -26,20 +26,22 @@ class ObjParser private: glm::vec3 getVertex(std::stringstream &line); glm::vec2 getUV(std::stringstream &line); + glm::vec3 getNormals(std::stringstream &line); void addFace(std::stringstream &line); long int checkVertexIndex(int index, size_t size); void parseMtl(std::stringstream &line, Scene &scene); - bool addTriangleFromPolygon(std::vector &vertices, std::vector &textureVertices, int inv); - void addTriangle(glm::vec3 v1, glm::vec3 v2, glm::vec3 v3, std::vector textureVertices); + bool addTriangleFromPolygon(std::vector &vertices, std::vector &textureVertices, std::vector &normalVertices, int inv); + void addTriangle(glm::vec3 v1, glm::vec3 v2, glm::vec3 v3, std::vector textureVertices, std::vector normalVertices); std::string getFilePath(std::string &file); int pointInTriangle(glm::vec3 pts[3], std::vector vertices, size_t cur); std::vector objSplit(std::string str, std::string delim); - void getFaceVertices(std::vector &faceVertices, std::vector &textureVertices, std::stringstream &line); + void getFaceVertices(std::vector &faceVertices, std::vector &textureVertices, std::vector &normalVertices, std::stringstream &line); std::string _filename; std::ifstream _file; std::vector _vertices; std::vector _textureVertices; + std::vector _normalVertices; int _mat; std::map _matNames; diff --git a/includes/RT/Scene.hpp b/includes/RT/Scene.hpp index 16122aa..f208ee1 100644 --- a/includes/RT/Scene.hpp +++ b/includes/RT/Scene.hpp @@ -38,11 +38,14 @@ struct GPUTriangle alignas(16) glm::vec3 position; alignas(16) glm::vec3 vertex1; alignas(16) glm::vec3 vertex2; - alignas(16) glm::vec3 normal; + + alignas(16) glm::vec3 normal_vertex1; + alignas(16) glm::vec3 normal_vertex2; + alignas(16) glm::vec3 normal_vertex3; - alignas(8) glm::vec2 texture_vertex1; - alignas(8) glm::vec2 texture_vertex2; - alignas(8) glm::vec2 texture_vertex3; + alignas(8) glm::vec2 texture_vertex1; + alignas(8) glm::vec2 texture_vertex2; + alignas(8) glm::vec2 texture_vertex3; int mat_index; }; diff --git a/includes/RT/objects/Triangle.hpp b/includes/RT/objects/Triangle.hpp index a6c1aa5..3f55454 100644 --- a/includes/RT/objects/Triangle.hpp +++ b/includes/RT/objects/Triangle.hpp @@ -52,12 +52,20 @@ class Triangle : public Object _mat_index = mat_index; } Triangle(const glm::vec3& position, const glm::vec3& vertex2, const glm::vec3& vertex3, - const glm::vec2& vt1, const glm::vec2& vt2, const glm::vec2& vt3, const int mat_index) + const glm::vec2& vt1, const glm::vec2& vt2, const glm::vec2& vt3, + const glm::vec3& vn1, const glm::vec3& vn2, const glm::vec3& vn3, + const int mat_index) : Object(position, mat_index), _vertex2(vertex2), _vertex3(vertex3), - _texture_vertex1(vt1), _texture_vertex2(vt2), _texture_vertex3(vt3) + _texture_vertex1(vt1), _texture_vertex2(vt2), _texture_vertex3(vt3), + _normal_vertex1(vn1), _normal_vertex2(vn2), _normal_vertex3(vn3) { - - _normal = glm::normalize(glm::cross(_vertex2 - _position, _vertex3 - _position)); //optimization + if (vn1 == glm::vec3(0.0f) && vn2 == glm::vec3(0.0f) && vn3 == glm::vec3(0.0f)) + { + glm::vec3 normal = glm::normalize(glm::cross(_vertex2 - _position, _vertex3 - _position)); + _normal_vertex1 = normal; + _normal_vertex2 = normal; + _normal_vertex3 = normal; + } _centroid = (_position + _vertex2 + _vertex3) / 3.0f; // _vertex2 -= _position; //optimization // _vertex3 -= _position; //optimization @@ -67,6 +75,10 @@ class Triangle : public Object const glm::vec2 &getTextureVertex2() const {return (_texture_vertex2); } const glm::vec2 &getTextureVertex3() const {return (_texture_vertex3); } + const glm::vec3 &getNormalVertex1() const {return (_normal_vertex1); } + const glm::vec3 &getNormalVertex2() const {return (_normal_vertex2); } + const glm::vec3 &getNormalVertex3() const {return (_normal_vertex3); } + const glm::vec3 &getVertex2() const { return (_vertex2); } const glm::vec3 &getVertex3() const { return (_vertex3); } const glm::vec3 &getNormal() const { return (_normal); } @@ -83,6 +95,10 @@ class Triangle : public Object glm::vec2 _texture_vertex2; glm::vec2 _texture_vertex3; + glm::vec3 _normal_vertex1; + glm::vec3 _normal_vertex2; + glm::vec3 _normal_vertex3; + glm::vec3 _normal; glm::vec3 _centroid; diff --git a/scenes/test.rt b/scenes/test.rt index ba8a3e9..051f89b 100644 --- a/scenes/test.rt +++ b/scenes/test.rt @@ -7,5 +7,5 @@ MAT 255 255 255 1.0 0.0 0.0 LAM 0 // 1 # sp 0 2 0 150 1 # pl 0 0 0 0 1 0 0 -OBJ obj/castle.obj +OBJ obj/lambo2.obj 0 0 0 0.25 diff --git a/shaders/debug.glsl b/shaders/debug.glsl index 4b98fec..2c13c06 100644 --- a/shaders/debug.glsl +++ b/shaders/debug.glsl @@ -55,7 +55,10 @@ struct GPUTriangle vec3 position; vec3 vertex1; vec3 vertex2; - vec3 normal; + + vec3 normal_vertex1; + vec3 normal_vertex2; + vec3 normal_vertex3; vec2 texture_vertex1; vec2 texture_vertex2; @@ -189,7 +192,8 @@ hitInfo traceBVH(Ray ray, GPUBvhData bvh_data, inout Stats stats) { hit.t = temp_hit.t; hit.obj_index = bvh_data.triangle_start_index + node.index + i; - hit.normal = temp_hit.normal; + hit.u = temp_hit.u; + hit.v = temp_hit.v; } } } @@ -260,8 +264,9 @@ hitInfo traverseBVHs(Ray ray, inout Stats stats) vec3 position = transformedRay.origin + transformedRay.direction * temp_hit.t; hit.position = inverseTransformMatrix * position + bvh_data.offset; - vec3 based_normal = triangle.normal * sign(-dot(transformedRay.direction, triangle.normal)); - hit.normal = normalize(inverseTransformMatrix * based_normal); + vec3 normal = normalize(triangle.normal_vertex1 * (1.0 - hit.u - hit.v) + triangle.normal_vertex2 * hit.u + triangle.normal_vertex3 * hit.v); + vec3 directed_normal = normal * sign(-dot(transformedRay.direction, normal)); + hit.normal = normalize(inverseTransformMatrix * directed_normal); } } diff --git a/shaders/denoising.glsl b/shaders/denoising.glsl index ed01523..4845e8d 100644 --- a/shaders/denoising.glsl +++ b/shaders/denoising.glsl @@ -68,6 +68,7 @@ void main() } } light *= (1.0 / totalWeight); + light.a = 1.0; if (u_pass == u_pass_count - 1) { vec4 color = light * imageLoad(color_texture, pixel_coords); diff --git a/shaders/intersect.glsl b/shaders/intersect.glsl index 3623cba..23fe42a 100644 --- a/shaders/intersect.glsl +++ b/shaders/intersect.glsl @@ -102,10 +102,6 @@ bool intersectTriangle(Ray ray, GPUTriangle obj, out hitInfo hit) hit.v >= 0.0 && (hit.u + hit.v) <= 1.0 && hit.t > 0.0; - // hit.position = ray.origin + ray.direction * t; - // hit.normal = obj.normal * sign(-dot(ray.direction, obj.normal)); - // hit.normal = vec3(u, v, 1 - (u + v)); //texture mapping - return (valid); } @@ -114,7 +110,6 @@ bool intersectTriangle(Ray ray, GPUObject obj, out hitInfo hit) GPUTriangle tri; tri.position = obj.position; - tri.normal = obj.normal; tri.vertex1 = obj.vertex1; tri.vertex2 = obj.vertex2; diff --git a/shaders/raytracing.glsl b/shaders/raytracing.glsl index afaa8bc..e94eda5 100644 --- a/shaders/raytracing.glsl +++ b/shaders/raytracing.glsl @@ -30,7 +30,10 @@ struct GPUTriangle vec3 position; vec3 vertex1; vec3 vertex2; - vec3 normal; + + vec3 normal_vertex1; + vec3 normal_vertex2; + vec3 normal_vertex3; vec2 texture_vertex1; vec2 texture_vertex2; @@ -202,10 +205,10 @@ vec3[2] pathtrace(Ray ray, inout uint rng_state) if (i == 0) { - imageStore(normal_texture, ivec2(gl_GlobalInvocationID.xy), vec4(normalize(hit.normal), 1.0)); - imageStore(position_texture, ivec2(gl_GlobalInvocationID.xy), vec4(normalize(hit.position), 1.0)); - // vec4 accum_normal = accumulate(normal_texture, accum_normal, normalize(hit.normal)); - // vec4 accum_position = accumulate(position_texture, accum_position, normalize(hit.position)); + // imageStore(normal_texture, ivec2(gl_GlobalInvocationID.xy), vec4(normalize(hit.normal), 1.0)); + // imageStore(position_texture, ivec2(gl_GlobalInvocationID.xy), vec4(normalize(hit.position), 1.0)); + vec4 accum_normal = accumulate(normal_texture, accum_normal, normalize(hit.normal)); + vec4 accum_position = accumulate(position_texture, accum_position, normalize(hit.position)); } float p = max(color.r, max(color.g, color.b)); diff --git a/shaders/trace.glsl b/shaders/trace.glsl index 2f4b011..25a3725 100644 --- a/shaders/trace.glsl +++ b/shaders/trace.glsl @@ -157,8 +157,9 @@ hitInfo traverseBVHs(Ray ray) vec3 position = transformedRay.origin + transformedRay.direction * temp_hit.t; hit.position = inverseTransformMatrix * position + bvh_data.offset; - vec3 based_normal = triangle.normal * sign(-dot(transformedRay.direction, triangle.normal)); - hit.normal = normalize(inverseTransformMatrix * based_normal); + vec3 normal = normalize(triangle.normal_vertex1 * (1.0 - hit.u - hit.v) + triangle.normal_vertex2 * hit.u + triangle.normal_vertex3 * hit.v); + vec3 directed_normal = normal * sign(-dot(transformedRay.direction, normal)); + hit.normal = normalize(inverseTransformMatrix * directed_normal); } } diff --git a/srcs/class/ObjParser.cpp b/srcs/class/ObjParser.cpp index 5ca6145..7eb3fa0 100644 --- a/srcs/class/ObjParser.cpp +++ b/srcs/class/ObjParser.cpp @@ -58,6 +58,15 @@ glm::vec2 ObjParser::getUV(std::stringstream &line) return(res); } +glm::vec3 ObjParser::getNormals(std::stringstream &line) +{ + glm::vec3 res; + + if(!(line >> res.x) || !(line >> res.y) || (!(line >> res.z)) && !line.eof()) + throw std::runtime_error("syntax error in obj file while parsing normal vertex"); + return(res); +} + long int ObjParser::checkVertexIndex(int index, size_t size) { if((size_t)index > size || index == 0 || (index < 0 && (size_t)(-index) > size)) @@ -97,10 +106,11 @@ int ObjParser::pointInTriangle(glm::vec3 pts[3], std::vector vertices return(0); } -bool ObjParser::addTriangleFromPolygon(std::vector &vertices, std::vector &textureVertices, int inv) +bool ObjParser::addTriangleFromPolygon(std::vector &vertices, std::vector &textureVertices, std::vector &normalVertices, int inv) { glm::vec3 v1, v2, v3; glm::vec2 vt1, vt2, vt3; + glm::vec3 vn1, vn2, vn3; float dot; @@ -110,11 +120,13 @@ bool ObjParser::addTriangleFromPolygon(std::vector &vertices, std::ve { v1 = vertices.back(); vt1 = textureVertices.back(); + vn1 = normalVertices.back(); } else { v1 = vertices[i - 1]; vt1 = textureVertices[i - 1]; + vn1 = normalVertices[i - 1]; } v2 = vertices[i]; v3 = vertices[(i + 1) % vertices.size()]; @@ -122,6 +134,9 @@ bool ObjParser::addTriangleFromPolygon(std::vector &vertices, std::ve vt2 = textureVertices[i]; vt3 = textureVertices[(i + 1) % textureVertices.size()]; + vn2 = normalVertices[i]; + vn3 = normalVertices[(i + 1) % normalVertices.size()]; + if (inv) dot = glm::cross(v2 - v1, v2 - v3).z; else @@ -133,14 +148,19 @@ bool ObjParser::addTriangleFromPolygon(std::vector &vertices, std::ve continue; vertices.erase(vertices.begin() + i); textureVertices.erase(textureVertices.begin() + i); - + normalVertices.erase(normalVertices.begin() + i); std::vector texture; texture.push_back(vt1); texture.push_back(vt2); texture.push_back(vt3); - addTriangle(v1, v2, v3, texture); + std::vector normals; + normals.push_back(vn1); + normals.push_back(vn2); + normals.push_back(vn3); + + addTriangle(v1, v2, v3, texture, normals); return(1); } return(0); @@ -159,7 +179,7 @@ std::vector ObjParser::objSplit(std::string str, std::string delim) return(res); } -void ObjParser::getFaceVertices(std::vector &faceVertices, std::vector &textureVertices, std::stringstream &line) +void ObjParser::getFaceVertices(std::vector &faceVertices, std::vector &textureVertices, std::vector &normalVertices, std::stringstream &line) { std::string el; std::vector sp; @@ -174,6 +194,9 @@ void ObjParser::getFaceVertices(std::vector &faceVertices, std::vecto if (sp.size() > 1 && sp[1].length()) textureVertices.push_back(_textureVertices[checkVertexIndex(std::stoi(sp[1]), _textureVertices.size())]); + if (sp.size() > 2 && sp[2].length()) + normalVertices.push_back(_normalVertices[checkVertexIndex(std::stoi(sp[2]), _normalVertices.size())]); + faceVertices.push_back(_vertices[checkVertexIndex(std::stoi(sp[0]), _vertices.size())]); } } @@ -182,29 +205,34 @@ void ObjParser::addFace(std::stringstream &line) { std::vector faceVertices; std::vector textureVertices; + std::vector normalVertices; - getFaceVertices(faceVertices, textureVertices, line); + getFaceVertices(faceVertices, textureVertices, normalVertices, line); if(!line.eof()) throw std::runtime_error("OBJ : an error occured while paring face"); if(faceVertices.size() < 3) throw std::runtime_error("OBJ : face does not have enough vertices"); while(faceVertices.size() > 3) - if (!addTriangleFromPolygon(faceVertices, textureVertices, 0)) - if(!addTriangleFromPolygon(faceVertices, textureVertices, 1)) + if (!addTriangleFromPolygon(faceVertices, textureVertices, normalVertices, 0)) + if(!addTriangleFromPolygon(faceVertices, textureVertices, normalVertices, 1)) return ; if(!line.eof()) throw std::runtime_error("OBJ: an error occured while parsing face"); - addTriangle(faceVertices[0], faceVertices[1], faceVertices[2], textureVertices); + addTriangle(faceVertices[0], faceVertices[1], faceVertices[2], textureVertices, normalVertices); } -void ObjParser::addTriangle(glm::vec3 v1, glm::vec3 v2, glm::vec3 v3, std::vector texture_vertices) +void ObjParser::addTriangle(glm::vec3 v1, glm::vec3 v2, glm::vec3 v3, std::vector texture_vertices, std::vector normal_vertices) { glm::vec2 vt1 = glm::vec2(0.); glm::vec2 vt2 = glm::vec2(0.); glm::vec2 vt3 = glm::vec2(0.); + glm::vec3 vn1 = glm::vec3(0.); + glm::vec3 vn2 = glm::vec3(0.); + glm::vec3 vn3 = glm::vec3(0.); + if (texture_vertices.size() == 3) { vt1 = texture_vertices[0]; @@ -212,7 +240,14 @@ void ObjParser::addTriangle(glm::vec3 v1, glm::vec3 v2, glm::vec3 v3, std::vecto vt3 = texture_vertices[2]; } - _triangles.push_back(Triangle(v1, v2, v3, vt1, vt2, vt3, _mat)); + if (normal_vertices.size() == 3) + { + vn1 = glm::normalize(normal_vertices[0]); + vn2 = glm::normalize(normal_vertices[1]); + vn3 = glm::normalize(normal_vertices[2]); + } + + _triangles.push_back(Triangle(v1, v2, v3, vt1, vt2, vt3, vn1, vn2, vn3, _mat)); } void ObjParser::parseMtl(std::stringstream &input_line, Scene &scene) @@ -286,7 +321,9 @@ void ObjParser::parseMtl(std::stringstream &input_line, Scene &scene) float x, y, z; if(!(lineStream >> x >> y >> z)) throw std::runtime_error("OBJ: syntax error while getting material emission"); - mat->emission = (x + y + z) / 3; + if (mat->color == glm::vec3(0.0f)) + mat->color = glm::vec3(x, y, z); + mat->emission = (x + y + z); } else if(identifier == "Ni") { @@ -384,6 +421,8 @@ void ObjParser::parse(Scene &scene, glm::vec3 offset, float scale, glm::mat4 tra _vertices.push_back(getVertex(lineStream)); else if (identifier == "vt") _textureVertices.push_back(getUV(lineStream)); + else if (identifier == "vn") + _normalVertices.push_back(getNormals(lineStream)); else if (identifier == "f") addFace(lineStream); else if (identifier == "mtllib") diff --git a/srcs/class/Scene.cpp b/srcs/class/Scene.cpp index 342553d..6258d27 100644 --- a/srcs/class/Scene.cpp +++ b/srcs/class/Scene.cpp @@ -109,17 +109,7 @@ void Scene::addObject(Object *obj) } else if (obj->getType() == Object::Type::TRIANGLE) { - GPUTriangle gpu_triangle; - auto triangle = static_cast(obj); - gpu_triangle.position = triangle->getPosition(); - gpu_triangle.mat_index = triangle->getMaterialIndex(); - - gpu_triangle.vertex1 = triangle->getVertex2(); - gpu_triangle.vertex2 = triangle->getVertex3(); - gpu_triangle.normal = triangle->getNormal(); - - _gpu_triangles.push_back(gpu_triangle); gpu_obj.vertex1 = triangle->getVertex2(); gpu_obj.vertex2 = triangle->getVertex3(); @@ -182,12 +172,15 @@ void Scene::addBvh(std::vector &triangles, glm::vec3 offset, float sc gpu_triangle.vertex1 = triangles[i].getVertex2(); gpu_triangle.vertex2 = triangles[i].getVertex3(); - gpu_triangle.normal = triangles[i].getNormal(); gpu_triangle.texture_vertex1 = triangles[i].getTextureVertex1(); gpu_triangle.texture_vertex2 = triangles[i].getTextureVertex2(); gpu_triangle.texture_vertex3 = triangles[i].getTextureVertex3(); + gpu_triangle.normal_vertex1 = triangles[i].getNormalVertex1(); + gpu_triangle.normal_vertex2 = triangles[i].getNormalVertex2(); + gpu_triangle.normal_vertex3 = triangles[i].getNormalVertex3(); + _gpu_triangles.push_back(gpu_triangle); }