计算机图形学入门踩坑记录2
0.前言
正在学习实现一个渲染器tinyrenderer,现记录如下, ssloy/tinyrenderer 链接: 目标github地址
上次看公式看了半天,最后整明白cross()函数计算的给定点对应三角形顶点的分量(一个0-1的比例);这次又碰见一个棘手的问题:第三节最后给出了一个课后题,用已有的贴图,贴在模型上。
1.不明白的地方
题主简要的介绍了几个概念:
1.字母f代表face 一个面(三角形),后面跟着的数字代表序号
2.依次为:顶点序号/纹理序号/?(第三个还没学到)
3.对应字母: v/vt/?
4.v 顶点的三维位置(从-1到1的float,可以与分辨率相乘放大)
5.vt 对应顶点的u v值,即图四中的前两个值,使用已有的函数,传入uv值后可以计算出颜色值
TGAColor Model::diffuse(Vec2f uvf) {
Vec2i uv(uvf[0] * diffusemap_.get_width(), uvf[1] * diffusemap_.get_height());
return diffusemap_.get(uv[0], uv[1]);
}//数据来自读入的文件,具体参照源码
2.解析
题主在源码中并没有给出如何贴上纹理,只用语言描述了如图一的原理。
以下为我自己的理解分析:
1.纹理的填充,根据三个顶点的纹理坐标,计算出三角形中所有像素点的纹理坐标,具体方法为使用3个比例值*3个纹理坐标,得到一个新的纹理坐标(u,v)带入可得到颜色。
2.由1倒推,要得到3个纹理坐标和3个比例值(上节已给出如何计算比例),源码中model.cpp中加入如下函数即可提取到每一点uv的值,对比之前提取点的三维坐标好理解些。
std::vector<int> Model::face(int idx) {
std::vector<int> face;
for (int i = 0; i < (int)faces_[idx].size(); i++)
face.push_back(faces_[idx][i][0]);
return face;
}//获取点的3个坐标序号(前几节已经使用过了)
std::vector<int> Model::uvt(int idx) {
std::vector<int> uv;
for (int i = 0; i < (int)faces_[idx].size(); i++)
//注意这里序号为1 对应了前边图二中斜杠处的一个偏移量
uv.push_back(faces_[idx][i][1]);
return uv;
}//获取3个纹理坐标序号(本节课后题使用)
//使用上边的结果
std::vector<int> uvt = model->uvt(i);
Vec2f uv = model->uv(uvt[i]);//这里省略了一个for循环
得到了uv值再用diffuse函数,即可得到对应的TGAcolor(用3个顶点的uv值,在填充三角形时计算得到三角形内部的每一个点的uv值,即可得到对应点的颜色值)。
3.不足之处
要想得到题主的效果,需要再计算得到颜色值后只使用其中的rgb值,否则就会像这样,看不到模型的三角形边缘了(猜测TGAcolor中的第四个值有这样的效果):