GLProgram.m 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. // This is Jeff LaMarche's GLProgram OpenGL shader wrapper class from his OpenGL ES 2.0 book.
  2. // A description of this can be found at his page on the topic:
  3. // http://iphonedevelopment.blogspot.com/2010/11/opengl-es-20-for-ios-chapter-4.html
  4. #import "GLProgram.h"
  5. // START:typedefs
  6. #pragma mark Function Pointer Definitions
  7. typedef void (*GLInfoFunction)(GLuint program,
  8. GLenum pname,
  9. GLint* params);
  10. typedef void (*GLLogFunction) (GLuint program,
  11. GLsizei bufsize,
  12. GLsizei* length,
  13. GLchar* infolog);
  14. // END:typedefs
  15. #pragma mark -
  16. #pragma mark Private Extension Method Declaration
  17. // START:extension
  18. @interface GLProgram()
  19. - (BOOL)compileShader:(GLuint *)shader
  20. type:(GLenum)type
  21. string:(NSString *)shaderString;
  22. - (NSString *)logForOpenGLObject:(GLuint)object
  23. infoCallback:(GLInfoFunction)infoFunc
  24. logFunc:(GLLogFunction)logFunc;
  25. @end
  26. // END:extension
  27. #pragma mark -
  28. @implementation GLProgram
  29. // START:init
  30. @synthesize initialized = _initialized;
  31. - (id)initWithVertexShaderString:(NSString *)vShaderString
  32. fragmentShaderString:(NSString *)fShaderString;
  33. {
  34. if ((self = [super init]))
  35. {
  36. _initialized = NO;
  37. attributes = [[NSMutableArray alloc] init];
  38. uniforms = [[NSMutableArray alloc] init];
  39. program = glCreateProgram();
  40. if (![self compileShader:&vertShader
  41. type:GL_VERTEX_SHADER
  42. string:vShaderString])
  43. NSLog(@"Failed to compile vertex shader");
  44. // Create and compile fragment shader
  45. if (![self compileShader:&fragShader
  46. type:GL_FRAGMENT_SHADER
  47. string:fShaderString])
  48. NSLog(@"Failed to compile fragment shader");
  49. glAttachShader(program, vertShader);
  50. glAttachShader(program, fragShader);
  51. }
  52. return self;
  53. }
  54. - (id)initWithVertexShaderString:(NSString *)vShaderString
  55. fragmentShaderFilename:(NSString *)fShaderFilename;
  56. {
  57. NSString *fragShaderPathname = [[NSBundle mainBundle] pathForResource:fShaderFilename ofType:@"fsh"];
  58. NSString *fragmentShaderString = [NSString stringWithContentsOfFile:fragShaderPathname encoding:NSUTF8StringEncoding error:nil];
  59. if ((self = [self initWithVertexShaderString:vShaderString fragmentShaderString:fragmentShaderString]))
  60. {
  61. }
  62. return self;
  63. }
  64. - (id)initWithVertexShaderFilename:(NSString *)vShaderFilename
  65. fragmentShaderFilename:(NSString *)fShaderFilename;
  66. {
  67. NSString *vertShaderPathname = [[NSBundle mainBundle] pathForResource:vShaderFilename ofType:@"vsh"];
  68. NSString *vertexShaderString = [NSString stringWithContentsOfFile:vertShaderPathname encoding:NSUTF8StringEncoding error:nil];
  69. NSString *fragShaderPathname = [[NSBundle mainBundle] pathForResource:fShaderFilename ofType:@"fsh"];
  70. NSString *fragmentShaderString = [NSString stringWithContentsOfFile:fragShaderPathname encoding:NSUTF8StringEncoding error:nil];
  71. if ((self = [self initWithVertexShaderString:vertexShaderString fragmentShaderString:fragmentShaderString]))
  72. {
  73. }
  74. return self;
  75. }
  76. // END:init
  77. // START:compile
  78. - (BOOL)compileShader:(GLuint *)shader
  79. type:(GLenum)type
  80. string:(NSString *)shaderString
  81. {
  82. // CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
  83. GLint status;
  84. const GLchar *source;
  85. source =
  86. (GLchar *)[shaderString UTF8String];
  87. if (!source)
  88. {
  89. NSLog(@"Failed to load vertex shader");
  90. return NO;
  91. }
  92. *shader = glCreateShader(type);
  93. glShaderSource(*shader, 1, &source, NULL);
  94. glCompileShader(*shader);
  95. glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
  96. if (status != GL_TRUE)
  97. {
  98. GLint logLength;
  99. glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
  100. if (logLength > 0)
  101. {
  102. GLchar *log = (GLchar *)malloc(logLength);
  103. glGetShaderInfoLog(*shader, logLength, &logLength, log);
  104. NSLog(@"Shader compile log:\n%s", log);
  105. free(log);
  106. }
  107. }
  108. // CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);
  109. // NSLog(@"Compiled in %f ms", linkTime * 1000.0);
  110. return status == GL_TRUE;
  111. }
  112. // END:compile
  113. #pragma mark -
  114. // START:addattribute
  115. - (void)addAttribute:(NSString *)attributeName
  116. {
  117. if (![attributes containsObject:attributeName])
  118. {
  119. [attributes addObject:attributeName];
  120. glBindAttribLocation(program,
  121. (GLuint)[attributes indexOfObject:attributeName],
  122. [attributeName UTF8String]);
  123. }
  124. }
  125. // END:addattribute
  126. // START:indexmethods
  127. - (GLuint)attributeIndex:(NSString *)attributeName
  128. {
  129. return (GLuint)[attributes indexOfObject:attributeName];
  130. }
  131. - (GLuint)uniformIndex:(NSString *)uniformName
  132. {
  133. return glGetUniformLocation(program, [uniformName UTF8String]);
  134. }
  135. // END:indexmethods
  136. #pragma mark -
  137. // START:link
  138. - (BOOL)link
  139. {
  140. // CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
  141. GLint status;
  142. glLinkProgram(program);
  143. glGetProgramiv(program, GL_LINK_STATUS, &status);
  144. if (status == GL_FALSE)
  145. return NO;
  146. if (vertShader)
  147. {
  148. glDeleteShader(vertShader);
  149. vertShader = 0;
  150. }
  151. if (fragShader)
  152. {
  153. glDeleteShader(fragShader);
  154. fragShader = 0;
  155. }
  156. self.initialized = YES;
  157. // CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);
  158. // NSLog(@"Linked in %f ms", linkTime * 1000.0);
  159. return YES;
  160. }
  161. // END:link
  162. // START:use
  163. - (void)use
  164. {
  165. glUseProgram(program);
  166. }
  167. // END:use
  168. #pragma mark -
  169. // START:privatelog
  170. - (NSString *)logForOpenGLObject:(GLuint)object
  171. infoCallback:(GLInfoFunction)infoFunc
  172. logFunc:(GLLogFunction)logFunc
  173. {
  174. GLint logLength = 0, charsWritten = 0;
  175. infoFunc(object, GL_INFO_LOG_LENGTH, &logLength);
  176. if (logLength < 1)
  177. return nil;
  178. char *logBytes = malloc(logLength);
  179. logFunc(object, logLength, &charsWritten, logBytes);
  180. NSString *log = [[NSString alloc] initWithBytes:logBytes
  181. length:logLength
  182. encoding:NSUTF8StringEncoding];
  183. free(logBytes);
  184. return log;
  185. }
  186. // END:privatelog
  187. // START:log
  188. - (NSString *)vertexShaderLog
  189. {
  190. return [self logForOpenGLObject:vertShader
  191. infoCallback:(GLInfoFunction)&glGetProgramiv
  192. logFunc:(GLLogFunction)&glGetProgramInfoLog];
  193. }
  194. - (NSString *)fragmentShaderLog
  195. {
  196. return [self logForOpenGLObject:fragShader
  197. infoCallback:(GLInfoFunction)&glGetProgramiv
  198. logFunc:(GLLogFunction)&glGetProgramInfoLog];
  199. }
  200. - (NSString *)programLog
  201. {
  202. return [self logForOpenGLObject:program
  203. infoCallback:(GLInfoFunction)&glGetProgramiv
  204. logFunc:(GLLogFunction)&glGetProgramInfoLog];
  205. }
  206. // END:log
  207. - (void)validate;
  208. {
  209. GLint logLength;
  210. glValidateProgram(program);
  211. glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
  212. if (logLength > 0)
  213. {
  214. GLchar *log = (GLchar *)malloc(logLength);
  215. glGetProgramInfoLog(program, logLength, &logLength, log);
  216. NSLog(@"Program validate log:\n%s", log);
  217. free(log);
  218. }
  219. }
  220. #pragma mark -
  221. // START:dealloc
  222. - (void)dealloc
  223. {
  224. if (vertShader)
  225. glDeleteShader(vertShader);
  226. if (fragShader)
  227. glDeleteShader(fragShader);
  228. if (program)
  229. glDeleteProgram(program);
  230. }
  231. // END:dealloc
  232. @end