原博主博客地址: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 coreout 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 coreout 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是使用索引数,我们定义如下:
// 使用EBOfloat 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);// 第四步:删除EBOglDeleteBuffers(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