GLPRogram是GPUImage中代表openGL ES 中的program,具有glprogram功能。
屬性
@property(readwrite, nonatomic) BOOL initialized
作用:該屬性用于指示program的初始化工作是否成功,成功返回YES,反之返回NO
@property(readwrite, copy, nonatomic) NSString *vertexShaderLog
作用:該屬性用于設置或獲取頂點著色器的日志。
@property(readwrite, copy, nonatomic) NSString *fragmentShaderLog
作用:該屬性用于設置或獲取片段著色器的日志。
@property(readwrite, copy, nonatomic) NSString *programLog
作用:該屬性用于設置或獲取program的日志。
方法
- (id)initWithVertexShaderString:(NSString *)vShaderString fragmentShaderString:(NSString *)fShaderString
說明:使用一個頂點著色字符串和一個片段著色字符串創建一個GLProgram對象
參數:頂點著色字符串,片段著色字符串
返回:GLProgram對象
相似方法:- (id)initWithVertexShaderString:(NSString *)vShaderString fragmentShaderFilename:(NSString *)fShaderFilename;
- (id)initWithVertexShaderFilename:(NSString *)vShaderFilename fragmentShaderFilename:(NSString *)fShaderFilename(從文件中讀取內容)
實現
- (id)initWithVertexShaderString:(NSString *)vShaderString fragmentShaderString:(NSString *)fShaderString;{ if ((self = [super init])) { _initialized = NO; attributes = [[NSMutableArray alloc] init]; uniforms = [[NSMutableArray alloc] init]; program = glCreateProgram(); if (![self compileShader:&vertShader type:GL_VERTEX_SHADER string:vShaderString]) { NSLog(@"Failed to compile vertex shader"); } // Create and compile fragment shader if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER string:fShaderString]) { NSLog(@"Failed to compile fragment shader"); } glAttachShader(program, vertShader); glAttachShader(program, fragShader); } return self;}
詳解:1.使用glCreateProgram()函數創建一個program
2.編譯著色器
3.附加著色器。glAttachShader(program, fragShader)
- (void)addAttribute:(NSString *)attributeName
說明:該方法用于向一個program對象中添加屬性
參數:需要添加的屬性名稱
返回:void
實現:
- (void)addAttribute:(NSString *)attributeName{ if (![attributes containsObject:attributeName]) { [attributes addObject:attributeName]; glBindAttribLocation(program, (GLuint)[attributes indexOfObject:attributeName], [attributeName UTF8String]); }}
詳解:void glBindAttribLocation( GLuint program, GLuint index,const GLchar *name)函數用來將屬性綁定到具體位置。program是使用的program對象,index是位置索引,*name是需要綁定的屬性名
- (GLuint)attributeIndex:(NSString *)attributeName
說明:返回具體屬性名的索引
參數:指定的屬性名
返回:指定屬性名的索引
- (GLuint)uniformIndex:(NSString *)uniformName
說明:返回Uniform的索引
參數:指定的Uniform名
返回:指定Uniform的索引
- (BOOL)link
說明:判斷program是否link成功
返回:YES說明link成功,反之失敗
實現:
- (BOOL)link{ GLint status; glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &status); if (status == GL_FALSE) return NO; if (vertShader) { glDeleteShader(vertShader); vertShader = 0; } if (fragShader) { glDeleteShader(fragShader); fragShader = 0; } self.initialized = YES; return YES;}
詳解:glLinkProgram(program)函數link一個創建好的program對象,glGetProgramiv(program, GL_LINK_STATUS, &status)用來查詢link結果。
- (void)use
說明:使用program
- (void)validate
說明:program對象是否有效
- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type string:(NSString *)shaderString
說明:編譯著色器
參數:shader是著色器 type為著色器類型(頂點和片段) shaderString為著色器內容字符串。
實現
- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type string:(NSString *)shaderString{// CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); GLint status; const GLchar *source; source = (GLchar *)[shaderString UTF8String]; if (!source) { NSLog(@"Failed to load vertex shader"); return NO; } *shader = glCreateShader(type); glShaderSource(*shader, 1, &source, NULL); glCompileShader(*shader); glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); if (status != GL_TRUE) { GLint logLength; glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); if (logLength > 0) { GLchar *log = (GLchar *)malloc(logLength); glGetShaderInfoLog(*shader, logLength, &logLength, log); if (shader == &vertShader) { self.vertexShaderLog = [NSString stringWithFormat:@"%s", log]; } else { self.fragmentShaderLog = [NSString stringWithFormat:@"%s", log]; } free(log); } } // CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);// NSLog(@"Compiled in %f ms", linkTime * 1000.0); return status == GL_TRUE;}
#import <Foundation/Foundation.h>#if TARGET_ipHONE_SIMULATOR || TARGET_OS_IPHONE#import <OpenGLES/ES2/gl.h>#import <OpenGLES/ES2/glext.h>#else#import <OpenGL/OpenGL.h>#import <OpenGL/gl.h>#endif@interface GLProgram : NSObject { NSMutableArray *attributes; NSMutableArray *uniforms; GLuint program, vertShader, fragShader; }@property(readwrite, nonatomic) BOOL initialized;@property(readwrite, copy, nonatomic) NSString *vertexShaderLog;@property(readwrite, copy, nonatomic) NSString *fragmentShaderLog;@property(readwrite, copy, nonatomic) NSString *programLog;- (id)initWithVertexShaderString:(NSString *)vShaderString fragmentShaderString:(NSString *)fShaderString;- (id)initWithVertexShaderString:(NSString *)vShaderString fragmentShaderFilename:(NSString *)fShaderFilename;- (id)initWithVertexShaderFilename:(NSString *)vShaderFilename fragmentShaderFilename:(NSString *)fShaderFilename;- (void)addAttribute:(NSString *)attributeName;- (GLuint)attributeIndex:(NSString *)attributeName;- (GLuint)uniformIndex:(NSString *)uniformName;- (BOOL)link;- (void)use;- (void)validate;@end
#import "GLProgram.h"// START:typedefs#pragma mark Function Pointer Definitionstypedef void (*GLInfoFunction)(GLuint program, GLenum pname, GLint* params);typedef void (*GLLogFunction) (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);// END:typedefs#pragma mark -#pragma mark Private Extension Method Declaration// START:extension@interface GLProgram()- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type string:(NSString *)shaderString;@end// END:extension#pragma mark -@implementation GLProgram// START:init@synthesize initialized = _initialized;- (id)initWithVertexShaderString:(NSString *)vShaderString fragmentShaderString:(NSString *)fShaderString;{ if ((self = [super init])) { _initialized = NO; attributes = [[NSMutableArray alloc] init]; uniforms = [[NSMutableArray alloc] init]; program = glCreateProgram(); if (![self compileShader:&vertShader type:GL_VERTEX_SHADER string:vShaderString]) { NSLog(@"Failed to compile vertex shader"); } // Create and compile fragment shader if (![self compileShader:&fragShader type:GL_FRAGMENT_SHADER string:fShaderString]) { NSLog(@"Failed to compile fragment shader"); } glAttachShader(program, vertShader); glAttachShader(program, fragShader); } return self;}- (id)initWithVertexShaderString:(NSString *)vShaderString fragmentShaderFilename:(NSString *)fShaderFilename;{ NSString *fragShaderPathname = [[NSBundle mainBundle] pathForResource:fShaderFilename ofType:@"fsh"]; NSString *fragmentShaderString = [NSString stringWithContentsOfFile:fragShaderPathname encoding:NSUTF8StringEncoding error:nil]; if ((self = [self initWithVertexShaderString:vShaderString fragmentShaderString:fragmentShaderString])) { } return self;}- (id)initWithVertexShaderFilename:(NSString *)vShaderFilename fragmentShaderFilename:(NSString *)fShaderFilename;{ NSString *vertShaderPathname = [[NSBundle mainBundle] pathForResource:vShaderFilename ofType:@"vsh"]; NSString *vertexShaderString = [NSString stringWithContentsOfFile:vertShaderPathname encoding:NSUTF8StringEncoding error:nil]; NSString *fragShaderPathname = [[NSBundle mainBundle] pathForResource:fShaderFilename ofType:@"fsh"]; NSString *fragmentShaderString = [NSString stringWithContentsOfFile:fragShaderPathname encoding:NSUTF8StringEncoding error:nil]; if ((self = [self initWithVertexShaderString:vertexShaderString fragmentShaderString:fragmentShaderString])) { } return self;}// END:init// START:compile- (BOOL)compileShader:(GLuint *)shader type:(GLenum)type string:(NSString *)shaderString{// CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); GLint status; const GLchar *source; source = (GLchar *)[shaderString UTF8String]; if (!source) { NSLog(@"Failed to load vertex shader"); return NO; } *shader = glCreateShader(type); glShaderSource(*shader, 1, &source, NULL); glCompileShader(*shader); glGetShaderiv(*shader, GL_COMPILE_STATUS, &status); if (status != GL_TRUE) { GLint logLength; glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength); if (logLength > 0) { GLchar *log = (GLchar *)malloc(logLength); glGetShaderInfoLog(*shader, logLength, &logLength, log); if (shader == &vertShader) { self.vertexShaderLog = [NSString stringWithFormat:@"%s", log]; } else { self.fragmentShaderLog = [NSString stringWithFormat:@"%s", log]; } free(log); } } // CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);// NSLog(@"Compiled in %f ms", linkTime * 1000.0); return status == GL_TRUE;}// END:compile#pragma mark -// START:addattribute- (void)addAttribute:(NSString *)attributeName{ if (![attributes containsObject:attributeName]) { [attributes addObject:attributeName]; glBindAttribLocation(program, (GLuint)[attributes indexOfObject:attributeName], [attributeName UTF8String]); }}// END:addattribute// START:indexmethods- (GLuint)attributeIndex:(NSString *)attributeName{ return (GLuint)[attributes indexOfObject:attributeName];}- (GLuint)uniformIndex:(NSString *)uniformName{ return glGetUniformLocation(program, [uniformName UTF8String]);}// END:indexmethods#pragma mark -// START:link- (BOOL)link{// CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent(); GLint status; glLinkProgram(program); glGetProgramiv(program, GL_LINK_STATUS, &status); if (status == GL_FALSE) return NO; if (vertShader) { glDeleteShader(vertShader); vertShader = 0; } if (fragShader) { glDeleteShader(fragShader); fragShader = 0; } self.initialized = YES;// CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);// NSLog(@"Linked in %f ms", linkTime * 1000.0); return YES;}// END:link// START:use- (void)use{ glUseProgram(program);}// END:use#pragma mark -- (void)validate;{ GLint logLength; glValidateProgram(program); glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength); if (logLength > 0) { GLchar *log = (GLchar *)malloc(logLength); glGetProgramInfoLog(program, logLength, &logLength, log); self.programLog = [NSString stringWithFormat:@"%s", log]; free(log); } }#pragma mark -// START:dealloc- (void)dealloc{ if (vertShader) glDeleteShader(vertShader); if (fragShader) glDeleteShader(fragShader); if (program) glDeleteProgram(program); }// END:dealloc@end
新聞熱點
疑難解答