美文网首页
OpenGL ES 纹理翻转策略

OpenGL ES 纹理翻转策略

作者: 紫水依 | 来源:发表于2019-07-14 19:44 被阅读0次

背景:使用GLSL渲染一张图片到屏幕上,发现图片是倒置的,这是因为屏幕的坐标原点在左上角,向右和向下为x和y正方向,而图片纹理坐标原点在左下角,向右和向上为正方向,导致图片渲染显示倒置。这就需要纹理翻转让图片显示正常。

基本策略有:

  1. 改变顶点数据的纹理坐标,翻转y值(1-y)
  2. 顶点着色器翻转y坐标,替换texCoord的值为```texCoord = vec2(texCoord.x, 1.0-texCoord.y);

纹理翻转的几种方式

1、GLKit处理纹理翻转

//设置纹理
- (void)setUpTexture {
    //获取纹理图片路径
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"hua" ofType:@"jpg"];
    
    //设置纹理相关参数,纹理原点左下角,view原点左上角
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:@(1), GLKTextureLoaderOriginBottomLeft, nil];
    GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];
    
    //GLBaseEffect完成着色器工作
    cEffect = [[GLKBaseEffect alloc] init];
    cEffect.texture2d0.enabled = GL_TRUE;
    cEffect.texture2d0.name = textureInfo.name;
}

2、修改顶点着色器,传递旋转矩阵让图形翻转,不翻转纹理

图形的顶点坐标乘以旋转矩阵旋转180°,纹理坐标不变

//传递旋转矩阵,旋转180度
- (void)rotateTextureImage {
    //!!!注意:获得shader里面的变量需要在glLinkProgram后面
    //获取顶点着色器的旋转矩阵rotateMatrix
    GLuint rotate = glGetUniformLocation(self.myProgram, "rotateMatrix");
    
    //旋转的弧度,度数转弧度
    float radians = 180 * 3.14159 / 180.0;
    
    //弧度对应的sin和cos值
    float s = sin(radians);
    float c = cos(radians);
    
    //Z轴旋转矩阵
    GLfloat zRotation[16] = {
        c, -s, 0, 0,
        s, c, 0, 0,
        0, 0, 1, 0,
        0, 0, 0, 1
    };
    
    /*
     glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value);
     location:shader的ID
     count:旋转矩阵个数
     transpose:是否转置,是否横向矩阵转为列项矩阵
     value:传递数据的指针,首地址
     */
    glUniformMatrix4fv(rotate, 1, GL_FALSE, zRotation);
    
}

顶点着色器顶点坐标乘以旋转矩阵

attribute vec4 position;
attribute vec2 textCoordinate;

uniform mat4 rotateMatrix; //旋转矩阵

varying lowp vec2 varyTextCoord;

void main() {
    varyTextCoord = textCoordinate;
    
    vec4 vPos = position; //精度已经预定义,不需要指定精度
    vPos = vPos * rotateMatrix; //顶点坐标乘以旋转矩阵,每一个顶点都应用旋转变化
    /*不能rotateMatrix * vPos,因为vPos是一行四列,rotateMatrix是四行四列,
    vPos * rotateMatrix会得到新的一行四列的顶点坐标,反过来矩阵相乘没有意义*/
    
    gl_Position = vPos;
}

3、解压缩绘制图片时使用CoreGraphic旋转纹理

解压缩绘制图片时将图片翻转180°

    /**
     创建上下文  CoreGraphic

     @param spriteData 指向要渲染的绘图的内存地址
     @param width bitmap的宽,单位是像素
     @param height bitmap的高,单位是像素
     @param 8 bitPerComponent,内存中像素的每个组件的位数,比如32位GRBA,就设置为8
     @param 4 bytesPerRow,bitmap的每一行的内存所占的比特数
     @param spriteData colorSpace,bitmap使用的颜色空间
     @param kCGImageAlphaPremultipliedLast颜色信息 RGBA
     */
    CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width * 4, CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);

    //绘制图片
    CGRect rect = CGRectMake(0, 0, width, height);
    CGContextDrawImage(spriteContext, rect, spriteImage);

    CGContextTranslateCTM(spriteContext, rect.origin.x, rect.origin.y);
    CGContextTranslateCTM(spriteContext, 0, rect.size.height);
    CGContextScaleCTM(spriteContext, 1.0, -1.0);
    CGContextTranslateCTM(spriteContext, -rect.origin.x, -rect.origin.y);
    CGContextDrawImage(spriteContext, rect, spriteImage);

    CGContextRelease(spriteContext);

4、修改片元着色器,翻转纹理坐标的y值

x坐标不变,y坐标翻转:1-y坐标;每一个像素点都会执行y坐标翻转,会执行很多次

varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;

void main() {
    //获取纹理坐标时,x坐标不变,y坐标翻转:1-y坐标
   gl_FragColor = texture2D(colorMap, vec2(varyTextCoord.x, 1.0-varyTextCoord.y));
    
}

5、修改顶点着色器,翻转顶点坐标的y值

x坐标不变,y坐标翻转:1-y坐标;图形的每个顶点都会执行y坐标翻转,会执行6次

attribute vec4 position;
attribute vec2 textCoordinate;

uniform mat4 rotateMatrix;

varying lowp vec2 varyTextCoord;

void main() {
    //x坐标不变,y坐标翻转:1-y坐标
    varyTextCoord = vec2(textCoordinate.x, 1.0-textCoordinate.y);
    
    gl_Position = position;
}

6、修改顶点坐标和纹理坐标的映射关系

    //设置顶点/纹理坐标,正常的映射关系
//    GLfloat attrArr[] = {
//        0.5, -0.5, -1.0,     1.0, 0.0,
//        -0.5, 0.5, -1.0,     0.0, 1.0,
//        -0.5, -0.5, -1.0,    0.0, 0.0,
//
//        0.5, 0.5, -1.0,      1.0, 1.0,
//        0.5, -0.5, -1.0,     1.0, 0.0,
//        -0.5, 0.5, -1.0,     0.0, 1.0,
//    };
    
    //修改图形的顶点坐标和纹理坐标的映射关系,翻转之后的映射关系
    GLfloat attrArr[] = {
        0.5, -0.5, -1.0,     1.0, 1.0,
        -0.5, 0.5, -1.0,     0.0, 0.0,
        -0.5, -0.5, -1.0,    0.0, 1.0,
        
        0.5, 0.5, -1.0,      1.0, 0.0,
        0.5, -0.5, -1.0,     1.0, 1.0,
        -0.5, 0.5, -1.0,     0.0, 0.0,
    };

相关文章

网友评论

      本文标题:OpenGL ES 纹理翻转策略

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