Repository navigation
Expand file tree
/
Copy pathsgl.cpp
More file actions
49 lines (41 loc) · 2.57 KB
/
Copy pathsgl.cpp
File metadata and controls
49 lines (41 loc) · 2.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <algorithm>
#include "sgl.h"
mat<4,4> ModelView, Viewport, Perspective; //state matrices for OpenGl
std::vector<double> zbuffer;
void lookat(const vec3 eye, const vec3 center, const vec3 up) {
vec3 n = normalized(eye-center);
vec3 l = normalized(cross(up,n));
vec3 m = normalized(cross(n, l));
ModelView = mat<4,4>{{{l.x,l.y,l.z,0}, {m.x,m.y,m.z,0}, {n.x,n.y,n.z,0}, {0,0,0,1}}} *
mat<4,4>{{{1,0,0,-center.x}, {0,1,0,-center.y}, {0,0,1,-center.z}, {0,0,0,1}}};
}
void init_perspective(const double f) {
Perspective = {{{1,0,0,0}, {0,1,0,0}, {0,0,1,0}, {0,0, -1/f,1}}};
}
void init_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 init_zbuffer(const int width, const int height){
zbuffer = std::vector<double>(width*height, -1000);
}
void rasterize(const Triangle &clip, const IShader &shader, TGAImage &framebuffer) {
vec4 ndc[3] = { clip[0]/clip[0].w, clip[1]/clip[1].w, clip[2]/clip[2].w }; // normalized device coordinates
vec2 screen[3] = { {(Viewport*ndc[0]).xy()}, {(Viewport*ndc[1]).xy()}, {(Viewport*ndc[2]).xy()}}; // screen coordinates
mat<3,3> ABC = {{ {screen[0].x, screen[0].y, 1.}, {screen[1].x, screen[1].y, 1.}, {screen[2].x, screen[2].y, 1.} }};
if (ABC.det()<1) return; // backface culling + discarding triangles that cover less than a pixel
auto [bbminx,bbmaxx] = std::minmax({screen[0].x, screen[1].x, screen[2].x}); // bounding box for the triangle
auto [bbminy,bbmaxy] = std::minmax({screen[0].y, screen[1].y, screen[2].y}); // defined by its top left and bottom right corners
#pragma omp parallel for
for (int x=std::max<int>(bbminx, 0); x<=std::min<int>(bbmaxx, framebuffer.width()-1); x++) { // clip the bounding box by the screen
for (int y=std::max<int>(bbminy, 0); y<=std::min<int>(bbmaxy, framebuffer.height()-1); y++) {
vec3 bc = ABC.invert_transpose() * vec3{static_cast<double>(x), static_cast<double>(y), 1.}; // barycentric coordinates of {x,y} w.r.t the triangle
if (bc.x<0 || bc.y<0 || bc.z<0) continue; // negative barycentric coordinate => the pixel is outside the triangle
double z = bc * vec3{ ndc[0].z, ndc[1].z, ndc[2].z };
if (z <= zbuffer[x+y*framebuffer.width()]) continue;
auto [discard, color] = shader.fragment(bc);
if (discard) continue;
zbuffer[x+y*framebuffer.width()] = z;
framebuffer.set(x,y,color);
}
}
}