個人
OpenGL
專題學習目錄,但願和你們一塊兒學習交流進步!bash
- 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
加載一張圖片,可是最後發現加載出來的圖片是 倒置
的,這是 爲何 呢? post
由於 OpenGL 要求 y 軸 0.0 座標是在圖片的底部的,可是圖片的 y 軸 0.0 座標一般在頂部。 這要怎麼解決呢?下面羅列了 5
種解決策略供咱們選擇。學習
圖片之因此倒置,就是紋理座標和頂點座標的映射關係發生了錯誤,因此咱們把映射關係改對就好了。這種方法最直接最原始,也一勞永逸,可是容易在對應的時候犯糊塗出錯。測試
//6.設置頂點、紋理座標
//前3個是頂點座標,後2個是紋理座標
// GLfloat attrArr[] =
// {
// 0.5f, -0.5f, -1.0f, 1.0f, 0.0f,
// -0.5f, 0.5f, -1.0f, 0.0f, 1.0f,
// -0.5f, -0.5f, -1.0f, 0.0f, 0.0f,
//
// 0.5f, 0.5f, -1.0f, 1.0f, 1.0f,
// -0.5f, 0.5f, -1.0f, 0.0f, 1.0f,
// 0.5f, -0.5f, -1.0f, 1.0f, 0.0f,
// };
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,
};
複製代碼
- 在頂點着色器
shaderv.vsh
中,咱們傳進一個旋轉矩陣rotateMatrix
,由於矩陣傳進來就不會再修改了,因此咱們用uniform
來修飾,4 行 4 列的矩陣mat4
。而後用頂點座標vPos
乘以這個rotateMatrix
旋轉矩陣,讓每個頂點都應用旋轉變化。
⚠️ 注意只能是 vPos * rotateMatrix
,順序不能反過來,由於頂點是 1 行 4 列,旋轉矩陣是 4 行 4 列。 shaderv.vsh
中:ui
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;
}
複製代碼
源碼中:spa
- (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,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);
}
複製代碼
使用下面三行代碼,對圖片進行了平移縮放操做之後,再從新繪製。指針
CGContextTranslateCTM(spriteContext, 0, rect.size.height);
CGContextScaleCTM(spriteContext, 1.0, -1.0);
CGContextDrawImage(spriteContext, rect, spriteImage);
複製代碼
從圖片加載紋理的總體代碼以下:code
//從圖片中加載紋理
- (GLuint)setupTexture:(NSString *)fileName {
//一、將 UIImage 轉換爲 CGImageRef
CGImageRef spriteImage = [UIImage imageNamed:fileName].CGImage;
//二、讀取圖片的大小,寬和高
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);
//五、在CGContextRef上--> 將圖片繪製出來
CGRect rect = CGRectMake(0, 0, width, height);
//6.使用默認方式繪製
//CGContextDrawImage(spriteContext, rect, spriteImage);
// 圖片翻轉後繪製
CGContextTranslateCTM(spriteContext, 0, rect.size.height);
CGContextScaleCTM(spriteContext, 1.0, -1.0);
CGContextDrawImage(spriteContext, rect, spriteImage);
//七、畫圖完畢就釋放上下文
CGContextRelease(spriteContext);
//八、綁定紋理到默認的紋理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_LINEAR );
glTexParameteri( GL_TEXTURE_2D, 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, 0, GL_RGBA, fw, fh, 0, GL_RGBA, GL_UNSIGNED_BYTE, spriteData);
//11.釋放spriteData
free(spriteData);
return 0;
}
複製代碼
這裏是修改了片元着色器的代碼,x 座標不動,將 y 座標改成 1-y,這樣就達到了翻轉的效果。其餘地方代碼不用動。orm
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));
}
複製代碼
在頂點着色器傳入的時候,就翻轉。相比上面的片元着色器,執行次數要少不少,有幾個頂點執行幾回。cdn
attribute vec4 position;
attribute vec2 textCoordinate;
varying lowp vec2 varyTextCoord;
void main() {
varyTextCoord = vec2(textCoordinate.x,1.0-textCoordinate.y);
gl_Position = position;
}
複製代碼
上面五種方法均可以解決圖片倒置問題,第一種是最直接也是最原始的修改方式,但容易映射關係出錯。第二種和第三種相對麻煩。後兩種只用修改一行代碼最輕鬆,喜歡選哪一種看你的了。最後就獲得了正着的圖片啦!
轉載請備註原文出處,不得用於商業傳播——凡幾多