紋理翻轉(zhuǎn)解析
我們在使用紋理貼圖來渲染一張圖片的時,在解壓縮紋理圖像的過程中,畫出來的位圖原點是從圖像的左下角開始的,畫出的結(jié)果就是倒置的,怎么讓它翻轉(zhuǎn)過來呢?這就需要在圖片渲染過程中紋理相關(guān)的部分處理了。

原圖

上下倒置的鏡像圖
倒置圖看起來就像是原圖在水面上的倒影,是個上下倒置的鏡像圖。
1. 修改紋理坐標
首先,頂點坐標是和紋理坐標相對應(yīng)的。圖片角度不對,就依次改變頂點對應(yīng)的紋理坐標實現(xiàn)翻轉(zhuǎn)。數(shù)組中每行最后兩列的紋理坐標由:
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,
};
這種做法一勞永逸。但是需要一個一個對照著改,很麻煩。如果頂點很多,在修改紋理坐標時也是很費時的。
2.解壓圖片時翻轉(zhuǎn)
在渲染之前我們需要把png或者jpg之類的圖片進行解壓縮,而解壓縮其實就是重新繪制成位圖。在獲取圖片數(shù)據(jù)后,可以先把圖片翻轉(zhuǎn),然后再繪制。
使用Quartz中用戶空間和設(shè)備空間中間的轉(zhuǎn)換矩陣CTM實現(xiàn)。下面的圖畫的不是太準確,理解就好,不糾結(jié)。
CGRect rect = CGRectMake(0, 0, width, height);
CGContextTranslateCTM(bitmapContext, 0, rect.size.height);
CGContextScaleCTM(bitmapContext, 1, -1);
先下移一個圖片高度,再針對Y軸做一個鏡像。

QQ20190611-095926@2x.png
3. 使用旋轉(zhuǎn)矩陣
創(chuàng)建一個旋轉(zhuǎn)180度的矩陣,通過uniform通道傳給頂點著色器。
//1. rotate等于shaderv.vsh中的uniform屬性,rotateMatrix
GLuint rotate = glGetUniformLocation(self.myPrograme, "rotateMatrix");
//2.獲取渲旋轉(zhuǎn)的弧度
float radians = 180 * (M_PI / 180.0f);
//3.求得弧度對于的sin\cos值
float s = sin(radians);
float c = cos(radians);
//4.定義旋轉(zhuǎn)矩陣
GLfloat zRotation[16] = {
1,0,0,0,
s,c,0,0,
c,-s,0,0,
0,0,0,1
};
//5.設(shè)置旋轉(zhuǎn)矩陣
glUniformMatrix4fv(rotate, 1, GL_FALSE, zRotation);
著色器部分把頂點向量和旋轉(zhuǎn)矩陣相乘或得一個旋轉(zhuǎn)后的頂點位置:
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;
}
4.在頂點著色器中修改
用1.0減去紋理坐標的Y值,使y坐標反轉(zhuǎn)。片元著色器會對每個像素進行計算,調(diào)用次數(shù)很多,這里應(yīng)該盡量去掉不必要的操作。
attribute vec4 position;
attribute vec2 textCoordinate;
varying lowp vec2 varyTextCoord;
void main()
{
//varyTextCoord = textCoordinate;
varyTextCoord = vec2(textCoordinate.x, 1.0 - textCoordinate.y);
gl_Position = position;
}
5.在片元著色器中修改
同樣的方法也可以在頂點著色器中使用。頂點數(shù)據(jù)相對較少,不過也不建議寫不必要的操作。
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));
}