美文网首页OpenGL 笔记
OpenGL笔记十三:GLSL加载纹理颠倒六种方案

OpenGL笔记十三:GLSL加载纹理颠倒六种方案

作者: 御雪飞斐 | 来源:发表于2019-06-16 23:18 被阅读113次

    前言

    期待您移步上篇:OpenGL笔记十二:初探GLSL加载图片纹理

    纹理颠倒原因

    GLSL 加载一张图片纹理,最后发现加载出来的图片是倒置的。倒置的原因,是纹理坐标的坐标原点与视觉系的坐标原点不一致造成的。
    即:纹理坐标原点 (0.0, 0.0)坐标在左下角,屏幕的坐标原点(0.0,0.0)在左上角。

    纹理颠倒解决策略

    1.使用矩阵翻转

    • 在加载纹理之后
       //解决纹理翻转(方法1)
        [self rotateTextureImage];
    
    -(void)rotateTextureImage
    {
        //注意,想要获取shader里面的变量,这里记得要在glLinkProgram后面,后面,后面!
        //1. rotate等于shaderv.vsh中的uniform属性,rotateMatrix
        GLuint rotate = glGetUniformLocation(self.myPrograme, "rotateMatrix");
        GLuint scale = glGetUniformLocation(self.myPrograme, "scaleMatrix");
        
        //2.获取渲旋转的弧度
        float radians = 180 * 3.14159f / 180.0f;
       
        //3.求得弧度对于的sin\cos值
        float s = sin(radians);
        float c = cos(radians);
        
        //4.因为在3D课程中用的是横向量,在OpenGL ES用的是列向量
        /*
         参考Z轴旋转矩阵
         */
        GLfloat zRotation[16] = {
            c,s,0,0,
            -s,c,0,0,
            0,0,1,0,
            0,0,0,1
        };
        GLfloat scaleMatrix[16] = {
            -1,0,0,0,
            0,1,0,0,
            0,0,1,0,
            0,0,0,1
        };
    
        //5.设置旋转矩阵
        /*
         glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
         location : 对于shader 中的ID
         count : 个数
         transpose : 转置
         value : 指针
         */
        
        glUniformMatrix4fv(rotate, 1, GL_FALSE, zRotation);
        glUniformMatrix4fv(scale, 1, GL_FALSE, scaleMatrix);    
    }
    
    • 对应shader 中GLSL代码
    attribute vec4 position;
    attribute vec2 textCoordinate;
    uniform mat4 rotateMatrix;
    uniform mat4 scaleMatrix;
    
    varying lowp vec2 varyTextCoord;
    
    void main()
    {
        varyTextCoord = textCoordinate;
        vec4 vPos = rotateMatrix * scaleMatrix * position;
        gl_Position = vPos;
    }
    
    • shader 中GLSL代码(另一种)不使用scaleMatrix
    attribute vec4 position;
    attribute vec2 textCoordinate;
    varying lowp vec2 varyTextCoord;
    
    uniform mat4 rotateMatrix;
    void main()
    {
        varyTextCoord = textCoordinate;
        vec4 vPos  = rotateMatrix * position;
        vPos *= vec4(-1, 1, 1, 1);
        gl_Position = vPos;
    }
    

    2.纹理读取时,翻转绘图上下文

    • 在图片加载纹理方法中
       //4.创建上下文
        /*
         参数1:data,指向要渲染的绘制图像的内存地址
         参数2:width,bitmap的宽度,单位为像素
         参数3:height,bitmap的高度,单位为像素
         参数4:bitPerComponent,内存中像素的每个组件的位数,比如32位RGBA,就设置为8
         参数5:bytesPerRow,bitmap的没一行的内存所占的比特数
         参数6:CGColorSpaceRef,colorSpace,bitmap上使用的颜色空间
         参数7:bitmapInfo,- kCGImageAlphaPremultipliedLast:RGBA
         */
        CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8,width * 4, CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);
        
        //5、在CGContextRef上--> 将图片绘制出来
        /*
         CGContextDrawImage 使用的是Core Graphics框架,坐标系与UIKit 不一样。UIKit框架的原点在屏幕的左上角,Core Graphics框架的原点在屏幕的左下角。
         CGContextDrawImage
         参数1:绘图上下文
         参数2:rect坐标
         参数3:绘制的图片
         */
        CGRect rect = CGRectMake(0, 0, width, height);
        
        CGContextTranslateCTM(spriteContext, 0, rect.size.height);//向x,平移0,向y平移rect.size.height
        CGContextScaleCTM(spriteContext, 1.0, -1.0); //x,缩放1.0,y,缩放-1.0
     
        //6.使用默认方式绘制
        CGContextDrawImage(spriteContext, rect, spriteImage);
    
    • 关键代码
        CGContextTranslateCTM(spriteContext, 0, rect.size.height);//向x,平移0,向y平移rect.size.height
        CGContextScaleCTM(spriteContext, 1.0, -1.0); //x,缩放1.0,y,缩放-1.0
    

    3.翻转verTexShader代码中gl_Position

    • 第一种
    attribute vec4 position;
    attribute vec2 textCoordinate;
    varying lowp vec2 varyTextCoord;
    void main()
    {
        varyTextCoord = textCoordinate;
        vec4 vPos  = position;
        vPos *= vec4(1, -1, 1, 1);
        gl_Position = vPos;
    }
    
    • 第二种
    attribute vec4 position;
    attribute vec2 textCoordinate;
    varying lowp vec2 varyTextCoord;
    void main()
    {
        varyTextCoord = textCoordinate;
        gl_Position = vec4(position.x, - position.y,1,1);
    }
    

    4.改变vertexShader中纹理坐标

    attribute vec4 position;
    attribute vec2 textCoordinate;
    varying lowp vec2 varyTextCoord;
    void main()
    {
        varyTextCoord = vec2(textCoordinate.x,1.0 -textCoordinate.y);
        gl_Position = position;
    }
    

    5.改变fragShader中纹理坐标

    varying lowp vec2 varyTextCoord;
    uniform sampler2D colorMap;
    void main()
    {
       gl_FragColor = texture2D(colorMap, vec2(varyTextCoord.x,1.0 -varyTextCoord.y));
    }
    

    6.修改每个顶点的纹理坐标(顶点与纹理映射关系)

        //6.设置顶点、纹理坐标
        //前3个是顶点坐标,后2个是纹理坐标
        //修改前的
        GLfloat attrArr[] =
        {
            0.5f, -0.5f, -1.0f,     1.0f, 0.0f,//1,1
            -0.5f, 0.5f, -1.0f,     0.0f, 1.0f,//0,0
            -0.5f, -0.5f, -1.0f,    0.0f, 0.0f,//0,1
    
            0.5f, 0.5f, -1.0f,      1.0f, 1.0f,//1,0
            -0.5f, 0.5f, -1.0f,     0.0f, 1.0f,//0,0
            0.5f, -0.5f, -1.0f,     1.0f, 0.0f,//1,1
        };
        //修改后
        GLfloat attrArr[] =
        {
            0.5f, -0.5f, -1.0f,     1.0f, 1.0f,
            -0.5f, 0.5f, -1.0f,     0.0f, 0.0f,
            -0.5f, -0.5f, -1.0f,    0.0f, 1.0f,
    
            0.5f, 0.5f, -1.0f,      1.0f, 0.0f,
            -0.5f, 0.5f, -1.0f,     0.0f, 0.0f,
            0.5f, -0.5f, -1.0f,     1.0f, 1.0f,
        };
    

    以上六种解决纹理图片掉到问题的方法。
    如有疑问或更进,请不吝指教。

    期待您移步下篇:OpenGL笔记十四:GLSL语法

    相关文章

      网友评论

        本文标题:OpenGL笔记十三:GLSL加载纹理颠倒六种方案

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