Skip to content

Commit

Permalink
polishing
Browse files Browse the repository at this point in the history
  • Loading branch information
ssloy committed Aug 25, 2020
1 parent 677595f commit d5355f5
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 32 deletions.
10 changes: 4 additions & 6 deletions main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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;
}
Expand All @@ -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);
Expand All @@ -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);
Expand All @@ -77,9 +74,10 @@ int main(int argc, char** argv) {
Model model(argv[m]);
Shader shader(model);
for (int i=0; i<model.nfaces(); i++) { // for every triangle
vec4 clip_vert[3]; // triangle coordinates (clip coordinates), written by VS, read by FS
for (int j=0; j<3; j++)
shader.vertex(i, j); // call the vertex shader for each triangle vertex
triangle(shader.varying_tri, shader, framebuffer, zbuffer); // actual rasterization routine call
clip_vert[j] = shader.vertex(i, j); // call the vertex shader for each triangle vertex
triangle(clip_vert, shader, framebuffer, zbuffer); // actual rasterization routine call
}
}
framebuffer.write_tga_file("framebuffer.tga"); // the vertical flip is moved inside the function
Expand Down
42 changes: 17 additions & 25 deletions our_gl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,28 @@ void viewport(const int x, const int y, const int w, const int h) {
Viewport = {{{w/2., 0, 0, x+w/2.}, {0, h/2., 0, y+h/2.}, {0,0,1,0}, {0,0,0,1}}};
}

void projection(const double coeff) {
void projection(const double coeff) { // check https://github.com/ssloy/tinyrenderer/wiki/Lesson-4-Perspective-projection
Projection = {{{1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {0,0,coeff,1}}};
}

void lookat(const vec3 eye, const vec3 center, const vec3 up) {
void lookat(const vec3 eye, const vec3 center, const vec3 up) { // check https://github.com/ssloy/tinyrenderer/wiki/Lesson-5-Moving-the-camera
vec3 z = (eye-center).normalize();
vec3 x = cross(up,z).normalize();
vec3 y = cross(z,x).normalize();
mat<4,4> 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<double> &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<double> &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<double>::max(), std::numeric_limits<double>::max());
vec2 bboxmax(-std::numeric_limits<double>::max(), -std::numeric_limits<double>::max());
Expand All @@ -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);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion our_gl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<double> &zbuffer);
void triangle(const vec4 clip_verts[3], IShader &shader, TGAImage &image, std::vector<double> &zbuffer);
#endif //__OUR_GL_H__

0 comments on commit d5355f5

Please sign in to comment.