OpenGL ES之基本简介和渲染流程

简介

  • OpenGL ES (OpenGL for Embedded Systems) 是以⼿持和嵌入式为目标的高级3D图形应用程序编程接口(API)。
  • OpenGL ES是目前智能手机中占据统治地位的图形API.支持的平台: iOS, Andriod , BlackBerry ,bada ,Linux ,Windows.
  • OpenGL ES 开放式图形库(OpenGL的)用于可视化的二维和三维数据。它是一个多功能开放标准图形库,⽀持2D和3D数字内容创建,机械和建筑设计,虚拟原型设计,飞⾏模拟,视频游戏等应用程序。您可以使⽤OpenGL配置3D图形管道并向其提交数据。顶点被变换和点亮,组合成图元,并光栅化以创建2D图像。 OpenGL旨在将函数调用转换为可以发送到底层图形硬件的图形命令。由于此底层硬件专用于处理图形命令,因此OpenGL绘图通常⾮常快。
  • OpenGL for Embedded Systems(OpenGL ES)是OpenGL的简化版本,它消除了冗余功能,提供了⼀个既易于学习⼜更易于在移动图形硬件中实现的库。
  • 苹果官方文档
    OpenGL ES API
    OpenGL ES Programming Guide

渲染流程

OpenGL ES允许应⽤程序利用底层图形处理器的强⼤功能。iOS设备上的GPU可以执⾏复杂的2D和3D绘图,以及最终图像中每个像素的复杂着⾊计算。

一、渲染流程示意图

来自苹果官方文档:OpenGL ES as a Graphics Pipeline

  • OpenGL ES client-server architecture(客户机-服务器架构)
    Your app communicates state changes, texture and vertex data, and rendering commands to the OpenGL ES client. The client translates this data into a format that the graphics hardware understands, and forwards them to the GPU. These processes add overhead to your app’s graphics performance.
    大致意思:APP会向OpenGL ES客户端传递状态变化、纹理和顶点数据以及渲染命令,客户端将这些数据转换为图形硬件能够理解的格式,然后将它们转发给GPU。

在这里插入图片描述

  • OpenGL ES graphics pipeline(图形管道)
    Your app configures the graphics pipeline, and then executes drawing commands to send vertex data down the pipeline. Successive stages of the pipeline run a vertex shader to process the vertex data, assemble vertices into primitives, rasterize primitives into fragments, run a fragment shader to compute color and depth values for each fragment, and blend fragments into a framebuffer for display.
    大致意思:APP配置图形管道,然后执行绘图命令将顶点数据发送到管道中,管道的后续阶段运行顶点着色器来处理顶点数据,将顶点组装为顶点数组,将图元光栅化为片段,运行片段着色器来计算每个片段的颜色和深度值,并将片段混合到一个framebuffer中进行显示。

在这里插入图片描述

  • 原理图:

在这里插入图片描述

二、顶点着色器

① 顶点着色器的输入
  • 着⾊器程序——描述顶点上执行操作的顶点着⾊器程序源代码/可执⾏⽂件
  • 顶点着⾊器输⼊(属性attribute)——用顶点数组提供每个顶点的数据
  • 统⼀变量(uniform)——顶点/⽚元着⾊器使⽤的不变数据
  • 采样器——代表顶点着⾊器使用纹理的特殊统⼀变量类型,一般是ID类型,GLSL会根据ID标签查找到纹理。
② 顶点着色器的输出
  • gl_Position,是GLSL 的内建变量,是将处理后的最终顶点数据赋值给它;
  • gl_PointSize,是指点的尺寸,即可以在顶点着色器中修改每个点的大小,使用率较低。
③ 顶点着色器处理的业务
  • 矩阵变换位置
  • 计算光照公式生成逐顶点颜色
  • 生成/变换纹理坐标
// 属性 顶点坐标 四维向量
attribute vec4 position;
// 属性 纹理坐标 二维向量
attribute vec2 textCoordinate; 
// uniform 旋转矩阵
uniform mat4 rotateMatrix; 
// 通道 可利用该值传递值到片元着色器
varying lowp vec2 varyTextCoord; 
void main() {
    varyTextCoord = textCoordinate; 
    vec4 vPos = position;
    vPos = vPos * rotateMatrix; 
    // 输出
    gl_Position = vPos;
}

三、 图元装配和光栅化

① 图元装配
  • 将顶点数据计算成一个个图元,在这个阶段会执行裁剪、透视分割和Viewport变换操作,即确定顶点形成的图形,点、线或三角形等。
  • 对于每个图元,必须确定图元是否位于视锥体(屏幕上可见的3D空间区域)内:图元没有完全在视锥体内,可能需要进行裁剪;图元完全处于该区域之外,它就会被抛弃。
② 光栅化
  • 绘制对应的图片(点、线、三角形),将图元转化成一组二维片段的过程,就是将顶点数据计算成的图片转化成片元,然后这些片元由片元着色器处理。

四、片元着色器

① 片元着色器的输入
  • 着色器程序 — 描述片段上执行操作的片元着色器程序源代码/可执行文件。
  • 输入变量 — 光栅化单元用插值为每个片段生成的顶点着色器输出
  • 统一变量(uniform) — 顶点或片元着色器使用的不变数据
  • 采样器 — 代表片元着色器使用纹理的特殊统一变量
② 片元着色器业务

它可以⽤于图⽚/视频/图形中每个像素的颜色填充(比如给视频添加滤镜,实际上就是将视频中每个图片的像素点颜色填充进行修改)

  • 计算颜色
  • 获取纹理值
  • 往像素点中填充颜色值(纹理值/颜色值)
// 纹理坐标 从顶点着色器传递过来 命名、类型要一致
varying lowp vec2 varyTextCoord; 
// 纹理采样器 
uniform sampler2D colorMap; 
void main() {
    // 输出值 gl_FragColor
    // texture2D(纹理采样器, 纹理坐标) 获取纹理像素
    gl_FragColor = texture2D(colorMap, varyTextCoord); 
}

五、逐片段操作

  • 像素归属测试: 确定帧缓存区中位置(Xw,Yw)的像素目前是不是归属于OpenGL ES所有。例如,如果⼀个显示OpenGL ES帧缓存区View被另外⼀个View所遮蔽.则窗口系统可以确定被遮蔽的像素不属于OpenGL ES上下⽂,从而不全显示这些像素。而像素归属测试是OpenGL ES的一部分,它不由开发者开人为控制,而是由OpenGL ES内部进行。
  • 裁剪测试: 裁剪测试确定(Xw,Yw)是否位于作为OpenGL ES状态的一部分裁剪矩形范围 内。如果该⽚段位于裁剪区域之外,则被抛弃。
  • 深度测试: 输⼊片段的深度值进步比较,确定片段是否拒绝测试。
  • 混合: 混合将新生成的⽚段颜色与保存在帧缓存的位置的颜色值组合起来。
  • 抖动: 抖动可用于最小化因为使用有限精度在帧缓存区中保存颜色值⽽产生的伪像。

OpenGL ES的应用

一、OpenGL ES 显示器执⾏动画的应用程序流程

在这里插入图片描述

  • 当应用程序启动时,它首先就是初始化在应用程序生命周期中不打算更改的资源(一般情况下,应用程序将这些资源封装到OpenGL ES对象中)。
  • 我们的目标是创建任何可以在应用运行时(甚至是应用生命周期的一部分,比如游戏中的关卡)中保持不变的对象,以增加的初始化时间换取更好的渲染性能。复杂的命令或状态的改变应该被OpenGL ES对象取代,这些对象可以用一个函数调用来使用。例如,配置固定函数管道可能需要进行几十次函数调用。相反,在初始化时编译一个图形着色器,并在运行时通过一个函数调用切换到它。
  • 创建或修改代价昂贵的OpenGL ES对象几乎总是应该创建为静态对象。循环处理想要呈现给OpenGL ES上下文的所有项,然后将结果显示出来。在动画场景中,每一帧都会更新一些数据。
  • 应用程序在更新渲染资源(在过程中创建或修改OpenGL ES对象)和提交使用这些资源的绘图命令之间交替,这个内部循环的目标是平衡工作负载,使CPU和GPU并行工作,防止应用程序和OpenGL ES同时访问相同的资源。
  • 在iOS上,如果修改不在一帧的开始或结束时执行,那么修改一个OpenGL ES对象的代价会很大。这个内部循环的一个重要目标是避免将数据从OpenGL ES复制回应用程序,将结果从GPU复制到CPU会非常慢。如果复制的数据稍后也被用作呈现当前帧的过程的一部分,如中间呈现循环所示,应用程序将阻塞,直到之前提交的所有绘图命令都完成。
  • 当app在框架中提交所有需要的绘制命令后,它会将结果显示在屏幕上。非交互式的应用程序将最终的图像复制到应用程序内存中进行进一步处理。最后,当应用程序准备退出时,或者当它完成一个主要任务时,它释放OpenGL ES对象,以便为自己或其他应用程序提供额外的可用资源。
二、EGL (Embedded Graphics Library )
  • OpenGL ES命令需要渲染上下文和绘制表面才能完成图形图像的绘制;
  • 渲染上下文: 存储相关OpenGL ES状态;
  • 绘制表面: 是用于绘制图元的表面,它指定渲染所需要的缓存区类型,例如颜色缓冲区,深度缓冲区和模板缓冲区;
  • OpenGL ES API并没有提供如何创建渲染上下⽂或者上下⽂如何连接到原生窗口系统。 EGL是Khronos渲染API(如OpenGL ES)和原⽣窗口系统之间的接口。唯一⽀持OpenGL ES却不⽀持EGL的平台是iOS。
  • Apple提供⾃己的EGL API的iOS实现,称为EAGL,因为每个窗口系统都有不同的定义,所以EGL提供基本的不透明类型EGLDisplay,这个类型封装了所有系统相关性,用于和原生窗口系统接口。

猜你喜欢

转载自blog.csdn.net/Forever_wj/article/details/107576192