OpenGL学习笔记(十三):将纹理贴图应用到四边形上,对VAO/VBO/EBO/纹理/着色器的使用方式进行总结

原博主博客地址: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步骤:

  1. 创建(标识ID)。
  2. 绑定(顶点数据绑定缓存)。
  3. 解绑。
  4. 绘制(再次绑定使用的EBO,并使用Elements绘制)。
  5. 删除(末尾删除)。

    …
    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

展开阅读全文

没有更多推荐了,返回首页