TinyRenderer项目地址: Naive camera handling – Playing with code
旋转场景而不是相机,通过旋转矩阵将所有的顶点进行旋转,下述代码是将模型绕y轴旋转30°
vec3 rot(vec3 v) {
//旋转的角度(弧度) = 30°
constexpr double a = M_PI/6;
//旋转矩阵
const mat<3,3> Ry = {{{std::cos(a), 0, std::sin(a)}, {0,1,0}, {-std::sin(a), 0, std::cos(a)}}};
return Ry*v;
}
std::tuple<int,int,int> project(vec3 v) { // First of all, (x,y) is an orthogonal projection of the vector (x,y,z).
return { (v.x + 1.) * width/2, // Second, since the input models are scaled to have fit in the [-1,1]^3 world coordinates,
(v.y + 1.) * height/2, // we want to shift the vector (x,y) and then scale it to span the entire screen.
(v.z + 1.) * 255./2 };
}
int main(int argc, char** argv) {
Model model("african_head.obj");
TGAImage framebuffer(width, height, TGAImage::RGB);
TGAImage zbuffer(width, height, TGAImage::GRAYSCALE);
for (int i=0; i<model.nfaces(); i++) { // iterate through all triangles
auto [ax, ay, az] = project(rot(model.vert(i, 0)));
auto [bx, by, bz] = project(rot(model.vert(i, 1)));
auto [cx, cy, cz] = project(rot(model.vert(i, 2)));
TGAColor rnd;
for (int c=0; c<3; c++) rnd[c] = std::rand()%255;
triangle(ax, ay, az, bx, by, bz, cx, cy, cz, zbuffer, framebuffer, rnd);
}
framebuffer.write_tga_file("framebuffer.tga");
zbuffer.write_tga_file("zbuffer.tga");
return 0;
}

正交投影下,z轴的影响几乎可以忽略,相机的远近不会改变物体的大小。
透视投影下,物体会有近大远小的特点,看起来更真实。
对旋转后的定顶进行处理,使其被投射到z=0的平面上。

vec3 persp(vec3 v) {
//c是相机到z = 0的距离
constexpr double c = 3.;
return v / (1-v.z/c);
}
//...
auto [ax, ay, az] = project(persp(rot(model.vert(i, 0))));
auto [bx, by, bz] = project(persp(rot(model.vert(i, 1))));
auto [cx, cy, cz] = project(persp(rot(model.vert(i, 2))));
//...

可以看到正交投影和透视投影下得到的图像还是有些许不同的。正交投影下的图像更像是2D的平面,而透视投影下的图像更有立体感。
评论(0)
暂无评论