十二、OpenGL ES GLSL语言以及常用API

2020-09-01  本文已影响0人  含笑州

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, 这 个类型封装了所有系统相关性,用于和原生窗⼝系统接⼝

主要功能

和本地窗口系统(native windowing system)通讯

查询可用的配置

创建OpenGL ES 可用的“绘图表面“(drawing surface)

同步不同类别的API之间的渲染,比如在OpenGL ES 和OpenVG之间同步,或者在OpenGL和本地窗口的绘图命令之间

管理”渲染资源“,比如纹理映射(Rendering map)

GLSL语言

xcode中不支持GLSL语言对顶点/片元着色器的编译和连接,因此需要在项目中创建两个空文件,分别命名为shader.vsh和shaderv.fsh

使用vsh、fsh后缀的原因是方便区分着色器,其本质就是一个字符串

是否可以直接使用NSString?并不建议这样做,因为代码结构不清晰,不易读

这两个文件中是否可以加中文注释?不建议加中文注释,会报奇怪的错误,由于在xcode中书写GLSL,完全是纯手写,没有任何提示,排查问题不好排查

向量数据类型

常用的是vec2、vec3、vec4,默认是浮点类型

矩阵数据类型

最常用的是mat3、mat4

类型(mat列×行)描述

mat2,mat2x2两⾏两列

mat3,mat3x3三行三列

mat4,mat4x4四行四列

mat2x3三行两列

mat2x4四行两列

mat3x2两行三列

mat3x4四行三列

mat4x2两行四列

mat4x3三行四列

变量存储限定符

常用varying、attribute、uniform

varying 修饰符:当需要将顶点着色器的数据传递到片元着色器时,两个着色器中一模一样的纹理坐标变量就需要它来修饰

attribute:数据只能从客户端中传递到顶点着色器,且只能在顶点着色器中使用

修饰的数据:顶点、纹理、颜色、法线等

API通常以glVertex...开头,例如glVertexAttribPointer

其中的纹理坐标,需要顶点着色器间接传递到片元着色器,需要在顶点与片元着色器中定义一个一模一样的纹理坐标,通过这个变量将纹理坐标数据间接传递到片元着色器,varying lowp vec2 varyTextCoord;

顶点着色器计算之后的顶点结果需要赋值给GLSL的内建变量gl_Position

attribute vec4 position;

attribute vec2 textCoordinate;

varying lowp vec2 varyTextCoord;

void main()

{

   varyTextCoord = textCoordinate;

   gl_Position = position;

}

uniform:从app代码传递到vertex、fragment中所用的变量

在vertex,fragment中一般将uniform当成常量

uniform可以传的数据:视图矩阵、投影矩阵、投影视图矩阵

API通常以glUniform...开头

片元着色器中最终颜色,即拿到纹理对应坐标下的纹素。纹素是纹理对应像素点的颜色值,需要通过内建函数texture2D(纹理,纹理坐标)计算,将最终返回的颜色值赋值给内建变量gl_FragColor

//需要定义精度,否则可能会报错

precsion highp float;

//纹理坐标 必须与顶点着色器中一模一样,通过这个参数获取传递过来的值

varying lowp vec2 varyTextCoord;

//纹理 

uniform sampler2D colorMap; 

void main(){

   //1、拿到纹理对应坐标下的纹素。纹素是纹理对应像素点的颜色值

   lowp vec4 temp = texture2D(colorMap, varyTextCoord);

   

   //2、非常重要且必须的内建变量:gl_FragColor

   gl_FragColor = temp;

}

OpenGL ES 错误处理

如果不正确使用OpenGL ES 命令,应用程序就会产生一个错误编码,且会被记录,可以用glGetError查询,一旦查询到错误代码,当前的错误代码就会复位为GL_NO_ERROR

错误代码描述

GL_NO_ERROR从上⼀次调⽤glGetError 以来没有生成任何错误

GL_INVALID_ENUMGLenum 参数超出范围,忽略生成错误命令

GL_INVALID_VALUE数值型 参数超出范围,忽略生成错误命令

GL_INVALID_OPERATION特定命令在当前OpenGL ES 状态⽆法执⾏

GL_OUT_OF_MEMORY内存不足时执⾏该命令,如果遇到这个错误,除⾮当前错误代码,否则OpenGL ES 管线的 状态被认为未定义

OpenGL ES 自定义着色器常用API

自定义着色器

自定义着色器一般有以下步骤:

创建顶点着色器/片元着色器 --glCreateShader

指定shader的source --glShaderSource

编译shader --glCompileShader

以下是创建与编译一个着色器的相关API

自定义程序

自定义程序一般有以下步骤:

创建一个程序对象 --glCreateProgram

着色器与程序连接/附着 --glAttachShader

链接程序 --glLinkProgram

使用程序 --glUseProgram

以下是创建与链接程序的相关API

上一篇下一篇

猜你喜欢

热点阅读