shader.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #ifndef SHADER_H
  2. #define SHADER_H
  3. #include <GL/glew.h>
  4. enum shader_err {
  5. SHADER_ERR_OK,
  6. SHADER_ERR_FAIL_CREATE,
  7. SHADER_ERR_FAIL_CREATE_PROG,
  8. SHADER_ERR_FAIL_COMPILE,
  9. SHADER_ERR_FAIL_READ_FILE,
  10. SHADER_ERR_FAIL_LINK_PROG
  11. };
  12. struct ret_uint32_t_err {
  13. uint32_t f1;
  14. enum shader_err f2;
  15. };
  16. struct ret_uint32_t_err shader_compile_source(const char *src, GLenum type);
  17. struct ret_uint32_t_err shader_compile_file(const char *filepath, GLenum type);
  18. uint32_t shader_compile_file_or_exit(const char *filepath, GLenum type);
  19. struct ret_uint32_t_err program_link(uint32_t vert_shader,
  20. uint32_t frag_shader);
  21. uint32_t program_link_or_exit(uint32_t vert_shader, uint32_t frag_shader);
  22. const char *shader_type_to_cstr(GLenum type);
  23. #if defined(SHADER_IMP) || defined(IMP)
  24. #include <stdio.h>
  25. #include "unwrap.h"
  26. #include "file.h"
  27. struct ret_uint32_t_err
  28. shader_compile_source(const char *src, GLenum type)
  29. {
  30. enum shader_err err;
  31. uint32_t shdr = glCreateShader(type);
  32. if ( shdr == 0 ) {
  33. err = SHADER_ERR_FAIL_CREATE;
  34. goto err;
  35. }
  36. glShaderSource(shdr, 1, &src, NULL);
  37. glCompileShader(shdr);
  38. int32_t comp_status = GL_FALSE;
  39. glGetShaderiv(shdr, GL_COMPILE_STATUS, &comp_status);
  40. if ( comp_status == GL_FALSE ) {
  41. err = SHADER_ERR_FAIL_COMPILE;
  42. int32_t log_length = 1024;
  43. glGetShaderiv(shdr, GL_INFO_LOG_LENGTH, &log_length);
  44. log_length += 10;
  45. char *log = calloc(sizeof(char), (size_t)log_length);
  46. glGetShaderInfoLog(shdr, log_length, NULL, log);
  47. fprintf(stderr, "FAILED COMPILE %s : %s\n",
  48. shader_type_to_cstr(type), log);
  49. goto err;
  50. }
  51. return (struct ret_uint32_t_err) {
  52. .f1 = shdr,
  53. .f2 = SHADER_ERR_OK
  54. };
  55. err: ;
  56. return (struct ret_uint32_t_err) {
  57. .f1 = 0,
  58. .f2 = err
  59. };
  60. }
  61. struct ret_uint32_t_err
  62. shader_compile_file(const char *filepath, GLenum type)
  63. {
  64. char *src;
  65. enum file_err err;
  66. src = (char *) file_read_all(filepath, NULL, &err);
  67. if ( err != FILE_ERR_OK ) {
  68. return (struct ret_uint32_t_err) {
  69. .f1 = 0,
  70. .f2 = SHADER_ERR_FAIL_READ_FILE,
  71. };
  72. }
  73. struct ret_uint32_t_err ret = shader_compile_source(src, type);
  74. free(src);
  75. return ret;
  76. }
  77. uint32_t
  78. shader_compile_file_or_exit(const char *filepath, GLenum type)
  79. {
  80. enum shader_err err;
  81. uint32_t shader;
  82. RET_UNWRAP2(shader, err, struct ret_uint32_t_err,
  83. shader_compile_file(filepath, type));
  84. if ( err != SHADER_ERR_OK ) {
  85. fprintf(stderr, "Failed to compile shader %s\n", filepath);
  86. exit(EXIT_FAILURE);
  87. }
  88. return shader;
  89. }
  90. struct ret_uint32_t_err
  91. program_link(uint32_t vert_shader, uint32_t frag_shader)
  92. {
  93. enum shader_err err;
  94. uint32_t prog = glCreateProgram();
  95. if ( prog == 0 ) {
  96. err = SHADER_ERR_FAIL_CREATE_PROG;
  97. goto err;
  98. }
  99. glAttachShader(prog, vert_shader);
  100. glAttachShader(prog, frag_shader);
  101. glLinkProgram(prog);
  102. int32_t link_status = GL_FALSE;
  103. glGetProgramiv(prog, GL_LINK_STATUS, &link_status);
  104. if ( link_status != GL_TRUE ) {
  105. err = SHADER_ERR_FAIL_LINK_PROG;
  106. int32_t log_length = 1024;
  107. glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &log_length);
  108. log_length += 10;
  109. char *log = calloc(sizeof(char), (size_t)log_length);
  110. glGetProgramInfoLog(prog, log_length, NULL, log);
  111. fprintf(stderr, "FAILED LINK PROG: %s\n", log);
  112. goto err;
  113. }
  114. glDeleteShader(vert_shader);
  115. glDeleteShader(frag_shader);
  116. return (struct ret_uint32_t_err) {
  117. .f1 = prog,
  118. .f2 = SHADER_ERR_OK,
  119. };
  120. err: ;
  121. return (struct ret_uint32_t_err) {
  122. .f1 = 0,
  123. .f2 = err,
  124. };
  125. }
  126. uint32_t
  127. program_link_or_exit(uint32_t vert_shader, uint32_t frag_shader)
  128. {
  129. enum shader_err err;
  130. uint32_t prog;
  131. RET_UNWRAP2(prog, err, struct ret_uint32_t_err,
  132. program_link(vert_shader, frag_shader));
  133. if ( err != SHADER_ERR_OK ) {
  134. fprintf(stderr, "Failed to link program\n");
  135. exit(EXIT_FAILURE);
  136. }
  137. return prog;
  138. }
  139. const char *
  140. shader_type_to_cstr(GLenum type)
  141. {
  142. switch ( type ) {
  143. case GL_VERTEX_SHADER: return "GL_VERTEX_SHADER"; break;
  144. case GL_FRAGMENT_SHADER: return "GL_FRAGMENT_SHADER"; break;
  145. }
  146. return "(Unknown Shader)";
  147. }
  148. #endif /* defined(SHADER_IMP) || defined(IMP) */
  149. #endif