前言
上一篇學(xué)習(xí)了如何渲染圖片,并最終程序到屏幕上。前面也知道同時(shí)渲染兩張圖片,其實(shí)是由片元著色器實(shí)現(xiàn)的兩張圖片疊加的功能,最終也只是調(diào)用了一次glDrawArrays()函數(shù)。因?yàn)椴还芏嗌購(gòu)垐D片,圖片的圖元類(lèi)型都是矩形。如果想在圖片上畫(huà)幾條直線,那該如何做呢?當(dāng)然也有人說(shuō),可以弄一個(gè)這樣直線的圖片去和另外一張圖片疊加(_ 也是一個(gè)思路,那還有其它方法嗎?這是本文的學(xué)習(xí)目標(biāo))
opengl es系列文章
opengl es之-基礎(chǔ)概念(一)
opengl es之-GLSL語(yǔ)言(二)
opengl es之-GLSL語(yǔ)言(三)
opengl es之-常用函數(shù)介紹(四)
opengl es之-渲染兩張圖片(五)
opengl es之-在圖片上添加對(duì)角線(六)
opengl es之-離屏渲染簡(jiǎn)介(七)
opengl es之-CVOpenGLESTextureCache介紹(八)
opengl es之-播放YUV文件(九)
需求
在一張圖片上畫(huà)兩條對(duì)角線,這種需求也經(jīng)常存在,比如相機(jī)的實(shí)時(shí)畫(huà)面上的九宮格等等。
思路
前面知道,調(diào)用一次glDrawArrays()就是一種類(lèi)型幾何圖元的渲染,如果單獨(dú)實(shí)現(xiàn)渲染一張圖片和渲染一個(gè)對(duì)角線然后呈現(xiàn)到屏幕上,我相信都會(huì)了,那一起呢?其實(shí)可以在渲染結(jié)果呈現(xiàn)到屏幕之前兩次調(diào)用glDrawArrays()函數(shù),即執(zhí)行兩次次渲染管線流程,最后再調(diào)用presentRenderbuffer將結(jié)果呈現(xiàn)到屏幕上,那這個(gè)問(wèn)題就解決了
準(zhǔn)備
依然分為準(zhǔn)備上下文環(huán)境,開(kāi)辟幀緩沖區(qū)和渲染緩沖區(qū),傳遞頂點(diǎn)坐標(biāo)和紋理圖片這幾個(gè)過(guò)程。具體代碼可以參考上一篇文章,或者Demo這里不再重復(fù)。有區(qū)別的地方這里做下說(shuō)明
1、緩沖區(qū)
雖然在調(diào)用presentRenderbuffer前執(zhí)行了兩次glDrawArrays(),但是幀緩沖區(qū)只需要一個(gè)即可
2、著色器代碼
渲染圖片和渲染直線分別使用各自獨(dú)立的著色器代碼,如下:
頂點(diǎn)著色器
attribute vec4 position;
attribute vec2 texcoord;
varying highp vec2 v_texcoord;
void main()
{
gl_Position = position;
v_texcoord = texcoord.xy;
}
因?yàn)殇秩镜揭粋€(gè)區(qū)域,所以直線和圖片的頂點(diǎn)著色器是一樣的,對(duì)于直線來(lái)說(shuō),里面有多余的變量,可以不用
圖片片元著色器
uniform sampler2D inputImageTexture1;
varying highp vec2 v_texcoord;
void main() {
gl_FragColor = texture2D(inputImageTexture1, v_texcoord);
}
直線片元著色器
void main(){
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
開(kāi)始渲染的代碼
glClearColor(0, 1, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, _renderWidth, _renderHeight);
int w1,h1;
void *image1 = [CGImageUtils rgbaImageDataForPath:path width:&w1 height:&h1];
NSLog(@"圖片的寬和高 w1 %d h1 %d",w1,h1);
[self.rgbTextureProgram use];
GLuint position = [self.rgbTextureProgram attribLocationForName:@"position"];
GLuint texcoord = [self.rgbTextureProgram attribLocationForName:@"texcoord"];
GLuint s_texture1 = [self.rgbTextureProgram uniformLocationForName:@"inputImageTexture1"];
glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, verData1);
glEnableVertexAttribArray(position);
glVertexAttribPointer(texcoord, 2, GL_FLOAT, GL_FALSE, 0, uvData);
glEnableVertexAttribArray(texcoord);
GLint active,textureSize;
glGetIntegerv(GL_ACTIVE_TEXTURE, &active);
NSLog(@"該設(shè)備支持的最大紋理單元數(shù)目 %d",active);
// 超過(guò)此大小則必須先壓縮再傳給opengl es,否則opengl es無(wú)法渲染
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &textureSize);
NSLog(@"該設(shè)備支持的紋理最大的長(zhǎng)或?qū)?%d",textureSize);
glActiveTexture(GL_TEXTURE1);
glGenTextures(1,&texturexId2);
glBindTexture(GL_TEXTURE_2D, texturexId2);
// 此方法必須有,第二個(gè)參數(shù)要與前面激活的紋理單元數(shù)對(duì)應(yīng),前面是GL_TEXTURE1,這里就是1
glUniform1i(s_texture1, 1);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); // S方向上的貼圖模式
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); // T方向上的貼圖模式
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)w1, (int)h1, 0, GL_RGBA, GL_UNSIGNED_BYTE, image1);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// 釋放圖片像素?cái)?shù)據(jù)
if (image1) {
free(image1);
}
// 確定要繪制的幾何圖形,該指令執(zhí)行后才opengl es指令才開(kāi)始真正的執(zhí)行;處于渲染管線的第一階段,每次glDrawArrays()的調(diào)用
// 代表前面所有的指令是一次完整的渲染
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
[self.lineprogram use];
GLuint linePosition = [self.lineprogram attribLocationForName:@"position"];
glVertexAttribPointer(linePosition, 2, GL_FLOAT, GL_FALSE, 0, verData2);
glEnableVertexAttribArray(linePosition);
glLineWidth(5.0);
glDrawArrays(GL_LINES, 0, 4);
// 即光柵化階段,它與opengl es的渲染是獨(dú)立的,不相干的。當(dāng)它會(huì)將前面所有的渲染結(jié)果呈現(xiàn)到屏幕上;
// 前面調(diào)用了兩次glDrawArrays();所以它會(huì)將前面兩次渲染的結(jié)果呈現(xiàn)到屏幕上
[_context.context presentRenderbuffer:GL_RENDERBUFFER];
rgbTextureProgram代表處理圖片的著色器;lineprogram代表處理直線的著色器
每次渲染開(kāi)始前都要調(diào)用一次glUseProgram(handle)函數(shù)以激活當(dāng)前渲染所使用的著色器程序,否則將使用上一次調(diào)用glUseProgram()的著色器程序
其它就和單獨(dú)渲染圖片沒(méi)什么區(qū)別了。
項(xiàng)目地址:
具體參考GLView.h下的如下函數(shù):
// 多次渲染,即多次調(diào)用glDrawArrays();第一次渲染一張圖片,同時(shí)再渲染兩條直線
- (void)renderTextureAndlinesWithPath:(NSString*)path;