IOS圖片畫(huà)對(duì)角線OpenGLES(六)

前言

上一篇學(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;

Demo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容