123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273 |
- // This is Jeff LaMarche's GLProgram OpenGL shader wrapper class from his OpenGL ES 2.0 book.
- // A description of this can be found at his page on the topic:
- // http://iphonedevelopment.blogspot.com/2010/11/opengl-es-20-for-ios-chapter-4.html
- #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;
- - (NSString *)logForOpenGLObject:(GLuint)object
- infoCallback:(GLInfoFunction)infoFunc
- logFunc:(GLLogFunction)logFunc;
- @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);
- NSLog(@"Shader compile log:\n%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 -
- // START:privatelog
- - (NSString *)logForOpenGLObject:(GLuint)object
- infoCallback:(GLInfoFunction)infoFunc
- logFunc:(GLLogFunction)logFunc
- {
- GLint logLength = 0, charsWritten = 0;
-
- infoFunc(object, GL_INFO_LOG_LENGTH, &logLength);
- if (logLength < 1)
- return nil;
-
- char *logBytes = malloc(logLength);
- logFunc(object, logLength, &charsWritten, logBytes);
- NSString *log = [[NSString alloc] initWithBytes:logBytes
- length:logLength
- encoding:NSUTF8StringEncoding];
- free(logBytes);
- return log;
- }
- // END:privatelog
- // START:log
- - (NSString *)vertexShaderLog
- {
- return [self logForOpenGLObject:vertShader
- infoCallback:(GLInfoFunction)&glGetProgramiv
- logFunc:(GLLogFunction)&glGetProgramInfoLog];
-
- }
- - (NSString *)fragmentShaderLog
- {
- return [self logForOpenGLObject:fragShader
- infoCallback:(GLInfoFunction)&glGetProgramiv
- logFunc:(GLLogFunction)&glGetProgramInfoLog];
- }
- - (NSString *)programLog
- {
- return [self logForOpenGLObject:program
- infoCallback:(GLInfoFunction)&glGetProgramiv
- logFunc:(GLLogFunction)&glGetProgramInfoLog];
- }
- // END:log
- - (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);
- NSLog(@"Program validate log:\n%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
|