由于iOS屏幕坐标中Y轴向下为正方向,即大家所熟知的左上角为(0,0),而OpenGL中纹理坐标系中左下角为(0,0),因此如不做处理时,默认贴图纹理是翻转效果的。
上篇文章案例中我们使用GLKit时,使用以下方法处理纹理翻转
//2.设置纹理参数
//纹理坐标原点是左下角,但是图片显示原点应该是左上角.
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:@(1),GLKTextureLoaderOriginBottomLeft, nil];
GLKTextureInfo *textureInfo = [GLKTextureLoader textureWithContentsOfFile:filePath options:options error:nil];
这是使用GLKit时设置Options,指定翻转后GLKit会继续处理翻转纹理。
那么在使用可编程管线GLSL中,本文列举以下几种方法处理:
1.翻转原始纹理坐标
修改前默认纹理坐标如下:
//前3个是顶点坐标,后2个是纹理坐标
GLfloat attrArr[] =
{
0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f,
0.5f, 0.5f, 0.0f, 1.0f, 1.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
};
由于纹理坐标是0-1的,所以我们只需要用 1 减 原来的纹理坐标的y值,即可完成翻转,如下:
GLfloat attrArr[] =
{
0.5f, -0.5f, -1.0f, 1.0f, 1 - 0.0f,
-0.5f, 0.5f, -1.0f, 0.0f, 1 - 1.0f,
-0.5f, -0.5f, -1.0f, 0.0f, 1 - 0.0f,
0.5f, 0.5f, -1.0f, 1.0f, 1 - 1.0f,
-0.5f, 0.5f, -1.0f, 0.0f, 1 - 1.0f,
0.5f, -0.5f, -1.0f, 1.0f, 1 - 0.0f,
};
2.翻转图片源文件
在解压过程中,可以对图片的源文件进行翻转,代码如下:
// 第二种方法:解决翻转问题,平移再翻转Y轴
//把spriteContext沿Y轴正方向移动图片的高度
CGContextTranslateCTM(spriteContext, 0, rect.size.height);
//把图片直接翻转过来
CGContextScaleCTM(spriteContext, 1.0, -1.0);
CGContextDrawImage(spriteContext, rect, spriteImage);
3.通过旋转矩阵直接旋转图形
在加载纹理时,把图形直接旋转180度即可,如下先写一个旋转矩阵传入顶点着色器.
//解决纹理翻转
- (void)rotateTextureImage{
//注意,想要获取shader里面的变量,这里记得要在glLinkProgram后面,后面,后面!
//1. rotate等于shaderv.vsh中的uniform属性,rotateMatrix
GLuint rotate = glGetUniformLocation(self.myPrograme, "rotateMatrix");
//2.获取渲旋转的弧度
float radias = 180 * 3.1415926 / 180.0f;
//3.求得弧度对于的sin\cos值
float s = sin(radias);
float c = cos(radias);
//4.在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);
}
然后在顶点着色器中接收到旋转矩阵后与原始定点位置相乘即可。
//顶点着色器GLSL代码
attribute vec4 position;
attribute vec2 textCoordinate;
uniform mat4 rotateMatrix;
varying lowp vec2 varyTextCoord;
void main()
{
varyTextCoord = textCoordinate;
vec4 pox = position;
gl_Position = pox *rotateMatrix;
}
4. 修改着色器里的纹理坐标
我们可以修改顶点着色器里的纹理坐标或者修改片元着色器里的纹理坐标,两种方式原理是一样的。
修改顶点着色器
attribute vec4 position;
attribute vec2 textCoordinate;
varying lowp vec2 varyTextCoord;
void main()
{
varyTextCoord = vec2(textCoordinate.x,1.0 - textCoordinate.y);
gl_Position = position;
}
修改片元着色器
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));
}
以上为几种纹理翻转解决方案,使用GLKit时则较为简单,GLSL时个人偏向第二种解决方案,代码简单,一个地方即可处理完毕。
网友评论