OpenGL 加载流程 vs OpenGL ES 加载流程

一、OpenGL 加载流程

OpenGL的加载过程涉及多个步骤,主要包括初始化OpenGL环境、创建窗口、设置着色器和渲染循环。以下是一般情况下OpenGL加载的基本步骤:

  1. 初始化库和上下文: 在开始使用OpenGL之前,首先要初始化 OpenGL 库和创建 OpenGL 上下文。这可以通过调用特定的库函数(如GLFW、SDL等)来实现。这些库负责创建窗口、管理输入和OpenGL上下文等。

    //初始化GLFW和配置
    glfwInit();					
    //使用glfwWindowHint函数来配置GLFW
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//将主版本号(Major)设为3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//次版本号(Minor)设为3
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//我们同样明确告诉GLFW我们使用的是核心模式(Core-profile)。明确告诉GLFW我们需要使用核心模式意味着我们只能使用OpenGL功能的一个子集
    
  2. 创建窗口和上下文: 使用选定的库,你可以创建一个窗口,将OpenGL上下文绑定到该窗口中。上下文是OpenGL用来管理和执行图形渲染的关键环境。

    //创建一个窗口对象,这个窗口对象存放了所有和窗口相关的数据,而且会被GLFW的其他函数频繁地用到
    GLFWwindow* window = glfwCreateWindow(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", NULL, NULL);
    
    //将我们窗口的上下文设置为当前线程的主上下文
    glfwMakeContextCurrent(window);
    
  3. 加载和编译着色器: 创建和编译顶点着色器和片段着色器,这些着色器将定义你的渲染效果。通常,你需要使用GLSL(OpenGL Shading Language)编写着色器代码,然后将其加载到OpenGL中。

    传入着色器的源文件,读取文件的缓冲内容到数据流中,编译着色器

    // 2. 编译着色器
    unsigned int vertex, fragment;
    
    // 顶点着色器
    vertex = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex, 1, &vShaderCode, NULL);
    glCompileShader(vertex);
    checkCompileErrors(vertex, "VERTEX");
    
    // 片段着色器
    fragment = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment, 1, &fShaderCode, NULL);
    glCompileShader(fragment);
    checkCompileErrors(fragment, "FRAGMENT");
    
  4. 创建着色器程序: 使用已编译的顶点和片段着色器,创建一个着色器程序对象。这个程序对象将管理着色器的链接和使用。

    // 着色器程序
    ID = glCreateProgram();
    glAttachShader(ID, vertex);
    glAttachShader(ID, fragment);
    if (geometryPath != nullptr)
    {
            glAttachShader(ID, geometry);
    }
    glLinkProgram(ID);
    
  5. 设置顶点数据和缓冲区: 为你的渲染创建顶点数据,例如顶点坐标、法线、纹理坐标等。将这些数据存储在缓冲区对象中,这些缓冲区可以是顶点缓冲区、索引缓冲区等。

  6. 设置顶点属性指针: 将顶点数据与着色器的输入变量(如顶点坐标、法线等)关联起来。通过使用glVertexAttribPointer函数,将顶点数据绑定到顶点着色器的属性变量。

    //初始化缓冲,最终使用Draw函数绘制网格
    glGenVertexArrays(1, &VAO);//任何随后的顶点属性调用都会储存在这个VAO中
    glGenBuffers(1, &VBO);//针对缓冲ID:VBO生成一个VBO对象
    glGenBuffers(1, &EBO);
    
    glBindVertexArray(VAO);//要想使用VAO,要做的只是使用glBindVertexArray绑定VAO
    glBindBuffer(GL_ARRAY_BUFFER, VBO);//把创建的VBO缓冲对象绑定到GL_ARRAY_BUFFER目标上
    //我们使用的任何(GL_ARRAY_BUFFER目标上的)缓冲调用都会用来配置当前绑定的缓冲(VBO)
    //glBufferData参数:(1)目标缓冲的类型(2)传输数据的大小(3)我们希望发送的实际数据(4)希望显卡如何管理给定的数据(* GL_STATIC_DRAW :数据不会或几乎不会改变。* GL_DYNAMIC_DRAW:数据会被改变很多。* GL_STREAM_DRAW :数据每次绘制时都会改变)
    glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(Vertex), &vertices[0], GL_STATIC_DRAW);//把之前定义的顶点数据复制到缓冲的内存中
    
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.size() * sizeof(unsigned short), &indices[0], GL_STATIC_DRAW);
    
    // 顶点位置
    glEnableVertexAttribArray(0);
    //glVertexAttribPointer参数:(1)指定我们要配置的顶点属性,具体依据着色器中的定义layout(location = 0)我们希望把数据传递到这一个顶点属性中
    //(2)顶点属性的大小VEC3,大小就是3.(3)数据的类型(4)是否希望数据被标准化(Normalize),是的话就会映射到0-1之间
    //(5)Stride步长,顶点属性组之间的间隔(6)它表示位置数据在缓冲中起始位置的偏移量
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)0);
    // 顶点法线
    glEnableVertexAttribArray(1);
    glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Normal));//Normal在Vertex结构体中的偏移量
    // 顶点纹理坐标
    glEnableVertexAttribArray(2);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, TexCoords));
    // vertex tangent
    glEnableVertexAttribArray(3);
    glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Tangent));
    // vertex bitangent
    glEnableVertexAttribArray(4);
    glVertexAttribPointer(4, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*)offsetof(Vertex, Bitangent));
    
    glBindVertexArray(0);
    
  7. 启用着色器和缓冲区: 启用着色器程序,让OpenGL知道你要使用哪些着色器进行渲染。还要绑定相应的缓冲区对象,以供渲染使用。

    // 程序ID
    unsigned int ID;
    glUseProgram(ID);
    
  8. 设置绘制参数: 设置绘制参数,如清除颜色、深度缓冲区,设置视口、投影矩阵等。

  9. 渲染循环: 进入渲染循环,即不断地绘制场景并处理输入。在每一帧中,你需要设置相应的状态、更新数据,然后调用绘制函数来执行渲染操作。

    while (!glfwWindowShouldClose(window))
    {
    ...
    }
    
  10. 交换缓冲区: 在渲染完成后,使用交换缓冲区操作,将渲染结果显示在屏幕上。

```
glfwSwapBuffers(window);//交换颜色缓冲(它是一个储存着GLFW窗口每一个像素颜色值的大缓冲),它在这一迭代中被用来绘制,并且将会作为输出显示在屏幕上。
```

二、OpenGL ES 加载流程

OpenGL ES(OpenGL for Embedded Systems)是用于嵌入式系统的一种轻量级的OpenGL API。它在很大程度上与标准的OpenGL相似,但考虑了资源受限的嵌入式环境。OpenGL ES的加载过程与标准的OpenGL加载过程类似,但有一些特定的步骤和差异。以下是OpenGL ES加载过程的基本步骤:

  1. 初始化库和上下文: 与标准OpenGL一样,你需要使用特定的库函数(如EGL、GLFW、SDL等)来初始化OpenGL ES库和创建OpenGL ES上下文。这些库负责创建窗口、管理输入和OpenGL ES上下文等。

  2. 创建窗口和上下文: 使用选定的库,创建一个窗口,并将OpenGL ES上下文绑定到该窗口中。上下文是OpenGL ES用来管理和执行图形渲染的关键环境。

  3. 加载和编译着色器: 创建和编译顶点着色器和片段着色器,同样使用GLSL编写着色器代码,然后将其加载到OpenGL ES中。OpenGL ES 2.0和3.0支持GLSL ES(OpenGL ES Shading Language)。

  4. 创建着色器程序: 使用已编译的顶点和片段着色器,创建一个着色器程序对象。这个程序对象将管理着色器的链接和使用,与标准OpenGL类似。

  5. 设置顶点数据和缓冲区: 为你的渲染创建顶点数据,将这些数据存储在缓冲区对象中。OpenGL ES支持顶点缓冲区、索引缓冲区等。

  6. 设置顶点属性指针: 将顶点数据与着色器的输入变量关联起来,通过使用glVertexAttribPointer函数。同样,将顶点数据绑定到顶点着色器的属性变量。

  7. 启用着色器和缓冲区: 启用着色器程序,绑定相应的缓冲区对象,使OpenGL ES知道你要使用哪些着色器进行渲染。

  8. 设置绘制参数: 设置绘制参数,如清除颜色、深度缓冲区,设置视口、投影矩阵等,与标准OpenGL类似。

  9. 渲染循环: 进入渲染循环,即不断地绘制场景并处理输入。在每一帧中,设置状态、更新数据,然后调用绘制函数进行渲染。

  10. 交换缓冲区: 在渲染完成后,使用交换缓冲区操作,将渲染结果显示在屏幕上。

全部评论

相关推荐

11-18 15:57
门头沟学院 Java
最终归宿是测开:这个重邮的大佬在重邮很有名的,他就喜欢打92的脸,越有人质疑他,他越觉得爽😂
点赞 评论 收藏
分享
沉淀一会:1.同学你面试评价不错,概率很大,请耐心等待; 2.你的排名比较靠前,不要担心,耐心等待; 3.问题不大,正在审批,不要着急签其他公司,等等我们! 4.预计9月中下旬,安心过节; 5.下周会有结果,请耐心等待下; 6.可能国庆节前后,一有结果我马上通知你; 7.预计10月中旬,再坚持一下; 8.正在走流程,就这两天了; 9.同学,结果我也不知道,你如果查到了也告诉我一声; 10.同学你出线不明朗,建议签其他公司保底! 11.同学你找了哪些公司,我也在找工作。
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务