-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathour_gl.cpp
More file actions
49 lines (41 loc) · 2.78 KB
/
Copy pathour_gl.cpp
File metadata and controls
49 lines (41 loc) · 2.78 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 "our_gl.h"
mat<4,4> ModelView, Viewport, Perspective; // “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(width*height, -1000.);
}
void rasterize(const Triangle &clip, const IShader &shader, TGAImage &framebuffer, std::vector<double> &zbuffer) {
vec4 ndc[3] = { clip[0]/clip[0].w, clip[1]/clip[1].w, clip[2]/clip[2].w }; // 归一化设备坐标
vec2 screen[3] = { (Viewport*ndc[0]).xy(), (Viewport*ndc[1]).xy(), (Viewport*ndc[2]).xy() }; // 屏幕坐标
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; // 背面剔除 + 丢弃覆盖面积小于1像素的三角形
auto [bbminx,bbmaxx] = std::minmax({screen[0].x, screen[1].x, screen[2].x}); // 三角形外接包围盒
auto [bbminy,bbmaxy] = std::minmax({screen[0].y, screen[1].y, screen[2].y}); // 由左上角和右下角定义
#pragma omp parallel for
for (int x=std::max<int>(bbminx, 0); x<=std::min<int>(bbmaxx, framebuffer.width()-1); x++) { // 用屏幕边界裁剪包围盒
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.}; // 点 {x,y} 相对三角形的重心坐标
if (bc.x<0 || bc.y<0 || bc.z<0) continue; // 重心坐标为负表示像素在三角形外
double z = bc * vec3{ ndc[0].z, ndc[1].z, ndc[2].z }; // 深度线性插值
if (z <= zbuffer[x+y*framebuffer.width()]) continue; // 与 z-buffer 比较,丢弃更深片元
auto [discard, color] = shader.fragment(bc);
if (discard) continue; // 片元着色器可主动丢弃当前片元
zbuffer[x+y*framebuffer.width()] = z; // 更新 z-buffer
framebuffer.set(x, y, color); // 更新帧缓冲
}
}
}