GLESUtils.m 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. //
  2. // GLESUtils.m
  3. // Tutorial02
  4. //
  5. // Created by kesalin@gmail.com on 12-11-25.
  6. // Copyright (c) 2012年 http://blog.csdn.net/kesalin/. All rights reserved.
  7. //
  8. #import "GLESUtils.h"
  9. #define LogInfo printf
  10. #define LogError printf
  11. @implementation GLESUtils
  12. +(GLuint)loadShader:(GLenum)type withFilepath:(NSString *)shaderFilepath
  13. {
  14. NSError* error;
  15. NSString* shaderString = [NSString stringWithContentsOfFile:shaderFilepath
  16. encoding:NSUTF8StringEncoding
  17. error:&error];
  18. if (!shaderString) {
  19. NSLog(@"Error: loading shader file: %@ %@", shaderFilepath, error.localizedDescription);
  20. return 0;
  21. }
  22. return [self loadShader:type withString:shaderString];
  23. }
  24. +(GLuint)loadShader:(GLenum)type withString:(NSString *)shaderString
  25. {
  26. // Create the shader object
  27. GLuint shader = glCreateShader(type);
  28. if (shader == 0) {
  29. NSLog(@"Error: failed to create shader.");
  30. return 0;
  31. }
  32. // Load the shader source
  33. const char * shaderStringUTF8 = [shaderString UTF8String];
  34. glShaderSource(shader, 1, &shaderStringUTF8, NULL);
  35. // Compile the shader
  36. glCompileShader(shader);
  37. // Check the compile status
  38. GLint compiled = 0;
  39. glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
  40. if (!compiled) {
  41. GLint infoLen = 0;
  42. glGetShaderiv ( shader, GL_INFO_LOG_LENGTH, &infoLen );
  43. if (infoLen > 1) {
  44. char * infoLog = malloc(sizeof(char) * infoLen);
  45. glGetShaderInfoLog (shader, infoLen, NULL, infoLog);
  46. NSLog(@"Error compiling shader:\n%s\n", infoLog );
  47. free(infoLog);
  48. }
  49. glDeleteShader(shader);
  50. return 0;
  51. }
  52. return shader;
  53. }
  54. +(GLuint)loadProgram:(NSString *)vertexShaderFilepath withFragmentShaderFilepath:(NSString *)fragmentShaderFilepath
  55. {
  56. // Load the vertex/fragment shaders
  57. GLuint vertexShader = [self loadShader:GL_VERTEX_SHADER
  58. withFilepath:vertexShaderFilepath];
  59. if (vertexShader == 0)
  60. return 0;
  61. GLuint fragmentShader = [self loadShader:GL_FRAGMENT_SHADER
  62. withFilepath:fragmentShaderFilepath];
  63. if (fragmentShader == 0) {
  64. glDeleteShader(vertexShader);
  65. return 0;
  66. }
  67. // Create the program object
  68. GLuint programHandle = glCreateProgram();
  69. if (programHandle == 0)
  70. return 0;
  71. glAttachShader(programHandle, vertexShader);
  72. glAttachShader(programHandle, fragmentShader);
  73. // Link the program
  74. glLinkProgram(programHandle);
  75. // Check the link status
  76. GLint linked;
  77. glGetProgramiv(programHandle, GL_LINK_STATUS, &linked);
  78. if (!linked) {
  79. GLint infoLen = 0;
  80. glGetProgramiv(programHandle, GL_INFO_LOG_LENGTH, &infoLen);
  81. if (infoLen > 1){
  82. char * infoLog = malloc(sizeof(char) * infoLen);
  83. glGetProgramInfoLog(programHandle, infoLen, NULL, infoLog);
  84. NSLog(@"Error linking program:\n%s\n", infoLog);
  85. free(infoLog);
  86. }
  87. glDeleteProgram(programHandle );
  88. return 0;
  89. }
  90. // Free up no longer needed shader resources
  91. glDeleteShader(vertexShader);
  92. glDeleteShader(fragmentShader);
  93. return programHandle;
  94. }
  95. + (const GLchar *)readFile:(NSString *)name
  96. {
  97. NSString *path;
  98. const GLchar *source;
  99. path = [[NSBundle mainBundle] pathForResource:name ofType: nil];
  100. source = (GLchar *)[[NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil] UTF8String];
  101. return source;
  102. }
  103. #pragma mark -
  104. /* Compile a shader from the provided source(s) */
  105. GLint glueCompileShader(GLenum target, GLsizei count, const GLchar **sources, GLuint *shader)
  106. {
  107. GLint status;
  108. *shader = glCreateShader(target);
  109. glShaderSource(*shader, count, sources, NULL);
  110. glCompileShader(*shader);
  111. #if defined(DEBUG)
  112. GLint logLength = 0;
  113. glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &logLength);
  114. if (logLength > 0)
  115. {
  116. GLchar *log = (GLchar *)malloc(logLength);
  117. glGetShaderInfoLog(*shader, logLength, &logLength, log);
  118. LogInfo("Shader compile log:\n%s", log);
  119. free(log);
  120. }
  121. #endif
  122. glGetShaderiv(*shader, GL_COMPILE_STATUS, &status);
  123. if (status == 0)
  124. {
  125. int i;
  126. LogError("Failed to compile shader:\n");
  127. for (i = 0; i < count; i++)
  128. LogInfo("%s", sources[i]);
  129. }
  130. return status;
  131. }
  132. /* Link a program with all currently attached shaders */
  133. GLint glueLinkProgram(GLuint program)
  134. {
  135. GLint status;
  136. glLinkProgram(program);
  137. #if defined(DEBUG)
  138. GLint logLength = 0;
  139. glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
  140. if (logLength > 0)
  141. {
  142. GLchar *log = (GLchar *)malloc(logLength);
  143. glGetProgramInfoLog(program, logLength, &logLength, log);
  144. LogInfo("Program link log:\n%s", log);
  145. free(log);
  146. }
  147. #endif
  148. glGetProgramiv(program, GL_LINK_STATUS, &status);
  149. if (status == 0)
  150. LogError("Failed to link program %d", program);
  151. return status;
  152. }
  153. /* Validate a program (for i.e. inconsistent samplers) */
  154. GLint glueValidateProgram(GLuint program)
  155. {
  156. GLint status;
  157. glValidateProgram(program);
  158. #if defined(DEBUG)
  159. GLint logLength = 0;
  160. glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength);
  161. if (logLength > 0)
  162. {
  163. GLchar *log = (GLchar *)malloc(logLength);
  164. glGetProgramInfoLog(program, logLength, &logLength, log);
  165. LogInfo("Program validate log:\n%s", log);
  166. free(log);
  167. }
  168. #endif
  169. glGetProgramiv(program, GL_VALIDATE_STATUS, &status);
  170. if (status == 0)
  171. LogError("Failed to validate program %d", program);
  172. return status;
  173. }
  174. /* Return named uniform location after linking */
  175. GLint glueGetUniformLocation(GLuint program, const GLchar *uniformName)
  176. {
  177. GLint loc;
  178. loc = glGetUniformLocation(program, uniformName);
  179. return loc;
  180. }
  181. /* Convenience wrapper that compiles, links, enumerates uniforms and attribs */
  182. GLint glueCreateProgram(const GLchar *vertSource, const GLchar *fragSource,
  183. GLsizei attribNameCt, const GLchar **attribNames,
  184. const GLint *attribLocations,
  185. GLsizei uniformNameCt, const GLchar **uniformNames,
  186. GLint *uniformLocations,
  187. GLuint *program)
  188. {
  189. GLuint vertShader = 0, fragShader = 0, prog = 0, status = 1, i;
  190. // Create shader program
  191. prog = glCreateProgram();
  192. // Create and compile vertex shader
  193. status *= glueCompileShader(GL_VERTEX_SHADER, 1, &vertSource, &vertShader);
  194. // Create and compile fragment shader
  195. status *= glueCompileShader(GL_FRAGMENT_SHADER, 1, &fragSource, &fragShader);
  196. // Attach vertex shader to program
  197. glAttachShader(prog, vertShader);
  198. // Attach fragment shader to program
  199. glAttachShader(prog, fragShader);
  200. // Bind attribute locations
  201. // This needs to be done prior to linking
  202. for (i = 0; i < attribNameCt; i++)
  203. {
  204. if(strlen(attribNames[i]))
  205. glBindAttribLocation(prog, attribLocations[i], attribNames[i]);
  206. }
  207. // Link program
  208. status *= glueLinkProgram(prog);
  209. // Get locations of uniforms
  210. if (status)
  211. {
  212. for(i = 0; i < uniformNameCt; i++)
  213. {
  214. if(strlen(uniformNames[i]))
  215. uniformLocations[i] = glueGetUniformLocation(prog, uniformNames[i]);
  216. }
  217. *program = prog;
  218. }
  219. // Release vertex and fragment shaders
  220. if (vertShader)
  221. glDeleteShader(vertShader);
  222. if (fragShader)
  223. glDeleteShader(fragShader);
  224. return status;
  225. }
  226. @end