美文网首页
OpenGL ES案例04_3-GLSL索引绘图添加纹理颜色混合

OpenGL ES案例04_3-GLSL索引绘图添加纹理颜色混合

作者: 卡布奇诺_95d2 | 来源:发表于2020-09-01 11:40 被阅读0次

    本案例是在OpenGL ES案例04_1-GLSL使用索引绘图基础上增加纹理颜色混合。
    最终效果如下:

    最终效果
    本案例与之前案例最大的区别是增加了纹理颜色混合。其它绘制流程一致,可参考之前案例描述或文末的完整代码。接下来描述一下如何增加纹理颜色混合。

    顶点着色器

    在顶点着色器中,需要增加纹理坐标属性,并且将纹理坐标传递给片元着器

    attribute vec4 position;
    attribute vec4 positionColor;
    attribute vec2 textCoor;
    uniform mat4 projectionMatrix;
    uniform mat4 modelViewMatrix;
    
    varying lowp vec2 vTextCoor;
    varying lowp vec4 varyColor;
    
    void main(){
        vTextCoor = textCoor;
        varyColor = positionColor;
        gl_Position = projectionMatrix * modelViewMatrix * position;
    }
    

    片元着色器

    1. 设置float为高精度。在代码中去掉该行,无法正常绘制图片。
    2. 增加获取纹理坐标的属性,该属性与在顶点着色器中必须一模一样
    3. 使用texture2D函数,通过采样器,获取当前纹理坐标的颜色值。
    4. 对传入的顶点颜色值和纹理坐标对应的颜色值进行混合计算。
    5. 将最终计算的颜色值赋值给gl_FragColor。
    precision highp float;
    
    varying lowp vec2 vTextCoor;
    varying lowp vec4 varyColor;
    uniform sampler2D colorMap;
    
    void main(){
        vec4 weakMask = texture2D(colorMap, vTextCoor);
        vec4 mask = varyColor;
        float alpha = 0.3;
    
        vec4 tempColor = mask * (1.0 - alpha) + weakMask * alpha;
        
        gl_FragColor = tempColor;
    }
    

    读取纹理数据

    1. 解压缩png/jpg图片,将UIImage转换为CGImageRef。
    CGImageRef image = [[UIImage imageNamed:@"nn.jpg"] CGImage];
    
    1. 根据CGImageRef属性获取图片的宽和高,并开辟一段空间用于存放解压缩后的位图信息。
    size_t width = CGImageGetWidth(image);
    size_t height = CGImageGetHeight(image);
    GLubyte* spriteData = (GLubyte*)calloc(width*height*4, sizeof(GLubyte));
    
    1. 创建CGContextRef上下文
    CGContextRef context = CGBitmapContextCreate(spriteData, width, height, 8, width*4, CGImageGetColorSpace(image), kCGImageAlphaPremultipliedLast);
        CGRect rect = CGRectMake(0, 0, width, height);
    
    1. 在CGContextRef上将图片绘制出来,调用CGContextDrawImage函数,使用默认方式绘制,这样就得到了纹理数据。
    CGContextDrawImage(context, rect, image);
    
    1. 得到纹理数据之后就不需要CGContextRef上下文了,可以将CGContextRef这个上下文释放掉。
    CGContextRelease(context);
    
    1. 绑定一个纹理ID,默认纹理ID为0。
    glBindTexture(GL_TEXTURE_2D, 0);
    
    1. 设置纹理的参数。
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    
    1. 载入纹理数据。
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (float)width, (float)height, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
    
    1. 释放位图信息
    free(spriteData);
    
    1. 设置纹理采样器
      主要是用来获取纹理中对应像素点的颜色值,即纹素。此处使用glUniform1i函数告诉采样器,要获取纹理ID为0的纹素。
    glUniform1i(glGetUniformLocation(self.myProgram, "colorMap"), 0);
    

    设置纹理坐标

    由于添加了纹理,因此,在设置顶点坐标的时候需要添加纹理坐标。

    1. 获取顶点着色器中定义纹理坐标属性通道。
    2. 打开纹理坐标属性通道。
    3. 将数据传入纹理坐标属性。
    -(void)setupVertexData{
        //(1)顶点数组 前3顶点值(x,y,z),后3位颜色值(RGB)
        GLfloat attrArr[] = {
            -0.5f, 0.5f, 0.0f,      0.0f, 0.0f, 0.5f,       0.0f, 1.0f,//左上
            0.5f, 0.5f, 0.0f,       0.0f, 0.5f, 0.0f,       1.0f, 1.0f,//右上
            -0.5f, -0.5f, 0.0f,     0.5f, 0.0f, 1.0f,       0.0f, 0.0f,//左下
            0.5f, -0.5f, 0.0f,      0.0f, 0.0f, 0.5f,       1.0f, 0.0f,//右下
            0.0f, 0.0f, 1.0f,       1.0f, 1.0f, 1.0f,       0.5f, 0.5f,//顶点
        };
        
        GLuint bufferID;
        glGenBuffers(1, &bufferID);
        glBindBuffer(GL_ARRAY_BUFFER, bufferID);
        glBufferData(GL_ARRAY_BUFFER, sizeof(attrArr), attrArr, GL_DYNAMIC_DRAW);
        
        GLuint position = glGetAttribLocation(self.myProgram, "position");
        glEnableVertexAttribArray(position);
        glVertexAttribPointer(position, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), NULL);
        
        GLuint positionColor = glGetAttribLocation(self.myProgram, "positionColor");
        glEnableVertexAttribArray(positionColor);
        glVertexAttribPointer(positionColor, 3, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLfloat*)NULL+3);
        
        GLuint textCoor = glGetAttribLocation(self.myProgram, "textCoor");
        glEnableVertexAttribArray(textCoor);
        glVertexAttribPointer(textCoor, 2, GL_FLOAT, GL_FALSE, 8*sizeof(GLfloat), (GLfloat*)NULL+6);
    }
    

    到此,整个Demo完成。具体代码请看GLSL三角形变换_纹理颜色混合

    相关文章

      网友评论

          本文标题:OpenGL ES案例04_3-GLSL索引绘图添加纹理颜色混合

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