# 渲染金字塔，并添加纹理

·  阅读 74

#### 解析

• 我们将金字塔转换到我们的坐标系中

``````{
0.0, 1.0, 0.0,
-1.0, -1.0, -1.0,
-1.0, -1.0, 1.0
}

• 我们再看△ODA和底部△DAB，△BCD对应的纹理坐标 这里因为构成的三角形不同，所以同一个点，对应的纹理坐标可能是不一样的，因为每个点都会在不同的三角形中使用，△DAB中点A的纹理坐标是`(1,0)`,但在△DAB中点A的纹理坐标是`(0,0)`。 利用批次类依次录入各个顶点和对应的纹理坐标
``````    /*1、通过pyramidBatch组建三角形批次
参数1：类型
参数2：顶点数
参数3：这个批次中将会应用1个纹理
注意：如果不写这个参数，默认为0。
*/
pyramidBatch.Begin(GL_TRIANGLES, 18, 1);

/***前情导入

2)设置纹理坐标
void MultiTexCoord2f(GLuint texture, GLclampf s, GLclampf t);
参数1：texture，纹理层次，对于使用存储着色器来进行渲染，设置为0
参数2：s：对应顶点坐标中的x坐标
参数3：t:对应顶点坐标中的y
(s,t,r,q对应顶点坐标的x,y,z,w)

pyramidBatch.MultiTexCoord2f(0,s,t);

3)void Vertex3f(GLfloat x, GLfloat y, GLfloat z);
void Vertex3fv(M3DVector3f vVertex);
向三角形批次类添加顶点数据(x,y,z);
pyramidBatch.Vertex3f(-1.0f, -1.0f, -1.0f);

*/

//塔顶
M3DVector3f pointO = {0.0f, 1.0f, 0.0f};
M3DVector3f pointA = {-1.0f, -1.0f, 1.0f};
M3DVector3f pointB = {1.0f, -1.0f, 1.0f};
M3DVector3f pointD = {-1.0f, -1.0f, -1.0f};
M3DVector3f pointC = {1.0f, -1.0f, -1.0f};

//金字塔底部
//底部的四边形 = △DAB + △BCD
//△DAB = (pointD,pointA,pointB)
//pointD
pyraminBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
pyramidBatch.Vertex3fv(pointD);

//pointA
pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(pointA);

//pointB
pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(pointB);

//△BCD =(pointB,pointC,pointD)
//pointB
pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(pointB);

//pointC
pyramidBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
pyramidBatch.Vertex3fv(pointC);

//pointD
pyramidBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
pyramidBatch.Vertex3fv(pointD);

// 金字塔前面
//△OAB：（pointO，pointA，pointB）
pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
pyramidBatch.Vertex3fv(pointO);

pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(pointA);

pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(pointB);

//金字塔左边
//△ODA：（pointO, pointD, pointA）
pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
pyramidBatch.Vertex3fv(pointO);

pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(pointD);

pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(pointA);

//金字塔右边
//△OBC：（pointO, pointB, pointC）
pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
pyramidBatch.Vertex3fv(pointO);

pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(pointB);

pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(pointC);

//金字塔后边
//△OCD：（pointO, pointC, pointD）
pyramidBatch.MultiTexCoord2f(0, 0.5f, 1.0f);
pyramidBatch.Vertex3fv(pointO);

pyramidBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
pyramidBatch.Vertex3fv(pointC);

pyramidBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
pyramidBatch.Vertex3fv(pointD);

//结束批次设置
pyramidBatch.End();

• 我们利用自定义函数`bool LoadTGATexture(const char *szFileName, GLenum minFilter, GLenum magFilter, GLenum wrapMode)`来将TGA文件加载为2D纹理。内部实现如下:
``````    GLbyte *pBits;
int nWidth, nHeight, nComponents;
GLenum eFormat;

//1、读纹理位，读取像素
//参数1：纹理文件名称
//参数2：文件宽度地址
//参数3：文件高度地址
//参数4：文件组件地址
//参数5：文件格式地址
//返回值：pBits,指向图像数据的指针

pBits = gltReadTGABits(szFileName, &nWidth, &nHeight, &nComponents, &eFormat);
if(pBits == NULL)
return false;

//2、设置纹理参数
//参数1：纹理维度
//参数2：为S/T坐标设置模式
//参数3：wrapMode,环绕模式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode);

//参数1：纹理维度
//参数2：线性过滤
//参数3: 缩小/放大过滤方式.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter);

//3.载入纹理
//参数1：纹理维度
//参数2：mip贴图层次
//参数3：纹理单元存储的颜色成分（从读取像素图是获得）
//参数4：加载纹理宽
//参数5：加载纹理高
//参数6：加载纹理的深度
//参数7：像素数据的数据类型（GL_UNSIGNED_BYTE，每个颜色分量都是一个8位无符号整数）
//参数8：指向纹理图像数据的指针

glTexImage2D(GL_TEXTURE_2D, 0, nComponents, nWidth, nHeight, 0,
eFormat, GL_UNSIGNED_BYTE, pBits);
//使用完毕释放pBits
free(pBits);

//只有minFilter 等于以下四种模式，才可以生成Mip贴图
//GL_NEAREST_MIPMAP_NEAREST具有非常好的性能，并且闪烁现象非常弱
//GL_LINEAR_MIPMAP_NEAREST常常用于对游戏进行加速，它使用了高质量的线性过滤器
//GL_LINEAR_MIPMAP_LINEAR 和GL_NEAREST_MIPMAP_LINEAR 过滤器在Mip层之间执行了一些额外的插值，以消除他们之间的过滤痕迹。
//GL_LINEAR_MIPMAP_LINEAR 三线性Mip贴图。纹理过滤的黄金准则，具有最高的精度。
if(minFilter == GL_LINEAR_MIPMAP_LINEAR ||
minFilter == GL_LINEAR_MIPMAP_NEAREST ||
minFilter == GL_NEAREST_MIPMAP_LINEAR ||
minFilter == GL_NEAREST_MIPMAP_NEAREST)
//4.纹理生成所有的Mip层
//参数：GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D
glGenerateMipmap(GL_TEXTURE_2D);

return true;