OpenGL环境配置及着色器工作流

OpenGL相关笔记

最近在看图像后处理相关代码,学了一段时间的opengl,下面是从思维导图笔记转化过来的文档
学习的相关知识来源于 [https://learnopengl-cn.github.io/intro/]

一、环境配置和相关概念

1.1 环境配置

vs2019+nuget

nuget 安装 glfw glew-c++

可能遇到的问题:__imp__glClear@4,该符号在函数 _main 中被引用

原因:未引入依赖项opengl32.lib

解决方法:版本、平台、附加依赖项opengl32.lib

1.2 包相关知识

OpenGL utility library 标准GLU 头文件 gl.h glu.h
OpenGL utility toolkit 工具箱GLUT 头文件 glut.h

区别:
glew(The OpenGL Extension Wrangler Library)是对底层OpenGL接口的封装,可以让你的代码跨平台。

GLEW是用来管理OpenGL的函数指针的

glad与glew作用相同,可以看作它的升级版。

glew.h

不同的显卡公司,也会发布一些只有自家显卡才支 持的扩展函数,你要想用这数涵数,不得不去寻找最新的glext.h,有了GLEW扩展库,你就再也不用为找不到函数的接口而烦恼,因为GLEW能自动识别你的平台所支持的全部OpenGL高级扩展函数。也就是说,只要包含一个glew.h头文件,你就能使用gl,glu,glext,wgl,glx的全部函数。

glfw.h

一个轻量级的,开源的,跨平台的library。支持OpenGL及OpenGL ES,用来管理窗口,读取输入,处理事件等。因为OpenGL没有窗口管理的功能,所以很多热心的人写了工具来支持这些功能,比如早期的glut,现在的freeglut等。那么GLFW有何优势呢?glut太老了,最后一个版本还是90年代的。freeglut完全兼容glut,算是glut的代替品,功能齐全,但是bug太多。稳定性也不好(不是我说的啊),GLFW应运而生。

1.3 基础概念

1.3.1 着色

  • 名词

    • 管线:将3D坐标转换为2D坐标,然后将2D坐标转换Wie2D像素输出

    • 顶点数组对象:Vertex Array Object,VAO

      • 在VAO后创建的VBO都属于该VAO。关联VBO数据用取得当前激活的缓存区对象偏移来指定。
      • VAO是一个保存了所有顶点数据属性的状态结合,它存储了顶点数据的格式以及顶点数据所需的VBO对象的引用
    • 顶点缓冲对象:Vertex Buffer Object,VBO

      • 优点:采用VBO、VAO节省了绘制多个物体时 CPU 与 GPU 之间的通讯时间,提高了渲染性能。
      • VBO是内存缓冲区,用来保存顶点信息,颜色信息,法线信息,纹理坐标信息和索引信息等等
    • Uniform

      • 从CPU中的应用向GPU中的着色器发送数据的方式
      • 全局变量,以被着色器程序的任意着色器在任意阶段访问
  • 着色器运行在GPU上,存在每个渲染管线阶段

  • OpenGL 着色器是用 OpenGL 着色器语言 (OpenGL Shading Language 即 GLSL)

  • GLSL中的向量是一个可以包含有1、2、3或者4个分量的容器,分量的类型可以是前面默认基础类型的任意一个

cnblog参考

1.3.2 着色器代码特点

  • 着色器的开头总是要声明版本,接着是输入和输出变量、uniform(以后会解释)和main函数

1.3.3 layout

  • 顶点在内存的布局
  • layout(location=0) 代表元素排列在顶点数据内存为0位置

二、顶点数据(缓冲)的创建及属性配置

2.1 VBO

  • VBO创建

    • 生成缓冲区对象

      • glGenBuffers(1, &VBO)
      1. 绑定顶点信息
      • glBindBuffer(GL_ARRAY_BUFFER, VBO);
      1. 数据传输
      • glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
  • 删除

    • glDeleteBuffers(1, &VBO);
  • 解除绑定

    • glBindBuffer(GL_ARRAY_BUFFER, 0)

2.2 VAO

  • VAO创建

      1. 生成VAO对象
      • glGenVertexArrays(1, &VAO);
      1. 绑定VAO
      • glBindVertexArray(VAO);
      • 执行VAO绑定之后其后的所有VBO配置都是这个VAO对象的一部分,可以说VBO是对顶点属性信息的绑定,VAO是对很多个VBO的绑定。
  • 删除

    • glDeleteVertexArrays(1, &VAO);
  • 解除绑定

    • glBindVertexArray(0)

配置VAO和VBO

    1. 解释顶点数据,设置顶点属性指针
    • glVertexAttribPointer
    1. 启用顶点数据
    • glEnableVertexAttribArray

2.3 EBO

  • VBO创建

    • 生成缓冲区对象

      • glGenBuffers(1, &EBO);
      1. 绑定顶点信息
      • glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
      1. 数据传输
      • glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
  • 删除

    • glDeleteBuffers(1, &VBO);
  • 解除绑定

    • glBindBuffer(GL_ARRAY_BUFFER, 0)

注意点

​ 当目标是GL_ELEMENT_ARRAY_BUFFER的时候,VAO会储存glBindBuffer的函数调用。这也意味着它也会储存解绑调用,所以确保你没有在解绑VAO之前解绑索引数组缓冲,否则它就没有这个EBO配置了

三、着色器工作流

3.1 着色器对象创建及编译

  • 顶点着色器

    • glCreateShader ( GL_VERTEX_SHADER )
    • glShaderSource
    • glCompileShader ( vertexShader );
    • glGetShaderiv ( vertexShader, GL_COMPILE_STATUS, &success );
  • 片段着色器

  • 顶点着色器

    • 创建着色器

      • glCreateShader ( GL_VERTEX_SHADER )
    • glShaderSource

    • glCompileShader ( vertexShader );

    • glGetShaderiv ( vertexShader, GL_COMPILE_STATUS, &success );

3.2 链接着色器对象到用来渲染的着色器程序中

  • glLinkProgram(shaderProgram);

3.3 程序调用

  • glUseProgram(shaderProgram);

四、绘制工作流

4.1 使用当前的激活的着色器

  • glUseProgram(shaderProgram);

4.2 绑定相应的VAO

  • glBindVertexArray(VAO);

4.3 绘制物体

  • glDrawArrays(GL_TRIANGLES, 0, 3);

4.4 解绑VAO

思路:它使用当前激活的着色器,之前定义的顶点属性配置,和VBO的顶点数据(通过VAO间接绑定)来绘制图元。

五、纹理工作流(未完成)

glTexParameteri

  • 作用:确定如何把纹理象素映射成像素,因为图象从纹理图象空间映射到帧缓冲图象空间(映射需要重新构造纹理图像,这样就会造成应用到多边形上的图像失真)

  • glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);

  • glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

  • 参数:1.指定纹理目标类型 2.指定设置的选项与应用的纹理轴 3.递一个环绕方式(Wrapping)

    • 纹理类型

      • GL_TEXTURE_2D
      • GL_TEXTURE_3D
    • 设置选项

      • STR方向上的贴图模式

        • 应用的纹理轴S、T、R:类似x、y、z

        • GL_TEXTURE_WRAP_S: S方向上的贴图模式

        • 环绕Wrapping

          • GL_REPEAT :对纹理的默认行为。重复纹理图像。
          • GL_MIRRORED_REPEAT :和GL_REPEAT一样,但每次重复图片是镜像放置的。
          • GL_CLAMP_TO_EDGE :纹理坐标会被约束在0到1之间,超出的部分会重复纹理坐标的边缘,产生一种边缘被拉伸的效果。
          • GL_CLAMP_TO_BORDER:超出的坐标为用户指定的边缘颜色。
      • 纹理过滤

        • GL_TEXTURE_MAG_FILTER: 放大过滤

        • GL_TEXTURE_MIN_FILTER: 缩小过滤

        • 过滤方式

          • GL_LINEAR: 线性过滤
          • GL_LINEAR_MIPMAP_NEAREST: 邻近过滤
    • 多级过滤

glBindTexture

  • 绑定纹理
  • glBindTexture(GL_TEXTURE_3D, pTexture->GetTextureName());

glGenerateMipmap

glTexImage2D

glGenTextures

  • 生成纹理
  • glGenTextures(1, &texture);

glActiveTexture

纹理坐标

  • 纹理坐标是你给模型顶点设置的那个数组,OpenGL以这个顶点的纹理坐标数据去查找纹理图像上的像素,然后进行采样提取纹理像素的颜色。
  • 纹理坐标范围为0到1之间,纹理坐标起始于(0, 0),也就是纹理图片的左下角,终始于(1, 1),即纹理图片的右上角
  • 每个顶点就会关联着一个纹理坐标,用来标明该从纹理图像的哪个部分采样

六、附录-常用函数

顶点数据

  • glBufferData

    • 调用glBufferData函数,把之前定义的顶点数据复制到显存缓冲区中
    • glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
  • glBindBuffer

    • 把新创建的缓冲绑定到指定类型上,参数:缓冲类型、缓冲ID

    • 目标缓存类型

      • GL_ARRAY_BUFFER
      • GL_ELEMENT_ARRAY_BUFFER
  • glEnableVertexAttribArray

    • 允许顶点着色器读取GPU(服务器端)数据:数据在GPU端是否可见,即,着色器能否读取到数据,由是否启用了对应的属性决定
    • 与其他区别。glVertexAttribPointer或VBO只是建立CPU和GPU之间的逻辑连接,从而实现了CPU数据上传至GPU
  • glVertexAttribPointer

    • 参数:1.位置 2.大小 3.数据类型 4.标准化 5.步长 6.偏移量

      计算步长值。为获得数据队列中下一个属性值:3个是位置值,另外3个是颜色值。这使我们的步长值为6乘以float的字节数

      计算偏移量:如颜色值3个float

    • 指定了渲染时索引值为 index 的顶点属性数组的数据格式和位置。它们之间也是通过上下文,只有唯一的激活VAO,在VAO后创建的VBO都属于该VAO。关联VBO数据用取得当前激活的缓存区对象偏移来指定。

  • glBufferData

    • 作用:用来把用户定义的数据复制到当前绑定缓冲的函数

    • 参数:1是目标缓冲的类型 2.指定传输数据的大小 3.发送的实际数据 4.显卡如何管理给定数据

    • 目标缓存类型

      • GL_ARRAY_BUFFER
      • GL_ELEMENT_ARRAY_BUFFER
    • 显卡如何管理给定的数据

      • GL_STATIC_DRAW :数据不会或几乎不会改变。
      • GL_DYNAMIC_DRAW:数据会被改变很多。
      • GL_STREAM_DRAW :数据每次绘制时都会改变。
  • glGenBuffers

    • void glGenBuffers(GLsizei n,GLuint * buffers);
    • 第一个参数是要生成的缓冲对象的数量,第二个是要输入用来存储缓冲对象名称的数组
      该函数会在buffers里返回n个缓冲对象的名称。
  • glBindVertexArray

glUniform4f

  • 设置uniform值:无返回
  • glUniform4f(vertexColorLocation, 0.0f, greenValue, 0.0f, 1.0f);

glUseProgram

  • 调用程序:无返回
  • glUseProgram(shaderProgram);

glGetUniformLocation

  • 查询uniform ourColor的位置值:返回位置值,-1代表未查询到
  • int vertexColorLocation = glGetUniformLocation(shaderProgram, "ourColor");

着色器对象和程序

  • glCreateShader

    • 创建一个着色器对象,并返回着色器对象ID引用

    • 类型

      • GL_VERTEX_SHADER
      • GL_FRAGMENT_SHADER
  • glCompileShader

    • 编译着色器对象
    • glCompileShader(vertexShader); 参数为着色器对象
  • glShaderSource

    • 把这个着色器源码附加到着色器对象
    • 参数:1. 待编译的着色器对象 2.指定传递的源码字符串数量 3.顶点着色器真正的源码 4.
    • glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
  • glCreateProgram

    • 创建一个程序,并返回新创建程序对象的ID引用
    • shaderProgram = glCreateProgram();
  • glAttachShader

    • 将着色器对象附加到程序
    • glAttachShader(shaderProgram, vertexShader);
  • glLinkProgram

    • glLinkProgram(shaderProgram);
    • 链接
  • glUseProgram

    • 调用程序
    • glUseProgram(shaderProgram);
    • 在glUseProgram函数调用之后,每个着色器调用和渲染调用都会使用这个程序对象(也就是之前写的着色器)了。
    • 在把着色器对象链接到程序对象以后,记得删除着色器对象

绘图

  • glDrawArrays

    • 使用当前绑定的缓冲对象引进行绘制:
    • glDrawArrays(GL_TRIANGLES, 0, 3);
    • 参数:1.图元类型 2.指定了顶点数组的起始索引 3.指定我们打算绘制多少个顶点
  • glDrawElements

    最后一个参数不是很懂

    • 使用当前绑定的索引缓冲对象中的索引进行绘制:
    • glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    • 参数:1.图元类型 2.绘制顶点格式 3.索引类型 4. 指定EBO中偏移量
  • 线框模式

    • 用线框模式绘制你的三角形
    • 设置线框模式 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)
    • 取消线框模式 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
  • 图元的类型

    • GL_TRIANGLES

GLAD

  • glGetShaderInfoLog

    • glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
  • glGetShaderiv

    • 检测在调用glCompileShader后编译是否成功
    • glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
  • glGetProgramiv

    • 检测链接着色器程序是否失败
    • glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
posted @   鸽立青  阅读(167)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示