gl-shader.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. /******************************************************************************
  2. Copyright (C) 2013 by Hugh Bailey <[email protected]>
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ******************************************************************************/
  14. #include <assert.h>
  15. #include "graphics/vec2.h"
  16. #include "graphics/vec3.h"
  17. #include "graphics/vec4.h"
  18. #include "graphics/matrix3.h"
  19. #include "graphics/matrix4.h"
  20. #include "gl-subsystem.h"
  21. #include "gl-shaderparser.h"
  22. static inline void shader_param_init(struct shader_param *param)
  23. {
  24. memset(param, 0, sizeof(struct shader_param));
  25. }
  26. static inline void shader_param_free(struct shader_param *param)
  27. {
  28. bfree(param->name);
  29. da_free(param->cur_value);
  30. da_free(param->def_value);
  31. }
  32. static void gl_get_program_info(GLuint program, char **error_string)
  33. {
  34. char *errors;
  35. GLint info_len = 0;
  36. GLsizei chars_written = 0;
  37. glGetProgramiv(program, GL_INFO_LOG_LENGTH, &info_len);
  38. if (!gl_success("glGetProgramiv") || !info_len)
  39. return;
  40. errors = bmalloc(info_len+1);
  41. memset(errors, 0, info_len+1);
  42. glGetProgramInfoLog(program, info_len, &chars_written, errors);
  43. *error_string = errors;
  44. }
  45. static bool gl_add_param(struct gs_shader *shader, struct shader_var *var,
  46. GLint *texture_id)
  47. {
  48. struct shader_param param = {0};
  49. param.array_count = var->array_count;
  50. param.name = bstrdup(var->name);
  51. param.type = get_shader_param_type(var->type);
  52. if (param.type == SHADER_PARAM_TEXTURE) {
  53. param.sampler_id = var->gl_sampler_id;
  54. param.texture_id = (*texture_id)++;
  55. } else {
  56. param.changed = true;
  57. }
  58. da_move(param.def_value, var->default_val);
  59. da_copy(param.cur_value, param.def_value);
  60. param.param = glGetUniformLocation(shader->program, param.name);
  61. if (!gl_success("glGetUniformLocation"))
  62. return false;
  63. return true;
  64. }
  65. static inline bool gl_add_params(struct gs_shader *shader,
  66. struct gl_shader_parser *glsp)
  67. {
  68. size_t i;
  69. GLint tex_id = 0;
  70. for (i = 0; i < glsp->parser.params.num; i++)
  71. if (!gl_add_param(shader, glsp->parser.params.array+i, &tex_id))
  72. return false;
  73. return true;
  74. }
  75. static void gl_add_sampler(struct gs_shader *shader,
  76. struct shader_sampler *sampler)
  77. {
  78. struct gs_sampler new_sampler = {0};
  79. struct gs_sampler_info info;
  80. shader_sampler_convert(sampler, &info);
  81. convert_sampler_info(&new_sampler, &info);
  82. da_push_back(shader->samplers, &new_sampler);
  83. }
  84. static inline void gl_add_samplers(struct gs_shader *shader,
  85. struct gl_shader_parser *glsp)
  86. {
  87. size_t i;
  88. for (i = 0; i < glsp->parser.samplers.num; i++) {
  89. struct shader_sampler *sampler = glsp->parser.samplers.array+i;
  90. gl_add_sampler(shader, sampler);
  91. }
  92. }
  93. static bool gl_shader_init(struct gs_shader *shader,
  94. struct gl_shader_parser *glsp,
  95. const char *file, char **error_string)
  96. {
  97. GLenum type = convert_shader_type(shader->type);
  98. int compiled = 0;
  99. bool success = true;
  100. shader->program = glCreateShaderProgramv(type, 1,
  101. &glsp->gl_string.array);
  102. gl_success("glCreateShaderProgramv");
  103. if (!shader->program)
  104. return false;
  105. glGetProgramiv(shader->program, GL_VALIDATE_STATUS, &compiled);
  106. if (!gl_success("glGetProgramiv"))
  107. return false;
  108. if (!compiled)
  109. success = false;
  110. gl_get_program_info(shader->program, error_string);
  111. if (success)
  112. success = gl_add_params(shader, glsp);
  113. if (success)
  114. gl_add_samplers(shader, glsp);
  115. return success;
  116. }
  117. static struct gs_shader *shader_create(device_t device, enum shader_type type,
  118. const char *shader_str, const char *file, char **error_string)
  119. {
  120. struct gs_shader *shader = bmalloc(sizeof(struct gs_shader));
  121. struct gl_shader_parser glsp;
  122. bool success = true;
  123. memset(shader, 0, sizeof(struct gs_shader));
  124. shader->type = type;
  125. gl_shader_parser_init(&glsp);
  126. if (!gl_shader_parse(&glsp, shader_str, file))
  127. success = false;
  128. else
  129. success = gl_shader_init(shader, &glsp, file, error_string);
  130. if (!success) {
  131. shader_destroy(shader);
  132. shader = NULL;
  133. }
  134. gl_shader_parser_free(&glsp);
  135. return shader;
  136. }
  137. shader_t device_create_vertexshader(device_t device,
  138. const char *shader, const char *file,
  139. char **error_string)
  140. {
  141. return shader_create(device, SHADER_VERTEX, shader, file, error_string);
  142. }
  143. shader_t device_create_pixelshader(device_t device,
  144. const char *shader, const char *file,
  145. char **error_string)
  146. {
  147. return shader_create(device, SHADER_PIXEL, shader, file, error_string);
  148. }
  149. void shader_destroy(shader_t shader)
  150. {
  151. size_t i;
  152. if (!shader)
  153. return;
  154. for (i = 0; i < shader->params.num; i++)
  155. shader_param_free(shader->params.array+i);
  156. if (shader->program) {
  157. glDeleteProgram(shader->program);
  158. gl_success("glDeleteProgram");
  159. }
  160. da_free(shader->samplers);
  161. da_free(shader->params);
  162. bfree(shader);
  163. }
  164. int shader_numparams(shader_t shader)
  165. {
  166. return (int)shader->params.num;
  167. }
  168. sparam_t shader_getparambyidx(shader_t shader, int param)
  169. {
  170. assert(param < shader->params.num);
  171. return shader->params.array+param;
  172. }
  173. sparam_t shader_getparambyname(shader_t shader, const char *name)
  174. {
  175. size_t i;
  176. for (i = 0; i < shader->params.num; i++) {
  177. struct shader_param *param = shader->params.array+i;
  178. if (strcmp(param->name, name) == 0)
  179. return param;
  180. }
  181. return NULL;
  182. }
  183. void shader_getparaminfo(shader_t shader, sparam_t param,
  184. struct shader_param_info *info)
  185. {
  186. info->type = param->type;
  187. info->name = param->name;
  188. }
  189. sparam_t shader_getviewprojmatrix(shader_t shader)
  190. {
  191. return shader->viewproj;
  192. }
  193. sparam_t shader_getworldmatrix(shader_t shader)
  194. {
  195. return shader->world;
  196. }
  197. void shader_setbool(shader_t shader, sparam_t param, bool val)
  198. {
  199. glProgramUniform1i(shader->program, param->param, (GLint)val);
  200. gl_success("glProgramUniform1i");
  201. }
  202. void shader_setfloat(shader_t shader, sparam_t param, float val)
  203. {
  204. glProgramUniform1f(shader->program, param->param, val);
  205. gl_success("glProgramUniform1f");
  206. }
  207. void shader_setint(shader_t shader, sparam_t param, int val)
  208. {
  209. glProgramUniform1i(shader->program, param->param, val);
  210. gl_success("glProgramUniform1i");
  211. }
  212. void shader_setmatrix3(shader_t shader, sparam_t param,
  213. const struct matrix3 *val)
  214. {
  215. struct matrix4 mat;
  216. matrix4_from_matrix3(&mat, val);
  217. glProgramUniformMatrix4fv(shader->program, param->param, 1, true,
  218. mat.x.ptr);
  219. gl_success("glProgramUniformMatrix4fv");
  220. }
  221. void shader_setmatrix4(shader_t shader, sparam_t param,
  222. const struct matrix4 *val)
  223. {
  224. glProgramUniformMatrix4fv(shader->program, param->param, 1, true,
  225. val->x.ptr);
  226. gl_success("glProgramUniformMatrix4fv");
  227. }
  228. void shader_setvec2(shader_t shader, sparam_t param,
  229. const struct vec2 *val)
  230. {
  231. glProgramUniform2fv(shader->program, param->param, 1, val->ptr);
  232. gl_success("glProgramUniform2fv");
  233. }
  234. void shader_setvec3(shader_t shader, sparam_t param,
  235. const struct vec3 *val)
  236. {
  237. glProgramUniform3fv(shader->program, param->param, 1, val->ptr);
  238. gl_success("glProgramUniform3fv");
  239. }
  240. void shader_setvec4(shader_t shader, sparam_t param,
  241. const struct vec4 *val)
  242. {
  243. glProgramUniform4fv(shader->program, param->param, 1, val->ptr);
  244. gl_success("glProgramUniform4fv");
  245. }
  246. void shader_settexture(shader_t shader, sparam_t param, texture_t val)
  247. {
  248. }
  249. static void shader_setval_data(shader_t shader, sparam_t param,
  250. const void *val, int count)
  251. {
  252. if (param->type == SHADER_PARAM_BOOL ||
  253. param->type == SHADER_PARAM_INT) {
  254. glProgramUniform1iv(shader->program, param->param, count, val);
  255. gl_success("glProgramUniform1iv");
  256. } else if (param->type == SHADER_PARAM_FLOAT) {
  257. glProgramUniform1fv(shader->program, param->param, count, val);
  258. gl_success("glProgramUniform1fv");
  259. } else if (param->type == SHADER_PARAM_VEC2) {
  260. glProgramUniform2fv(shader->program, param->param, count, val);
  261. gl_success("glProgramUniform2fv");
  262. } else if (param->type == SHADER_PARAM_VEC3) {
  263. glProgramUniform3fv(shader->program, param->param, count, val);
  264. gl_success("glProgramUniform3fv");
  265. } else if (param->type == SHADER_PARAM_VEC4) {
  266. glProgramUniform4fv(shader->program, param->param, count, val);
  267. gl_success("glProgramUniform4fv");
  268. } else if (param->type == SHADER_PARAM_MATRIX4X4) {
  269. glProgramUniformMatrix4fv(shader->program, param->param,
  270. count, false, val);
  271. gl_success("glProgramUniformMatrix4fv");
  272. }
  273. }
  274. void shader_setval(shader_t shader, sparam_t param, const void *val,
  275. size_t size)
  276. {
  277. int count = param->array_count;
  278. size_t expected_size = 0;
  279. if (!count)
  280. count = 1;
  281. switch (param->type) {
  282. case SHADER_PARAM_FLOAT: expected_size = sizeof(float); break;
  283. case SHADER_PARAM_BOOL:
  284. case SHADER_PARAM_INT: expected_size = sizeof(int); break;
  285. case SHADER_PARAM_VEC2: expected_size = sizeof(float)*2; break;
  286. case SHADER_PARAM_VEC3: expected_size = sizeof(float)*3; break;
  287. case SHADER_PARAM_VEC4: expected_size = sizeof(float)*4; break;
  288. case SHADER_PARAM_MATRIX3X3: expected_size = sizeof(float)*3*3; break;
  289. case SHADER_PARAM_MATRIX4X4: expected_size = sizeof(float)*4*4; break;
  290. }
  291. expected_size *= count;
  292. if (!expected_size)
  293. return;
  294. if (expected_size != size) {
  295. blog(LOG_ERROR, "shader_setval (GL): Size of shader param does "
  296. "not match the size of the input");
  297. return;
  298. }
  299. shader_setval_data(shader, param, val, count);
  300. }
  301. void shader_setdefault(shader_t shader, sparam_t param)
  302. {
  303. shader_setval(shader, param, param->def_value.array,
  304. param->def_value.num);
  305. }