美文网首页
NO.14 - OpenGL ES GLSL语言以及自定义着色器

NO.14 - OpenGL ES GLSL语言以及自定义着色器

作者: z夜流星 | 来源:发表于2020-08-23 21:50 被阅读0次

    OpenGL ES GLSL语言

    EGL(Embedded Graphics Library)
    • OpenGL ES 命令需要渲染上下⽂绘制表面才能完成图形图像的绘制
    • 渲染上下⽂: 存储相关OpenGL ES状态,是一个状态机
    • 绘制表面:⽤于绘制图元的表面,需要指定渲染的缓存区,例如颜⾊缓、深度和模板
    • OpenGL ES API 并没有提供如何创建渲染上下文或者上下文如何连接到原生窗口系 统. EGLKhronos 渲染API(如OpenGL ES) 和原⽣窗⼝系统之间的接⼝. 唯⼀支持 OpenGL ES 却不支持EGL的平台是iOS. Apple 提供⾃己的EGL APIiOS实现,称为EAGL
    • 因为每个窗⼝系统都有不同的定义,所以EGL提供基本的不透明类型—EGLDisplay, 这 个类型封装了所有系统相关性,用于和原生窗⼝系统接⼝

    主要功能

    • 和本地窗口系统(native windowing system)通讯
    • 查询可用的配置
    • 创建OpenGL ES 可用的绘图表面drawing surface
    • 同步不同类别的API之间的渲染,比如在OpenGL ESOpenVG之间同步,或者在OpenGL和本地窗口的绘图命令之间
    • 管理渲染资源,比如纹理映射(Rendering map
    GLSL语言

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

    • 使用vsh、fsh后缀的原因是方便区分着色器,其本质就是一个字符串
    • 是否可以直接使用NSString?并不建议这样做,因为代码结构不清晰,不易读
    • 这两个文件中是否可以加中文注释?不建议加中文注释,会报奇怪的错误,由于在xcode中书写GLSL,完全是纯手写,没有任何提示,排查问题不好排查
    类型及API的总结

    向量数据类型
    常用的vec2、vec3、vec4,默认是浮点类型

    vec2,vec3,vec4
    2分量、3分量、4分量浮点向量
    ivec2,ivec3,ivec4
    2分量、3分量、4分量整型向量
    uvec2,uvec3,uvec4
    2分量、3分量、4分量无符号整型向量
    bvec2,bvec3,bvec4
    2分量、3分量、4分量bool型向量

    矩阵数据类型

    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;
    } 
    

    <none> 只是普通的本地变量,外部不见,外部不可访问
    const ⼀个编译常量,或者说是⼀个对函数来说为只读的参数
    in/varying 从以前阶段传递过来的变量
    in/varying centroid ⼀个从以前的阶段传递过来的变量,使⽤质⼼插值
    out/attribute 传递到下⼀个处理阶段或者在⼀个函数中指定⼀个返回值
    out/attribute centroid 传递到下⼀个处理阶段,质心插值
    uniform ⼀个从客户端代码传递过来的变量,在顶点之间不做改变

    OpenGL ES 错误处理

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

    GL_NO_ERROR 从上⼀次调⽤glGetError 以来没有生成任何错误
    GL_INVALID_ENUM GLenum 参数超出范围,忽略生成错误命令
    GL_INVALID_VALUE 数值型 参数超出范围,忽略生成错误命令
    GL_INVALID_OPERATION 特定命令在当前OpenGL ES 状态⽆法执⾏
    GL_OUT_OF_MEMORY 内存不足时执⾏该命令,如果遇到这个错误,除⾮当前错误代码,否则OpenGL ES 管线的 状态被认为未定义

    OpenGL ES 自定义着色器常用API

    自定义着色器

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

    • 创建顶点着色器/片元着色器 --glCreateShader
    • 指定shadersource --glShaderSource
    • 编译shader --glCompileShader

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


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

    自定义程序

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

    • 创建一个程序对象 --glCreateProgram
    • 着色器与程序连接/附着 --glAttachShader
    • 链接程序 --glLinkProgram
    • 使用程序 --glUseProgram

    创建与链接程序的相关API


    创建与链接程序的相关API
    着色器与程序的 编译 & 链接
    • 需要创建2个基本对象才能使用着色器进行传染:着色器对象和程序对象
    • 获取链接后着色器对象一般的编译&链接分为6步:
    • 创建一个顶点着色器对象和一个片元着色器对象
    • 将源代码链接到每个着色器对象
    • 编译着色器对象
    • 创建一个程序对象
    • 将编译后的着色器对象连接到程序对象
    • 链接程序对象

    相关文章

      网友评论

          本文标题:NO.14 - OpenGL ES GLSL语言以及自定义着色器

          本文链接:https://www.haomeiwen.com/subject/hkywjktx.html