原博主博客地址:http://blog.csdn.net/qq21497936
本文章博客地址:http://blog.csdn.net/qq21497936/article/details/79196615
《OpenGL学习笔记》系列博客目录地址:http://blog.csdn.net/qq21497936/article/category/7315532
OpenGL学习笔记(十三):将纹理贴图应用到四边形上,对VAO/VBO/EBO/纹理/着色器的使用方式进行总结
前话
上一章节,我们使用了纹理进行贴图,但是是三角形了,如何把四边形的贴上去,就是本章节的要点,通过本章节,您可能对使用EBO有更深刻的认识,同时在最后,读者对VAO、VBO和EBO的使用方法进行再一次的梳理和总结,加强学习效果。
《OpenGL学习笔记》系列博客目录地址:http://blog.csdn.net/qq21497936/article/category/7315532
基础程序
本章节基础程序使用《OpenGL学习笔记(十二):纹理的使用》完成的demo。(CSDN目前无法设置免积分下载):
文章地址:http://blog.csdn.net/qq21497936/article/details/79184344
demo下载:http://download.csdn.net/download/qq21497936/10227600
本章完成的Demo
下载地址:http://download.csdn.net/download/qq21497936/10229560
额外修改了修改了片段着色器:
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 texCoord;
uniform sampler2D ourTexture;
void main()
{
// FragColor = texture(ourTexture, texCoord);
FragColor = texture(ourTexture, texCoord) * vec4(ourColor, 1.0);
}
纹理贴到四边形上
之前的Demo中,我们将窗户纸贴到了三角形上,之所以把四边形(举一反三:多边形)单独一章节,是因为四边形与大家潜意识里面的四边形贴图不一样,下面是上章节使用的图片
我们上章节(笔记十二)解析纹理如下:
下面笔者猜想大家在读到之前章节的笔记上,应该是认为可以直接画一个正方向,毕竟之前的代码是直接画线和三角形,那么应该像程序一样有可以直接画四边形,并对四边形贴图。所以大家所认为的四边形的顶点数据应该这样如下:
但是实际对绘制只能是三角形,纹理对于绘制,所以实际情况是下图:
(注意:随边画哪个三角形,只要能覆盖全部即可),笔者选择的是上图的2个。
原来的顶点数据是:
float vertices[] = {
// 三角形坐标 颜色 纹理坐标
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,0.0f,
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,0.0f,
0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.5f,1.0f
};
修改为:
// 四边形,共四个点,因为只能画三角形,所以要6个点(可使用EBO来实现,即可只要四个点)
float vertices[] = {
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,0.0f, // 左下角 *
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,0.0f, // 右下角 **
0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,1.0f, // 右上角 ***
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,0.0f, // 左下角 ***
0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,1.0f, // 右下角 **
-0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,1.0f // 左上角 *
};
之前的demo画了一个三角形:
glDrawArrays(GL_TRIANGLES, 0, 3);修改为:
glDrawArrays(GL_TRIANGLES, 0, 6);
画2个三角形,共6个点(注意:要是用画2个点则不会画,或4个点则只画一个,具体opengl是否绘制多余的点,笔者未研究,理论上认为画2个点纹理是1D的,肯能是画了表现不出来,可能是没画,以后有机会再研究)。
效果截图如下:
上图的效果修改了着色器的:
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 texCoord;
uniform sampler2D ourTexture;
void main()
{
// FragColor = vec4(ourColor, 1.0f);
FragColor = texture(ourTexture, texCoord) * vec4(ourColor, 1.0);
}
使用EBO
不使用EBO时,使用的顶点数据如下:
// 四边形,共四个点,因为只能画三角形,所以要6个点(可使用EBO来实现,即可只要四个点)
float vertices[] = {
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,0.0f, // 左下角 *
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,0.0f, // 右下角 **
0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,1.0f, // 右上角 ***
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,0.0f, // 左下角 ***
0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,1.0f, // 右下角 **
-0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,1.0f // 左上角 *
};
发现其实总共就四个顶点,但是每次重复时候,都要写出来,不但增加工作量还容易导致不好计算,不符合人类的认知(我们认为四边形就四个顶点),此时,我们可以使用EBO,EBO是使用索引数,我们定义如下:
// 使用EBO
float vertices[] = {
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,0.0f, // 左下角
0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f,0.0f, // 右下角
0.5f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f,1.0f, // 右上角
-0.5f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f,1.0f // 左上角
};
// 索引
unsigned int indices[] = {
0,1,2, // 第一个三角形
0,2,3 // 第二个三角形
};
使用EBO步骤:
- 创建(标识ID)。
- 绑定(顶点数据绑定缓存)。
- 解绑。
- 绘制(再次绑定使用的EBO,并使用Elements绘制)。
- 删除(末尾删除)。
…
unsigned int VBO, VAO, EBO;
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
// 第一步:获取EBO唯一标识
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
// 第二步:绑定EBO缓存
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(0 * sizeof(float)));
glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
// 添加进缓存,启用纹理
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
while (!glfwWindowShouldClose(window))
{
processInput(window);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
shader.use();
glBindVertexArray(VAO);
// 第三步:使用索引,绘制三角形,6个顶点
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
// 使用点
// glDrawArrays(GL_TRIANGLES, 0, 6);
glfwSwapBuffers(window);
glfwPollEvents();
}
glDeleteVertexArrays(1, &VAO);
glDeleteBuffers(1, &VBO);
// 第四步:删除EBO
glDeleteBuffers(1, &EBO);
glfwTerminate();
…
可以从以上代码中返现,EBO与VBO其实使用步骤是一样的。
效果如图:
总结VAO、VBO、EBO、纹理
现阶段总结使用过程大致如下(如有错误请留言批评指正,谢谢各位大神):
方式 |
VAO |
VBO |
EBO |
纹理 |
获取 |
getGenVertexArrays |
getGenBuffers |
getGenBuffers |
glGenTextures |
绑定 |
glBindBuffer |
glBindBuffer |
glBindBuffer |
glBindTexture |
属性定义 |
glVertexAttribPointer |
glVertexAttribPointer |
不需要 |
glTexImage2D glGenerateMipmap |
解绑 |
glBindVertexArray |
glBindBuffer |
glBindBuffer |
不解绑 |
使用 |
glBindVertexArray glDrawArrays |
默认作用于绑定时的顶点 |
glBindBuffer glDrawElements |
默认使用 |
删除 |
glDeleteVertexArrays |
glDeleteBuffers |
glDeleteBuffers |
|
总结Shader着色器使用
顶点着色器:创建(标识),绑定(代码),编译(着色器),获取编译结果
片段着色器:创建(标识),绑定(代码),编译(着色器),获取编译结果
着色器程序:创建(表示) ,绑定(各着色器id),连接(全局连接到着色器程序标识上),删除(释放使用的着色器内存)
着色器使用:使用该着色器id
具体细节查看《OpenGL学习笔记(十一):封装自己的着色器类》
文章地址:http://blog.csdn.net/qq21497936/article/details/79181818
原博主博客地址:http://blog.csdn.net/qq21497936
本文章博客地址:http://blog.csdn.net/qq21497936/article/details/79196615