OpenGL ES的著色器主要有片元著色器和頂點著色器,其使用方法簡單的介紹如下:
創建,裝載和編譯 shader:
繼續上一篇的基礎上,在工程中新建一個類,命名為OpenGLESUtils(繼承于NSObject),在.h中聲明2個方法: + (GLuint)loadShader:(GLenum)type shaderString:(NSString *)shaderString; + (GLuint)loadShader:(GLenum)type shaderFilePath:(NSString *)filePath;在OpenGLESUtils.m實現上面的兩個方法:+(GLuint)loadShader:(GLenum)type shaderFilePath:(NSString *)filePath { NSError *error; NSString *shaderString = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error]; if (!shaderString) { NSLog(@"Error: loading shader file: %@ %@", filePath, error.localizedDescription); return 0; } else { return [self loadShader:type shaderString:shaderString]; }} + (GLuint)loadShader:(GLenum)type shaderString:(NSString *)shaderString { GLuint shader = glCreateShader(type); if (shader == 0) { NSLog(@"Error: failed to create shader."); return 0; } const char *shaderStringUTF8 = [shaderString UTF8String]; glShaderSource(shader, 1, &shaderStringUTF8, NULL); glCompileShader(shader); GLint compiled = 0; glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled); if (!compiled) { GLint inforLen = 0; glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &inforLen); if (inforLen > 1) { char *infoLog = malloc(sizeof(char)*inforLen); glGetShaderInfoLog(shader, inforLen, NULL, infoLog); free(infoLog); } glDeleteShader(shader); return 0; } return shader;}OpenGLESUtils中的兩個方法用來跟進shader腳本字符串和shader腳本文件創建,具體方法如下: 1、創建/刪除 shader:函數 glCreateShader 用來創建 shader,參數 GLenum type 表示我們要處理的 shader 類型,它可以是 GL_VERTEX_SHADER 或 GL_FRAGMENT_SHADER,分別表示頂點 shader 或 片元 shader。它返回一個句柄指向創建好的 shader 對象; 2、裝載 shader:函數 glShaderSource 用來給指定 shader 提供 shader 源碼。第一個參數是 shader 對象的句柄;第二個參數表示 shader 源碼字符串的個數;第三個參數是 shader 源碼字符串數組;第四個參數一個 int 數組,表示每個源碼字符串應該取用的長度,如果該參數為 NULL,表示假定源碼字符串是 /0 結尾的,讀取該字符串的內容指定 /0 為止作為源碼,如果該參數不是 NULL,則讀取每個源碼字符串中前 length(與每個字符串對應的 length)長度個字符作為源碼; 3、編譯 shader:函數 glCompileShader 用來編譯指定的 shader 對象,這將編譯存儲在 shader 對象中的源碼。我們可以通過函數 glGetShaderiv 來查詢 shader 對象的信息,如本例中查詢編譯情況,此外還可以查詢 GL_DELETE_STATUS,GL_INFO_LOG_STATUS,GL_SHADER_SOURCE_LENGTH 和 GL_SHADER_TYPE。在這里我們查詢編譯情況,如果返回 0,表示編譯出錯了,錯誤信息會寫入 info 日志中,我們可以查詢該 info 日志,從而獲得錯誤信息。編寫著色腳本:
添加頂點著色腳本:在工程中新建一個Empty,命名為VertexShader.glsl,實現內容如下:attribute vec4 vPosition;void main(void) { gl_Position = vPosition;}添加片元著色腳本:同理實現,代碼如下:PRecision mediump float;void main() { gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);}創建 program,裝配 shader,鏈接 program,使用 program: 1、在 OpenGLView.h 的 OpenGLView 類聲明中添加兩個成員: GLuint programHandle; GLuint positionSlot; 2、然后依然在 OpenGLView.m 中的category 中添加成員方法: - (void)setupProgram { NSString *vertexShaderPath = [[NSBundle mainBundle] pathForResource:@"VertexShader" ofType:@"glsl"]; NSString *fragmentShaderPath = [[NSBundle mainBundle] pathForResource:@"FragmentShader" ofType:@"glsl"]; GLuint vertexShader = [OpenGLESUtils loadShader:GL_VERTEX_SHADER shaderFilePath:vertexShaderPath]; GLuint fragmentShader =[OpenGLESUtils loadShader:GL_FRAGMENT_SHADER shaderFilePath:fragmentShaderPath]; programHandle = glCreateProgram(); if (!programHandle) { NSLog(@"Failed to create program."); return; } glAttachShader(programHandle, vertexShader); glAttachShader(programHandle, fragmentShader); glLinkProgram(programHandle); GLint linked; glGetProgramiv(programHandle, GL_LINK_STATUS, &linked); if (!linked) { GLint infoLen = 0;glGetProgramiv(programHandle, GL_INFO_LOG_LENGTH, &infoLen); if (infoLen > 1) { char *infoLog = malloc(sizeof(char) *infoLen); glGetShaderInfoLog(programHandle, infoLen, NULL, infoLog); NSLog(@"Error linking program:/n%s/n", infoLog ); free(infoLog); } glDeleteProgram(programHandle); programHandle = 0; return; } glUseProgram(programHandle); positionSlot = glGetAttribLocation(programHandle, "vPosition");}使用實例: 在 - (void)layoutSubviews中調用 render 方法之前,插入對 setupProgram 的調用:- (void)layoutSubviews { [self setupLayer]; [self setupContext]; [self destoryRenderAndFrameBuffer]; [self setupRenderBuffer]; [self setupFrameBuffer]; [self setupProgram]; [self render];}// 改寫render方法:- (void)render { // 設置清屏顏色 glClearColor(0.0, 0.0, 1.0, 1.0); // 用來指定要用清屏顏色來清除由mask指定的buffer,此處是color buffer glClear(GL_COLOR_BUFFER_BIT); // 渲染區域 glViewport(0, 0, self.frame.size.width, self.frame.size.height); GLfloat vertices[] = { 0.0f, 0.5f, 0.0f, -0.5f, -0.5f, 0.0f, 0.5f, -0.5f, 0.0f }; // 通過 glVertexAttribPointer 將三角形頂點數據裝載到 OpenGL ES 中并與 vPositon 關聯起來 glVertexAttribPointer(positionSlot, 3, GL_FLOAT, GL_FALSE, 0, vertices); glEnableVertexAttribArray(positionSlot); // glDrawArrays 將三角形圖元渲染出來 glDrawArrays(GL_TRIANGLES, 0, 3); [eaglContext presentRenderbuffer:GL_RENDERBUFFER ];}參考文章:http://blog.csdn.net/kesalin/article/details/8223649
新聞熱點
疑難解答