当前位置: 欣欣网 > 码农

音视频、渲染引擎岗位面试相关, OpenGL 高频知识点

2024-04-03码农

OpenGL 共享上下文使用场景?有哪些资源可以共享?

多线程渲染或者跨窗口渲染,共享上下文可以使得多个线程、窗口之间能够共享 OpenGL 对象(如纹理、shader 等)和状态信息,避免了在多个上下文之间频繁地进行数据拷贝和同步操作,减少资源消耗,提高性能。

可以共享的资源:

  • 纹理;

  • shader;

  • program 着色器程序;

  • buffer 类对象,如 VBO、 EBO、 RBO 等 。

  • 不可以共享的资源:

  • FBO 帧缓冲区对象(不属于 buffer 类);

  • VAO 顶点数组对象(不属于 buffer 类)。

  • 这里解释下,在不可以共享的资源中,FBO 和 VAO 属于资源管理型对象,FBO 负责管理几种缓冲区,本身不占用资源,VAO 负责管理 VBO 或 EBO ,本身也不占用资源

    注意, 每个线程同时只能绑定(eglMakeCurrent)一个 Context ,但可以按顺序切换不同 Context。

    帧缓冲区对象 FBO 的作用?

    FBO 即帧缓冲区对象,实际上是一个可添加缓冲区的容器,用于管理渲染到纹理或渲染到屏幕之外的其他图像缓冲区的过程。

    帧缓冲区对象,渲染缓冲区对象和纹理

    FBO 本身不能用于渲染,只有添加了纹理或者渲染缓冲区之后才能作为渲染目标,它仅且提供了 3 种附着(Attachment),分别是 颜色附着、深度附着和模板附着

    离屏渲染和多重渲染目标都是基于帧缓冲区对象实现。

    离屏渲染: 允许将渲染结果输出到一个纹理或渲染缓冲区,而不是直接输出到屏幕上。 这对于实现一些高级渲染技术,如后期处理、阴影映射、抗锯齿等是至关重要的。

    多重渲染目标(MRT): 允许同时渲染到多个颜色附件,这对于一次性生成多个颜色通道的数据非常有用 ,例如渲染到不同的纹理或渲染缓冲区以进行后续处理。

    参考文章:

    如何传输一个超大数组到着色器?

    1. 使用将数组加载到 2D 纹理的方式,然后使用 texelFetch 取数据;

    2. 使用 uniform 缓冲区对象,即 UBO ;

    3. 使用纹理缓冲区对象,即 TBO 。

    参考我的文章:

    什么是顶点数组对象 VAO 和顶点缓冲区对象 VBO ,为什么要使用它们?

    VBO(Vertex Buffer Object)是指顶点缓冲区对象,VAO(Vertex Array Object)是指顶点数组对象。

    OpenGL ES 2.0 编程中,用于绘制的顶点数组数据首先保存在 CPU 内存,在调用 glDrawArrays 或者 glDrawElements 等进行绘制时,需要将顶点数组数据从 CPU 内存拷贝到显存。

    但是很多时候我们没必要每次绘制的时候都去进行内存拷贝,如果可以在显存中缓存这些数据,就可以在很大程度上降低内存拷贝带来的开销。

    OpenGL ES 3.0 VBO 出现就是为了解决这个问题。

    VBO 的作用是在显存中提前开辟好一块内存,用于缓存顶点数据,从而避免每次绘制时的 CPU 与 GPU 之间的内存拷贝 ,可以提升渲染性能,降低内存带宽和功耗

    VAO 的主要作用是用于管理 VBO ,减少 glBindBuffer 、glEnableVertexAttribArray、 glVertexAttribPointer 这些调用操作,高效地实现在顶点数组配置之间切换。

    详细参考文章:

    glFlush 和 glFinish 有什么区别

    一般来说,我们在使用 OpenGL 的时候,指令不是立即执行的。它们首先被送到指令缓冲区,然后才被送到硬件执行。

    glFinish 和 glFlush 都是强制将命令缓冲区的内容提交给硬件执行。

    1)glFlush:
    glFlush 清空缓冲区,将指令送往缓硬件立即执行, 但是它是将命令传送完毕之后立即返回,不会等待这些指令执行完毕 。这些指令会在有限时间内执行完毕

    2)glFinish
    glFinish 将缓冲区的指令立即送往硬件执行,但是要一直等到硬件执行完这些指令之后才返回

    如果直接绘制到前缓冲,那么在你想保存屏幕截图之前,就需要调用这个函数,确保绘制完毕。如果使用双缓冲,则这个函数不会有太大作用

    如果调用 glFinish,通常会带来性能上的损失。因为它会是的 GPU 和 CPU 之间的并行性丧失。 一般,我们提交给驱动的任务被分组,然后被送到硬件上(在缓冲区交换的时候)

    如果调用 glFinish,就强制驱动将命令送到 GPU。然后 CPU 等待直到被传送的命令全部执行完毕。

    这样在 GPU 工作的整个期间内,CPU 没有工作(至少在这个线程上)。而在 CPU 工作时(通常是在对命令分组),GPU 没有工作。因此造成性能上的下降。

    3) glFlush 和 glFinish 区别
    一般使用 glFlush 的目的是确保在调用之后,CPU 没有 OpenGL 相关的事情需要做,命令会送到硬件执行。调用 glFinish 的目的是确保当返回之后,没有相关工作留下需要继续做

    参考文章:

    顶点着色器、片段着色器的作用分别是什么?

    顶点着色器和片段着色器分别在图形渲染管线的不同阶段执行特定的任务。

    顶点着色器用于处理输入到图形渲染管线的顶点数据,对每个输入顶点进行处理和变换,例如 MVP 矩阵变换、光照计算。

    片段着色器负责确定图形中每个片段的最终颜色值,也就是用于产生颜色。

    -- END --

    进技术交流群, 扫码添加我的微信:Byte-Flow

    获取相关资料和源码

    学习音视频、OpenGL ES、Vulkan 、Metal、图像滤镜、视频特效及相关渲染技术的付费社群,面试指导,1v1 简历服务,职业规划。

    我的付费社群

    推荐: