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 = ;
}
if (fragShader)
{
glDeleteShader(fragShader);
fragShader = ;
} 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, , &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 > )
{
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 Definitions
typedef 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, , &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 > )
{
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 = ;
}
if (fragShader)
{
glDeleteShader(fragShader);
fragShader = ;
} 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 > )
{
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