GLProgram.m 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  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, GLenum pname, GLint* params);
  8. typedef void (*GLLogFunction) (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
  9. // END:typedefs
  10. #pragma mark -
  11. #pragma mark Private Extension Method Declaration
  12. // START:extension
  13. @interface GLProgram()
  14. - (BOOL)compileShader:(GLuint *)shader
  15. type:(GLenum)type
  16. string:(NSString *)shaderString;
  17. @end
  18. // END:extension
  19. #pragma mark -
  20. @implementation GLProgram
  21. // START:init
  22. @synthesize initialized = _initialized;
  23. - (id)initWithVertexShaderString:(NSString *)vShaderString
  24. fragmentShaderString:(NSString *)fShaderString;
  25. {
  26. if ((self = [super init]))
  27. {
  28. _initialized = NO;
  29. attributes = [[NSMutableArray alloc] init];
  30. uniforms = [[NSMutableArray alloc] init];
  31. program = glCreateProgram();
  32. if (![self compileShader:&vertShader
  33. type:GL_VERTEX_SHADER
  34. string:vShaderString])
  35. {
  36. NSLog(@"Failed to compile vertex shader");
  37. }
  38. // Create and compile fragment shader
  39. if (![self compileShader:&fragShader
  40. type:GL_FRAGMENT_SHADER
  41. string:fShaderString])
  42. {
  43. NSLog(@"Failed to compile fragment shader");
  44. }
  45. glAttachShader(program, vertShader);
  46. glAttachShader(program, fragShader);
  47. }
  48. return self;
  49. }
  50. - (id)initWithVertexShaderString:(NSString *)vShaderString
  51. fragmentShaderFilename:(NSString *)fShaderFilename;
  52. {
  53. NSString *fragShaderPathname = [[NSBundle mainBundle] pathForResource:fShaderFilename ofType:@"fsh"];
  54. NSString *fragmentShaderString = [NSString stringWithContentsOfFile:fragShaderPathname encoding:NSUTF8StringEncoding error:nil];
  55. if ((self = [self initWithVertexShaderString:vShaderString fragmentShaderString:fragmentShaderString]))
  56. {
  57. }
  58. return self;
  59. }
  60. - (id)initWithVertexShaderFilename:(NSString *)vShaderFilename
  61. fragmentShaderFilename:(NSString *)fShaderFilename;
  62. {
  63. NSString *vertShaderPathname = [[NSBundle mainBundle] pathForResource:vShaderFilename ofType:@"vsh"];
  64. NSString *vertexShaderString = [NSString stringWithContentsOfFile:vertShaderPathname encoding:NSUTF8StringEncoding error:nil];
  65. NSString *fragShaderPathname = [[NSBundle mainBundle] pathForResource:fShaderFilename ofType:@"fsh"];
  66. NSString *fragmentShaderString = [NSString stringWithContentsOfFile:fragShaderPathname encoding:NSUTF8StringEncoding error:nil];
  67. if ((self = [self initWithVertexShaderString:vertexShaderString fragmentShaderString:fragmentShaderString]))
  68. {
  69. }
  70. return self;
  71. }
  72. // END:init
  73. // START:compile
  74. - (BOOL)compileShader:(GLuint *)shader
  75. type:(GLenum)type
  76. string:(NSString *)shaderString
  77. {
  78. // CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
  79. GLint status;
  80. const GLchar *source;
  81. source =
  82. (GLchar *)[shaderString UTF8String];
  83. if (!source)
  84. {
  85. NSLog(@"Failed to load vertex shader");
  86. return NO;
  87. }
  88. *shader = glCreateShader(type);
  89. glShaderSource(*shader, 1, &source, NULL);
  90. glCompileShader(*shader);
  91. glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
  92. if (status != GL_TRUE)
  93. {
  94. GLint logLength;
  95. glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
  96. if (logLength > 0)
  97. {
  98. GLchar *log = (GLchar *)malloc(logLength);
  99. glGetShaderInfoLog(*shader, logLength, &logLength, log);
  100. if (shader == &vertShader)
  101. {
  102. self.vertexShaderLog = [NSString stringWithFormat:@"%s", log];
  103. }
  104. else
  105. {
  106. self.fragmentShaderLog = [NSString stringWithFormat:@"%s", log];
  107. }
  108. free(log);
  109. }
  110. }
  111. // CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);
  112. // NSLog(@"Compiled in %f ms", linkTime * 1000.0);
  113. return status == GL_TRUE;
  114. }
  115. // END:compile
  116. #pragma mark -
  117. // START:addattribute
  118. - (void)addAttribute:(NSString *)attributeName
  119. {
  120. if (![attributes containsObject:attributeName])
  121. {
  122. [attributes addObject:attributeName];
  123. glBindAttribLocation(program,
  124. (GLuint)[attributes indexOfObject:attributeName],
  125. [attributeName UTF8String]);
  126. }
  127. }
  128. // END:addattribute
  129. // START:indexmethods
  130. - (GLuint)attributeIndex:(NSString *)attributeName
  131. {
  132. return (GLuint)[attributes indexOfObject:attributeName];
  133. }
  134. - (GLuint)uniformIndex:(NSString *)uniformName
  135. {
  136. return glGetUniformLocation(program, [uniformName UTF8String]);
  137. }
  138. // END:indexmethods
  139. #pragma mark -
  140. // START:link
  141. - (BOOL)link
  142. {
  143. // CFAbsoluteTime startTime = CFAbsoluteTimeGetCurrent();
  144. GLint status;
  145. glLinkProgram(program);
  146. glGetProgramiv(program, GL_LINK_STATUS, &status);
  147. if (status == GL_FALSE)
  148. return NO;
  149. if (vertShader)
  150. {
  151. glDeleteShader(vertShader);
  152. vertShader = 0;
  153. }
  154. if (fragShader)
  155. {
  156. glDeleteShader(fragShader);
  157. fragShader = 0;
  158. }
  159. self.initialized = YES;
  160. // CFAbsoluteTime linkTime = (CFAbsoluteTimeGetCurrent() - startTime);
  161. // NSLog(@"Linked in %f ms", linkTime * 1000.0);
  162. return YES;
  163. }
  164. // END:link
  165. // START:use
  166. - (void)use
  167. {
  168. glUseProgram(program);
  169. }
  170. // END:use
  171. #pragma mark -
  172. - (void)validate;
  173. {
  174. GLint logLength;
  175. glValidateProgram(program);
  176. glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
  177. if (logLength > 0)
  178. {
  179. GLchar *log = (GLchar *)malloc(logLength);
  180. glGetProgramInfoLog(program, logLength, &logLength, log);
  181. self.programLog = [NSString stringWithFormat:@"%s", log];
  182. free(log);
  183. }
  184. }
  185. #pragma mark -
  186. // START:dealloc
  187. - (void)dealloc
  188. {
  189. if (vertShader)
  190. glDeleteShader(vertShader);
  191. if (fragShader)
  192. glDeleteShader(fragShader);
  193. if (program)
  194. glDeleteProgram(program);
  195. }
  196. // END:dealloc
  197. @end