美文网首页
OpenGL ES - GLSL 语言简介 加实战

OpenGL ES - GLSL 语言简介 加实战

作者: Th丶小伟 | 来源:发表于2020-05-07 15:19 被阅读0次

    基础语法

    int i = 300;
    float f = 2.0f;//floact类型必须要有f
    bool b = true;
    
    聚合数据类型 - 向量
            2D向量  3D向量  4D向量
    float    vec2    vec3    vec3
    int     ivec2   ivec3   ivec4
    bool    bvec2   bvec3   bvec4
    
    //定义:
    vec3 position = vec3(0.0f, 0.3f, 0.5f);
    
    聚合数据类型 - 矩阵
    
    float   mat2(2*2矩阵)   mat3(3*3矩阵)   mat4x3 (4*3矩阵)
    注意:举证相乘 需要看是否能链接 
    比如 mat4x3 与 mat3x2  得到一个4x2矩阵  换位置相乘无意义 
    
    还可以用结构体
    
    

    注意 : GLSL文件里面不要加注释 有时候会编译不过

    修饰符

    uniform

    外部(客户端)传递给vertext和fragment。

    1. 类似于const ,被uniform修饰的变量在顶点、片元着色器就只能用不能修改
    uniform mate4 viewP;//mate4 为4x4矩阵
    

    attribute

    只能在顶点着色器使用 。用来表示顶点数据 (vertex shader)

    attribute vec4 position;
    

    varying

    顶点着色器(vertex shader)传递数据到片元着色器中(fragment shader)

    //顶点着色器 和 片元着色器 都声明这个
    varying lowp vec2 varyTextCoord;  
    

    in out inout

    1. in 修饰输入变量
    2. out 修饰输出变量
    3. inout 修饰输入输出变量

    精度设置

    高精度

    attribute highp vec4 position;
    floating Point Range 范围在(-262,262)
    Integer Range 范围在(-216,216)

    中精度

    attribute mediump vec2 textCoordinate;
    floating Point Range 范围在 (-214,214);
    Integer Range 范围在(-210,210)

    低精度

    varying lowp vec2 varyTextCoord;
    floating Point Range 范围在 (-2,2);
    Integer Range 范围在(-28,28)

    低精度可以往高进度 转换:所以 int 的高&中精度可以转 float的高&中精度 。int 低进度不能转 float的低精度

    注意:在顶点着色器里面已经默认了高精度。片元着色器没有默认,所以片元着色器需要自己写精度。

    内键变量已经有默认精度

    OpenGL ES 使用GLSL绘制图片

    流程

    • 需要创建2个基本对象才能用着色器进行渲染:着色器对象和程序对象(GLuint myPrograme)
    • 获取连接后着色器对象 的 一般过程包括6个步骤
      • 创建一个顶点着色器对象和一个片元着色器对象
      • 将源代码连接到每个着色器对象
      • 编译着色器
      • 创建一个程序对象
      • 将编译后的着色器对象连接到程序对象
      • 连接程序对象

    创建着色器文件(顶点着色器&片元着色器)

    文件名 shaderv.vsh (顶点着色器)
    attribute vec4 position;
    attribute vec2 textCoordinate;
    varying lowp vec2 varyTextCoord;
    void main(){
        varyTextCoord = textCoordinate;
        gl_Position = position;
    }
    
    文件名 shaderf.fsh (片元着色器)
    varying lowp vec2 varyTextCoord;
    uniform sampler2D colorMap;
    void main(){
        gl_FragColor = texture2D(colorMap,varyTextCoord);
    } 
    
    

    IOS端伪代码

    开始绘制
    -(void)randerLayer{
            //设置清屏颜色
           glClearColor(0.3f, 0.45f, 0.5f, 1.0f);
           //清除屏幕
           glClear(GL_COLOR_BUFFER_BIT);
           
           //1.设置视口大小
           CGFloat scale = [[UIScreen mainScreen]scale];
           glViewport(self.frame.origin.x * scale, self.frame.origin.y * scale, self.frame.size.width * scale, self.frame.size.height * scale);
           
            //2.读取顶点着色程序、片元着色程序
           NSString *vertFile = [[NSBundle mainBundle]pathForResource:@"shaderv" ofType:@"vsh"];
           NSString *fragFile = [[NSBundle mainBundle]pathForResource:@"shaderf" ofType:@"fsh"];
           //3.加载shader
           self.myPrograme = [self loadShaders:vertFile Withfrag:fragFile];
           
           //4.链接
           glLinkProgram(self.myPrograme);
           GLint linkStatus;
           //获取链接状态
           glGetProgramiv(self.myPrograme, GL_LINK_STATUS, &linkStatus);
        
           if (linkStatus == GL_FALSE) {
               GLchar message[512];
               glGetProgramInfoLog(self.myPrograme, sizeof(message), 0, &message[0]);
               NSString *messageString = [NSString stringWithUTF8String:message];
               NSLog(@"Program Link Error:%@",messageString);
               return;
           }
           
           NSLog(@"Program Link Success!");
           //5.使用program
           glUseProgram(self.myPrograme);
           
           ...(顶点设置 纹理设置)
           
    //       传入着色器 属性
    //(1)注意:第二参数字符串必须和shaderv.vsh中的输入变量:position保持一致
           GLuint position = glGetAttribLocation(self.myPrograme, "position");
           
           //(2).设置合适的格式从buffer里面读取数据
           glEnableVertexAttribArray(position);
           
           //(3).设置读取方式
           //参数1:index,顶点数据的索引
           //参数2:size,每个顶点属性的组件数量,1,2,3,或者4.默认初始值是4.
           //参数3:type,数据中的每个组件的类型,常用的有GL_FLOAT,GL_BYTE,GL_SHORT。默认初始值为GL_FLOAT
           //参数4:normalized,固定点数据值是否应该归一化,或者直接转换为固定值。(GL_FALSE)
           //参数5:stride,连续顶点属性之间的偏移量,默认为0;
           //参数6:指定一个指针,指向数组中的第一个顶点属性的第一个组件。默认为0
           glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, sizeof(GLfloat) * 5, NULL);
           
           
           //9.----处理纹理数据-------
           //(1).glGetAttribLocation,用来获取vertex attribute的入口的.
           //注意:第二参数字符串必须和shaderv.vsh中的输入变量:textCoordinate保持一致
           GLuint textCoor = glGetAttribLocation(self.myPrograme, "textCoordinate");
           
           //(2).设置合适的格式从buffer里面读取数据
           glEnableVertexAttribArray(textCoor);
           //(3).设置读取方式
           //参数1:index,顶点数据的索引
           //参数2:size,每个顶点属性的组件数量,1,2,3,或者4.默认初始值是4.
           //参数3:type,数据中的每个组件的类型,常用的有GL_FLOAT,GL_BYTE,GL_SHORT。默认初始值为GL_FLOAT
           //参数4:normalized,固定点数据值是否应该归一化,或者直接转换为固定值。(GL_FALSE)
           //参数5:stride,连续顶点属性之间的偏移量,默认为0;
           //参数6:指定一个指针,指向数组中的第一个顶点属性的第一个组件。默认为0
           glVertexAttribPointer(textCoor, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*5, (float *)NULL + 3);
    
        ...(加载纹理)
        
         //11. 设置纹理采样器 sampler2D
           glUniform1i(glGetUniformLocation(self.myPrograme, "colorMap"), 0);
           
        ...(绘图)
    }
    
    #pragma mark - shader 链接
    -(GLuint)loadShaders:(NSString*)vert Withfrag:(NSString*)frag{
        GLuint verShader,fragShader;
        GLuint program = glCreateProgram();
        //编译
        [self compileShader:&verShader type:GL_VERTEX_SHADER file:vert];
        [self compileShader:&fragShader type:GL_FRAGMENT_SHADER file:frag];
        
        //着色器连接到program
        glAttachShader(program, verShader);
        glAttachShader(program, fragShader);
        //连接之后需要删除
        glDeleteShader(verShader);
        glDeleteShader(fragShader);
        
        return program;
    }
    #pragma mark - shader 编译
    -(void)compileShader:(GLuint*)shader type:(GLenum)type file:(NSString*)file{
        //1。读取文件路径 字符串
        NSString *content = [NSString stringWithContentsOfFile:file encoding:NSUTF8StringEncoding error:nil];
        const GLchar *source = (GLchar*)[content UTF8String];
        //2、创建着色器 - 需要指定是顶点着色器还是片元着色器
        *shader = glCreateShader(type);
        /*
         3、着色器 代码 -> 附着到 着色器上面
         参数1:shader 要编译的着色器对象 *shader
         参数2:numberOfString 传递的源码字符串数量 1个
         参数3:strings,着色器程序的源码(真正的着色器程序源码)
         参数4:lenOfStrings,长度,具有每个字符串长度的数组,或NULL,这意味着字符串是NULL终止的
         */
        glShaderSource(*shader, 1, &source, NULL);//1 传的是1个source
        //4.着色器源码编译成目标代码
        glCompileShader(*shader);
    }
    
    
    

    函数汇总

    glDeleteShader(GLuint shader)
        shader - 要上去的着色器对象句柄
        
        glShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
        shader - 指向着色器对象句柄
        count - 着色器源字符串的数量,着色器可以由多个源字符串组成,但每个着色器只有一个main函数
        string - 指向保存数量的count着色器源字符串的数组指针
        length - 指向保存每个着色器字符串大小且元素数量为count的整数数组指针
       
    glCompileShader(GLuint shader)
        shader - 需要编译的着色器对象句柄
        
    glGetShaderiv(GLuint shader, GLenum pname, GLint *params)
        shader - 需要变异的着色器句柄
        pname - 获取的信息参数。可以为GL_COMPILE_STATUS/GL_DELETE_STATUS/ GL_INFO_LOG_LENGTH/GL_SHADER_SOURCE_LENGTH/ GL_SHADER_TYPE
        params - 指向查询结果的整数储存位置指针
        
    void glGetShaderInfolog(GLuint shader , GLSizei maxLength, GLSizei *length , GLChar *infoLog);
        shader — 需要获取信息⽇日志的着⾊色器器对象句句柄
        maxLength — 保存信息⽇日志的缓存区⼤大⼩小
        length — 写⼊入的信息⽇日志的⻓长度(减去null 终⽌止符); 如果不不需要知道⻓长度. 这个参数可以为Null infoLog — 指向保存信息⽇日志的字符缓存区的指针.
        
        从程序信息⽇日志中获取信息
        void glGetPorgramInfoLog( GLuint program ,GLSizei maxLength, GLSizei *length , GLChar *infoLog )
        program : 指向需要获取信息的程序对象句句柄
        maxLength : 存储信息⽇日志的缓存区⼤大⼩小
        length : 写⼊入的信息⽇日志⻓长度(减去null 终⽌止符),如果不不需要知道⻓长度,这个参数可以为Null. infoLog : 指向存储信息⽇日志的字符缓存区的指针
        void glUseProgram(GLuint program) program: 设置为活动程序的程序对象句句柄
    
        
    GLUint glCreateProgram( )
        创建⼀一个程序对象
        返回值: 返回⼀一个执⾏行行新程序对象的句句柄
        
    void glDeleteProgram( GLuint program )
        program : 指向需要删除的程序对象句句柄
        
        着⾊色器器与程序连接/附着
    void glAttachShader( GLuint program , GLuint shader );
        program : 指向程序对象的句句柄
        shader : 指向程序连接的着⾊色器器对象的句句柄
        
        断开连接
    void glDetachShader(GLuint program);
        program : 指向程序对象的句句柄
        shader : 指向程序断开连接的着⾊色器器对象句句柄
        
    glLinkProgram(GLuint program)
        program - 指向程序对象句柄
        
        链接程序之后, 需要检查链接是否成功. 你可以使⽤用glGetProgramiv 检查链接状态:
    void glGetProgramiv (GLuint program,GLenum pname, GLint *params);
        program: 需要获取信息的程序对象句句柄 pname : 获取信息的参数,可以是:
        GL_ACTIVE_ATTRIBUTES GL_ACTIVE_ATTRIBUTES_MAX_LENGTH GL_ACTIVE_UNIFORM_BLOCK GL_ACTIVE_UNIFORM_BLOCK_MAX_LENGTH GL_ACTIVE_UNIFROMS GL_ACTIVE_UNIFORM_MAX_LENGTH GL_ATTACHED_SHADERS GL_DELETE_STATUS
        GL_INFO_LOG_LENGTH
        GL_LINK_STATUS GL_PROGRAM_BINARY_RETRIEVABLE_HINT GL_TRANSFORM_FEEDBACK_BUFFER_MODE GL_TRANSFORM_FEEDBACK_VARYINGS GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH GL_VALIDATE_STATUS
        课程研发:CC⽼老老师 课程授课:CC⽼老老师
        params : 指向查询结果整数存储位置的指针
    
    
    

    源码下载

    相关文章

      网友评论

          本文标题:OpenGL ES - GLSL 语言简介 加实战

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