05-探索纹理翻转的解决策略

2019-06-24  本文已影响0人  SPIREJ

第1种:旋转矩阵翻转图形,不翻转纹理

  1. 在顶点着色器程序shaderv.vsh中声明一个旋转矩阵uniform mat4 rotateMatrix;
    顶点数组 ✖️ 旋转矩阵 赋值给内建变量gl_Position
attribute vec4 position;
attribute vec2 textCoordinate;
uniform mat4 rotateMatrix;

varying lowp vec2 varyTextCoord;

void main()
{
    varyTextCoord = textCoordinate;

    vec4 vPos = position;
    vPos = vPos * rotateMatrix;
    
    gl_Position = vPos;
}

2.解决纹理翻转方法1

//注意,想要获取shader里面的变量,这里记得要在glLinkProgram后面,后面,后面!
//1. rotate等于shaderv.vsh中的uniform属性,rotateMatrix
GLuint rotate = glGetUniformLocation(self.myPrograme, "rotateMatrix");

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

//5.设置旋转矩阵
/*
 glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
 location : 对于shader 中的ID
 count : 个数
 transpose : 转置
 value : 指针
 */
glUniformMatrix4fv(rotate, 1, GL_FALSE, zRotation);

第2种:解压图片时,将图片源文件翻转

//1、将 UIImage 转换为 CGImageRef
CGImageRef spriteImage = [UIImage imageNamed:fileName].CGImage;

//判断图片是否获取成功
if (!spriteImage) {
    NSLog(@"Failed to load image %@", fileName);
    exit(1);
}

//2、读取图片的大小,宽和高
size_t width = CGImageGetWidth(spriteImage);
size_t height = CGImageGetHeight(spriteImage);

//3.获取图片字节数 宽*高*4(RGBA)
GLubyte * spriteData = (GLubyte *) calloc(width * height * 4, sizeof(GLubyte));

//4.创建上下文
/*
 参数1:data,指向要渲染的绘制图像的内存地址
 参数2:width,bitmap的宽度,单位为像素
 参数3:height,bitmap的高度,单位为像素
 参数4:bitPerComponent,内存中像素的每个组件的位数,比如32位RGBA,就设置为8
 参数5:bytesPerRow,bitmap的没一行的内存所占的比特数
 参数6:colorSpace,bitmap上使用的颜色空间  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);

//6.使用默认方式绘制
CGContextDrawImage(spriteContext, rect, spriteImage);

//平移画布(上下文)位置,y轴正向移动 rect.size.height
CGContextTranslateCTM(spriteContext, 0, rect.size.height);
//翻转画布,x方向不变,y方向沿着画布自己的坐标系对应的y轴渲染
CGContextScaleCTM(spriteContext, 1.0, -1.0);
CGContextDrawImage(spriteContext, rect, spriteImage);

//7、画图完毕就释放上下文
CGContextRelease(spriteContext);

//8、绑定纹理到默认的纹理ID
glBindTexture(GL_TEXTURE_2D, 0);

第3种:修改片元着色器,纹理坐标

OpenGL要求y0.0坐标是在图片的底部的,但是图片的y0.0坐标通常在顶部

我们可以改变顶点数据的纹理坐标,翻转y值(用1减去y坐标)。
我们可以编辑顶点着色器来自动翻转y坐标,替换TexCoord的值为TexCoord = vec2(texCoord.x, 1.0f - texCoord.y);

varying lowp vec2 varyTextCoord;
uniform sampler2D colorMap;

void main()
{
    //gl_FragColor = texture2D(colorMap, varyTextCoord);
    gl_FragColor = texture2D(colorMap, vec2(varyTextCoord.x,1.0-varyTextCoord.y));
}

第4种: 修改顶点着色器,纹理坐标

attribute vec4 position;
attribute vec2 textCoordinate;
varying lowp vec2 varyTextCoord;

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

第5种: 直接从源纹理坐标数据修改

GLfloat attrArr[] =
     {
     0.5f, -0.5f, 0.0f,        1.0f, 1.0f, //右下
     -0.5f, 0.5f, 0.0f,        0.0f, 0.0f, // 左上
     -0.5f, -0.5f, 0.0f,       0.0f, 1.0f, // 左下
     0.5f, 0.5f, 0.0f,         1.0f, 0.0f, // 右上
     -0.5f, 0.5f, 0.0f,        0.0f, 0.0f, // 左上
     0.5f, -0.5f, 0.0f,        1.0f, 1.0f, // 右下
     };
上一篇 下一篇

猜你喜欢

热点阅读