From d5355f5d23b5bb3ca82eb7c02702c870f5fc1c29 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Sokolov" Date: Tue, 25 Aug 2020 17:32:33 +0200 Subject: [PATCH] polishing --- main.cpp | 10 ++++------ our_gl.cpp | 42 +++++++++++++++++------------------------- our_gl.h | 2 +- 3 files changed, 22 insertions(+), 32 deletions(-) diff --git a/main.cpp b/main.cpp index 19708d96..933d42e1 100644 --- a/main.cpp +++ b/main.cpp @@ -18,7 +18,6 @@ struct Shader : IShader { const Model &model; vec3 l; // light direction in normalized device coordinates mat<2,3> varying_uv; // triangle uv coordinates, written by the vertex shader, read by the fragment shader - mat<4,3> varying_tri; // triangle coordinates (clip coordinates), written by VS, read by FS mat<3,3> varying_nrm; // normal per vertex to be interpolated by FS mat<3,3> ndc_tri; // triangle in normalized device coordinates @@ -30,7 +29,6 @@ struct Shader : IShader { varying_uv.set_col(nthvert, model.uv(iface, nthvert)); varying_nrm.set_col(nthvert, proj<3>((Projection*ModelView).invert_transpose()*embed<4>(model.normal(iface, nthvert), 0.))); vec4 gl_Vertex = Projection*ModelView*embed<4>(model.vert(iface, nthvert)); - varying_tri.set_col(nthvert, gl_Vertex); ndc_tri.set_col(nthvert, proj<3>(gl_Vertex/gl_Vertex[3])); return gl_Vertex; } @@ -41,7 +39,6 @@ struct Shader : IShader { // for the math refer to the tangent space normal mapping lecture // https://github.com/ssloy/tinyrenderer/wiki/Lesson-6bis-tangent-space-normal-mapping - mat<3,3> AI = mat<3,3>{ {ndc_tri.col(1) - ndc_tri.col(0), ndc_tri.col(2) - ndc_tri.col(0), bn} }.invert(); vec3 i = AI * vec3(varying_uv[0][1] - varying_uv[0][0], varying_uv[0][2] - varying_uv[0][0], 0); vec3 j = AI * vec3(varying_uv[1][1] - varying_uv[1][0], varying_uv[1][2] - varying_uv[1][0], 0); @@ -50,7 +47,7 @@ struct Shader : IShader { vec3 n = (B * model.normal(uv)).normalize(); // transform the normal from the texture to the tangent space double diff = std::max(0., n*l); // diffuse light intensity - vec3 r = (n*(n*l)*2 - l).normalize(); // reflected light direction + vec3 r = (n*(n*l)*2 - l).normalize(); // reflected light direction, specular mapping is described here: https://github.com/ssloy/tinyrenderer/wiki/Lesson-6-Shaders-for-the-software-renderer double spec = std::pow(std::max(r.z, 0.), 5+model.specular(uv)); // specular intensity, note that the camera lies on the z-axis (in ndc), therefore simple r.z TGAColor c = model.diffuse(uv); @@ -77,9 +74,10 @@ int main(int argc, char** argv) { Model model(argv[m]); Shader shader(model); for (int i=0; i Minv = mat<4,4>::identity(); - mat<4,4> Tr = mat<4,4>::identity(); - for (int i=0; i<3; i++) { - Minv[0][i] = x[i]; - Minv[1][i] = y[i]; - Minv[2][i] = z[i]; - Tr[i][3] = -center[i]; - } + vec3 x = cross(up,z).normalize(); + vec3 y = cross(z, x).normalize(); + mat<4,4> Minv = {{{x.x,x.y,x.z,0}, {y.x,y.y,y.z,0}, {z.x,z.y,z.z,0}, {0,0,0,1}}}; + mat<4,4> Tr = {{{1,0,0,-center.x}, {0,1,0,-center.y}, {0,0,1,-center.z}, {0,0,0,1}}}; ModelView = Minv*Tr; } -vec3 barycentric(const vec2 A, const vec2 B, const vec2 C, const vec2 P) { - mat<3,3> ABC = {{embed<3>(A), embed<3>(B), embed<3>(C)}}; +vec3 barycentric(const vec2 tri[3], const vec2 P) { + mat<3,3> ABC = {{embed<3>(tri[0]), embed<3>(tri[1]), embed<3>(tri[2])}}; if (ABC.det()<1e-3) return vec3(-1,1,1); // for a degenerate triangle generate negative coordinates, it will be thrown away by the rasterizator return ABC.invert_transpose() * embed<3>(P); } -void triangle(const mat<4,3> &clipc, IShader &shader, TGAImage &image, std::vector &zbuffer) { - mat<3,4> pts = (Viewport*clipc).transpose(); // transposed to ease access to each of the points - mat<3,2> pts2; - for (int i=0; i<3; i++) pts2[i] = proj<2>(pts[i]/pts[i][3]); +void triangle(const vec4 clip_verts[3], IShader &shader, TGAImage &image, std::vector &zbuffer) { + vec4 pts[3] = { Viewport*clip_verts[0], Viewport*clip_verts[1], Viewport*clip_verts[2] }; // triangle screen coordinates before persp. division + vec2 pts2[3] = { proj<2>(pts[0]/pts[0][3]), proj<2>(pts[1]/pts[1][3]), proj<2>(pts[2]/pts[2][3]) }; // triangle screen coordinates after perps. division vec2 bboxmin( std::numeric_limits::max(), std::numeric_limits::max()); vec2 bboxmax(-std::numeric_limits::max(), -std::numeric_limits::max()); @@ -50,17 +43,16 @@ void triangle(const mat<4,3> &clipc, IShader &shader, TGAImage &image, std::vect #pragma omp parallel for for (int x=(int)bboxmin.x; x<=(int)bboxmax.x; x++) { for (int y=(int)bboxmin.y; y<=(int)bboxmax.y; y++) { - vec3 bc_screen = barycentric(pts2[0], pts2[1], pts2[2], {(double)x, (double)y}); + vec3 bc_screen = barycentric(pts2, vec2(x, y)); vec3 bc_clip = vec3(bc_screen.x/pts[0][3], bc_screen.y/pts[1][3], bc_screen.z/pts[2][3]); - bc_clip = bc_clip/(bc_clip.x+bc_clip.y+bc_clip.z); - double frag_depth = clipc[2]*bc_clip; + bc_clip = bc_clip/(bc_clip.x+bc_clip.y+bc_clip.z); // check https://github.com/ssloy/tinyrenderer/wiki/Technical-difficulties-linear-interpolation-with-perspective-deformations + double frag_depth = vec3(clip_verts[0][2], clip_verts[1][2], clip_verts[2][2])*bc_clip; if (bc_screen.x<0 || bc_screen.y<0 || bc_screen.z<0 || zbuffer[x+y*image.get_width()]>frag_depth) continue; TGAColor color; bool discard = shader.fragment(bc_clip, color); - if (!discard) { - zbuffer[x+y*image.get_width()] = frag_depth; - image.set(x, y, color); - } + if (discard) continue; + zbuffer[x+y*image.get_width()] = frag_depth; + image.set(x, y, color); } } } diff --git a/our_gl.h b/our_gl.h index 85763ff5..01e42e77 100644 --- a/our_gl.h +++ b/our_gl.h @@ -12,6 +12,6 @@ struct IShader { virtual bool fragment(const vec3 bar, TGAColor &color) = 0; }; -void triangle(const mat<4,3> &pts, IShader &shader, TGAImage &image, std::vector &zbuffer); +void triangle(const vec4 clip_verts[3], IShader &shader, TGAImage &image, std::vector &zbuffer); #endif //__OUR_GL_H__