OpenGL學習(十二)-- OpenGL ES 紋理翻轉的策略對比
阿新 • • 發佈:2019-12-25
我的
OpenGL
專題學習目錄,希望和大家一起學習交流進步!
- OpenGL學習(一)-- 術語瞭解
- OpenGL學習(二)-- Xcode 搭建 OpenGL 環境
- OpenGL學習(三)-- OpenGL 基礎渲染
- OpenGL學習(四)-- 正面&背面剔除和深度測試
- OpenGL學習(五)-- 裁剪與混合
- OpenGL學習(六)-- 基礎紋理
- OpenGL學習(七)-- 基礎變化綜合練習實踐總結
- OpenGL學習(八)-- OpenGL ES 初探(上)
- OpenGL學習(九)-- OpenGL ES 初探(下)GLKit
- OpenGL學習(十)-- 著色語言 GLSL 語法介紹
- OpenGL學習(十一)-- 用 GLSL 實現載入圖片
- OpenGL學習(十二)-- OpenGL ES 紋理翻轉的策略對比
一、前言
我在上一篇 OpenGL學習(十二)-- OpenGL ES 紋理翻轉的策略對比 講了如果用 GLSL
載入一張圖片,但是最後發現加載出來的圖片是 倒置
的,這是 為什麼 呢?
因為 OpenGL 要求 y 軸 0.0 座標是在圖片的底部的,但是圖片的 y 軸 0.0 座標通常在頂部。
這要怎麼解決呢?下面羅列了 5
種解決策略供我們選擇。
二、紋理翻轉策略
1、修改紋理座標和頂點座標的對映關係
圖片之所以倒置,就是紋理座標和頂點座標的對映關係發生了錯誤,所以我們把對映關係改對就行了。這種方法最直接最原始,也一勞永逸,但是容易在對應的時候犯糊塗出錯。
//6.設定頂點、紋理座標
//前3個是頂點座標,後2個是紋理座標
// GLfloat attrArr[] =
// {
// 0.5f,-0.5f,-1.0f,1.0f,0.0f,// -0.5f,0.5f,//
// 0.5f,// 0.5f,// };
GLfloat attrArr[] =
{
0.5f,};
複製程式碼
2、旋轉矩陣翻轉圖形,不翻轉紋理
- 在頂點著色器
shaderv.vsh
中,我們傳進一個旋轉矩陣rotateMatrix
,因為矩陣傳進來就不會再修改了,所以我們用uniform
來修飾,4行 4 列的矩陣mat4
。然後用頂點座標vPos
乘以這個rotateMatrix
旋轉矩陣,讓每一個頂點都應用旋轉變化。
⚠️ 注意只能是 vPos * rotateMatrix
,順序不能反過來,因為頂點是 1 行 4 列,旋轉矩陣是 4 行 4 列。
shaderv.vsh
中:
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;
}
複製程式碼
原始碼中:
- (void)rotateTextureImage {
//注意,想要獲取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,s,c,1,1
};
//5.設定旋轉矩陣
/*
glUniformMatrix4fv (GLint location,GLsizei count,GLboolean transpose,const GLfloat* value)
location : 對於shader 中的ID
count : 個數
transpose : 是否需要轉置
value : 指標
*/
glUniformMatrix4fv(rotate,GL_FALSE,zRotation);
}
複製程式碼
3、在解壓圖片時,將圖片原始檔翻轉
使用下面三行程式碼,對圖片進行了平移縮放操作以後,再重新繪製。
CGContextTranslateCTM(spriteContext,rect.size.height);
CGContextScaleCTM(spriteContext,1.0,-1.0);
CGContextDrawImage(spriteContext,rect,spriteImage);
複製程式碼
從圖片載入紋理的整體程式碼如下:
//從圖片中載入紋理
- (GLuint)setupTexture:(NSString *)fileName {
//1、將 UIImage 轉換為 CGImageRef
CGImageRef spriteImage = [UIImage imageNamed:fileName].CGImage;
//2、讀取圖片的大小,寬和高
size_t width = CGImageGetWidth(spriteImage);
size_t height = CGImageGetHeight(spriteImage);
//3.獲取圖片位元組數 寬*高*4(RGBA)
GLubyte * spriteData = (GLubyte *) calloc(width * height * 4,sizeof(GLubyte));
//4.建立上下文
CGContextRef spriteContext = CGBitmapContextCreate(spriteData,width,height,8,width*4,CGImageGetColorSpace(spriteImage),kCGImageAlphaPremultipliedLast);
//5、在CGContextRef上--> 將圖片繪製出來
CGRect rect = CGRectMake(0,height);
//6.使用預設方式繪製
//CGContextDrawImage(spriteContext,spriteImage);
// 圖片翻轉後繪製
CGContextTranslateCTM(spriteContext,spriteImage);
//7、畫圖完畢就釋放上下文
CGContextRelease(spriteContext);
//8、繫結紋理到預設的紋理ID
glBindTexture(GL_TEXTURE_2D,0);
//9.設定紋理屬性
glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR );
glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri( GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
float fw = width,fh = height;
//10.載入紋理2D資料
glTexImage2D(GL_TEXTURE_2D,GL_RGBA,fw,fh,GL_UNSIGNED_BYTE,spriteData);
//11.釋放spriteData
free(spriteData);
return 0;
}
複製程式碼
4、修改片元著色器中的紋理座標
這裡是修改了片元著色器的程式碼,x 座標不動,將 y 座標改為 1-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));
}
複製程式碼
5、修改頂點著色器中的紋理座標
在頂點著色器傳入的時候,就翻轉。相比上面的片元著色器,執行次數要少很多,有幾個頂點執行幾次。
attribute vec4 position;
attribute vec2 textCoordinate;
varying lowp vec2 varyTextCoord;
void main() {
varyTextCoord = vec2(textCoordinate.x,1.0-textCoordinate.y);
gl_Position = position;
}
複製程式碼
上面五種方法都可以解決圖片倒置問題,第一種是最直接也是最原始的修改方式,但容易對映關係出錯。第二種和第三種相對麻煩。後兩種只用修改一行程式碼最輕鬆,喜歡選哪種看你的了。最後就得到了正著的圖片啦!
轉載請備註原文出處,不得用於商業傳播——凡幾多