OpenGL + OpenGL ES +Metal 系列文章匯總
本文案例代碼有OC及Swift版本脑融,詳情見文末鏈接喻频,講解以O(shè)C版本為主
本案例是在OpenGL ES 案例05:GLSL使用索引繪圖案例的基礎(chǔ)上新增紋理與顏色的混合填充
功能
整體效果圖如下:
這個案例的思路很簡單肘迎,主要就是OpenGL ES 案例04:GLSL加載圖片與OpenGL ES 案例05:GLSL使用索引繪圖案例中功能結(jié)合的一個綜合案例,下面主要針對新增的功能作一個說明
如圖所示窿侈,在案例05的基礎(chǔ)上,作了以下修改
注:圖中標(biāo)準(zhǔn)的(D诵恪6逖丁Q撑)
即表示需要修改或者新增代碼的位置
主要需要修改和新增兩個部分
- 自定義著色器
- renderLayer函數(shù)
自定義著色器
主要是在頂點著色器和片元著色器中新增紋理相關(guān)的變量和源碼超凳,如下圖所示
頂點著色器
- 新增
attribute
修飾的紋理坐標(biāo) - 新增
varying
修飾的橋接紋理坐標(biāo) - main函數(shù)中轮傍,將紋理坐標(biāo)賦值給橋接紋理坐標(biāo)
片元著色器
- 新增與頂點中一致的橋接紋理坐標(biāo)
- 新增
uniform
修飾的紋理采樣器 - main函數(shù)中杭跪,計算每個像素的紋素并與頂點顏色混合驰吓,將最終的顏色值賦值給
gl_FragColor
片元著色器中檬贰,顏色混合方式有兩種
- 直接使用GLSL的內(nèi)建函數(shù)
mix(x, y, alpha)
,返回一個vec4
類型的顏色值庄蹋,內(nèi)部的計算為x(1-alpha) +y*alpha
vec4 weakMask = texture2D(colorMap, varyTextCoord);
vec4 mask = varyColor;
// mix(x,y,a) return x(1-a) +y*a
gl_FragColor = mix(mask, weakMask, 0.3);
- 直接套用顏色混合計算公式
關(guān)于顏色的混合公式限书,在六章咧、OpenGL 渲染技巧:深度測試、多邊形偏移扰柠、 混合里,略有提及
vec4 weakMask = texture2D(colorMap, varyTextCoord);
vec4 mask = varyColor;
float alpha = 0.3;
vec4 tempColor = mask * (1.0 - alpha) + weakMask * alpha;
gl_FragColor = tempColor;
renderLayer函數(shù)
render函數(shù)的主要功能是渲染蝙泼,由于新增了紋理顏色混合汤踏,主要修改的是設(shè)置頂點數(shù)據(jù)部分舔腾,需要增加紋理相關(guān)數(shù)據(jù)稳诚、加載等
修改頂點數(shù)組
增加頂點的紋理坐標(biāo)
//前3個元素,是頂點數(shù)據(jù)才避;中間3個元素普办,是頂點顏色值徘钥,最后2個是紋理坐標(biāo)
GLfloat attrArr[] =
{
-0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f,//左上
0.5f, 0.5f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f,//右上
-0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,//左下
0.5f, -0.5f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,//右下
0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.5f, 0.5f,//頂點
};
新增紋理相關(guān)操作
- 處理紋理數(shù)據(jù)
將紋理坐標(biāo)傳入到頂點著色器 - 新增setupTexture函數(shù)呈础,用于加載紋理
- 設(shè)置紋理采樣器
用于采集紋理對應(yīng)像素點的顏色而钞,并傳入片元著色器中,與頂點顏色進(jìn)行混合
renderlayer函數(shù)中
新增紋理相關(guān)代碼如下
// ---------處理紋理數(shù)據(jù)
GLuint textCoord = glGetAttribLocation(self.myPrograme, "textCoordinate");
glEnableVertexAttribArray(textCoord);
glVertexAttribPointer(textCoord, 2, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*8, (float*)NULL+6);
// ------加載紋理
[self setupTexture:@"mouse"];
// ------設(shè)置紋理采樣器
glUniform1i(glGetUniformLocation(self.myPrograme, "colorMap"), 0);
setupTexture函數(shù)
主要是將png/jpg圖片解壓成位圖撬陵,然后進(jìn)行綁定巨税、加載
- (GLuint)setupTexture: (NSString *)fileName{
//將UIImage轉(zhuǎn)換為CGImageRef
CGImageRef image = [UIImage imageNamed:fileName].CGImage;
if (!image) {
NSLog(@"failed to load image %@", fileName);
exit(1);
}
//獲取圖片的寬高
size_t width = CGImageGetWidth(image);
size_t height = CGImageGetHeight(image);
//獲取圖片的字節(jié)數(shù)
GLubyte *imageData = (GLubyte *)calloc(width*height*4, sizeof(GLubyte));
//創(chuàng)建context & 使用默認(rèn)方式繪制圖片草添,即紋理的加載就是重新繪制圖片
CGContextRef context = CGBitmapContextCreate(imageData, width, height, 8, width*4, CGImageGetColorSpace(image), kCGImageAlphaPremultipliedLast);
CGRect rect = CGRectMake(0, 0, width, height);
CGContextDrawImage(context, rect, image);
CGContextRelease(context);
//綁定紋理到默認(rèn)的標(biāo)識符0扼仲,0默認(rèn)是激活狀態(tài)
glBindTexture(GL_TEXTURE_2D, 0);
//設(shè)置紋理參數(shù)(過濾方式抄淑、環(huán)繞模式)
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;
//加載紋理
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fw, fh, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData);
return 0;
}
完整的代碼見github - 11_02_GLSL三角形變換+紋理與顏色混合_OC肆资、11_02_GLSL三角形變換+紋理與顏色混合_Swift