b2l.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. #include "b2l.h"
  2. #include "lua.h"
  3. #include "lualib.h"
  4. #include "lauxlib.h"
  5. #include "program.h"
  6. #include "texture.h"
  7. #include <stdio.h>
  8. #include "glsl_parser.h"
  9. #include "glsl_ast.h"
  10. #include <glplatform/glplatform-glcore.h>
  11. #include <gdk-pixbuf/gdk-pixbuf.h>
  12. #include <glib.h>
  13. #include <stdlib.h>
  14. static char *filter_shader_text(lua_State *L, const char *input)
  15. {
  16. char *output;
  17. struct glsl_parse_context context;
  18. glsl_parse_context_init(&context);
  19. glsl_parse_string(&context, input);
  20. output = glsl_ast_generate_glsl(context.root);
  21. glsl_parse_context_destroy(&context);
  22. lua_pushstring(L, "#version 330\n"); //TODO: we need to grab the actual text for this
  23. lua_pushstring(L, output);
  24. lua_concat(L, 2);
  25. free(output);
  26. output = strdup(lua_tostring(L, -1));
  27. lua_pop(L, 1);
  28. return output;
  29. }
  30. static uint8_t *get_file_buffer(const char *fname, size_t *size)
  31. {
  32. FILE *f = fopen(fname, "rb");
  33. if (!f) {
  34. return NULL;
  35. }
  36. fseek(f, 0, SEEK_END);
  37. size_t fsize = ftell(f);
  38. fseek(f, 0, SEEK_SET);
  39. uint8_t *ret = (uint8_t *)malloc(fsize + 1);
  40. if (fread(ret, fsize, 1, f) != 1) {
  41. free(ret);
  42. fclose(f);
  43. return NULL;
  44. }
  45. ret[fsize] = 0;
  46. fclose(f);
  47. if (size)
  48. *size = fsize;
  49. return ret;
  50. }
  51. static void truncate_to_dirname(char *str)
  52. {
  53. char *x = str;
  54. char *y = NULL;
  55. while (*x) {
  56. if (*x == '/')
  57. y = x;
  58. x++;
  59. }
  60. if (y)
  61. *(++y) = 0;
  62. else
  63. *str = 0;
  64. }
  65. bool b2l_load(lua_State *L, const char *b2l_file_name, void ** blob, size_t *blob_size)
  66. {
  67. if (luaL_loadfile(L, b2l_file_name) != LUA_OK) {
  68. fprintf(stderr, "Failed to load B2L file %s\n", b2l_file_name);
  69. return false;
  70. }
  71. lua_call(L, 0, 1);
  72. char *b2l_mat_file_name = g_strdup_printf("%s.mat", b2l_file_name);
  73. if (luaL_loadfile(L, b2l_mat_file_name) != LUA_OK) {
  74. fprintf(stderr, "Failed to load B2L material file %s\n", b2l_mat_file_name);
  75. g_free(b2l_mat_file_name);
  76. return false;
  77. }
  78. lua_call(L, 0, 1);
  79. char *b2l_bin_file_name = g_strdup_printf("%s.bin", b2l_file_name);
  80. *blob = get_file_buffer(b2l_bin_file_name, blob_size);
  81. if (!*blob) {
  82. fprintf(stderr, "Failed to load bin file '%s'\n", b2l_bin_file_name);
  83. g_free(b2l_mat_file_name);
  84. g_free(b2l_bin_file_name);
  85. return false;
  86. }
  87. g_free(b2l_mat_file_name);
  88. g_free(b2l_bin_file_name);
  89. return true;
  90. }
  91. bool b2l_materials_gl_setup(lua_State *L, const char *b2l_file_name, int materials_idx)
  92. {
  93. int prev_top = lua_gettop(L);
  94. bool ret = false;
  95. char *b2l_dir = strdup(b2l_file_name);
  96. truncate_to_dirname(b2l_dir);
  97. lua_pushnil(L);
  98. while(lua_next(L, materials_idx)) {
  99. int material_idx = lua_gettop(L);
  100. lua_getfield(L, material_idx, "program");
  101. //
  102. // Create material program object if it's missing
  103. //
  104. if (!lua_isuserdata(L, -1)) {
  105. lprogram_create(L);
  106. lua_setfield(L, material_idx, "program");
  107. }
  108. lua_getfield(L, material_idx, "program");
  109. int program_idx = lua_gettop(L);
  110. struct program *program = lua_touserdata(L, program_idx);
  111. lua_getfield(L, material_idx, "shaders");
  112. int shaders_idx = lua_gettop(L);
  113. lua_getfield(L, shaders_idx, "fs_filename");
  114. if (lua_isnil(L, -1)) {
  115. fprintf(stderr, "No fragment shader specified for material '%s'\n", lua_tostring(L, material_idx - 1));
  116. goto end;
  117. }
  118. lua_getfield(L, shaders_idx, "vs_filename");
  119. if (lua_isnil(L, -1)) {
  120. fprintf(stderr, "No vertex shader specified for material '%s'\n", lua_tostring(L, material_idx - 1));
  121. goto end;
  122. }
  123. char *abs_vs_filename = g_strdup_printf("%s%s", b2l_dir, lua_tostring(L, -1));
  124. char *abs_fs_filename = g_strdup_printf("%s%s", b2l_dir, lua_tostring(L, -2));
  125. char *vs_text_orig = (char *)get_file_buffer(abs_vs_filename, NULL);
  126. if (!vs_text_orig) {
  127. fprintf(stderr, "Failed to load vertex shader '%s'\n", abs_vs_filename);
  128. g_free(abs_vs_filename);
  129. g_free(abs_fs_filename);
  130. free(vs_text_orig);
  131. goto end;
  132. }
  133. char *fs_text_orig = (char *)get_file_buffer(abs_fs_filename, NULL);
  134. if (!fs_text_orig) {
  135. fprintf(stderr, "Failed to fragment vertex shader '%s'\n", abs_fs_filename);
  136. g_free(abs_vs_filename);
  137. g_free(abs_fs_filename);
  138. free(fs_text_orig);
  139. free(fs_text_orig);
  140. goto end;
  141. }
  142. char *vs_text = filter_shader_text(L, vs_text_orig);
  143. char *fs_text = filter_shader_text(L, fs_text_orig);
  144. lua_pushvalue(L, program_idx);
  145. if (!lprogram_set_shaders(L, vs_text, fs_text)) {
  146. fprintf(stderr, "Failed to compile shaders\n");
  147. g_free(abs_vs_filename);
  148. g_free(abs_fs_filename);
  149. free(vs_text_orig);
  150. free(fs_text_orig);
  151. free(vs_text);
  152. free(fs_text);
  153. goto end;
  154. }
  155. g_free(abs_vs_filename);
  156. g_free(abs_fs_filename);
  157. free(vs_text_orig);
  158. free(fs_text_orig);
  159. free(vs_text);
  160. free(fs_text);
  161. glUseProgram(program->program);
  162. //
  163. // Upload textures if neccisary
  164. //
  165. int texunit = 0;
  166. lua_getfield(L, material_idx, "params");
  167. lua_pushnil(L); /* first key */
  168. while (lua_next(L, -2)) {
  169. int variable_idx = lua_gettop(L);
  170. lua_getfield(L, variable_idx, "datatype");
  171. const char *datatype = lua_tostring(L, -1);
  172. if (!strcmp(datatype,"sampler2D")) {
  173. lua_getfield(L, variable_idx, "_texture");
  174. if (!lua_isuserdata(L, -1)) {
  175. lua_getfield(L, variable_idx, "value");
  176. if (lua_isstring(L, -1)) {
  177. char *abs_filename = g_strdup_printf("%s%s", b2l_dir, lua_tostring(L, -1));
  178. GdkPixbuf *pbuf = gdk_pixbuf_new_from_file(abs_filename, NULL);
  179. if (pbuf) {
  180. //
  181. // Upload pbuf to texture
  182. //
  183. ltexture_create(L, pbuf);
  184. lua_setfield(L, variable_idx, "_texture");
  185. g_object_unref(pbuf);
  186. } else {
  187. fprintf(stderr, "Failed to load image file: %s\n", abs_filename);
  188. goto end;
  189. }
  190. g_free(abs_filename);
  191. }
  192. }
  193. texunit++;
  194. }
  195. lua_settop(L, variable_idx - 1);
  196. }
  197. lua_settop(L, material_idx - 1);
  198. }
  199. ret = true;
  200. end:
  201. lua_settop(L, prev_top);
  202. return ret;
  203. }
  204. bool b2l_is_mesh_object(lua_State *L, int b2l_data_idx, const char *object_name)
  205. {
  206. int prev_top = lua_gettop(L);
  207. bool ret = false;
  208. lua_getfield(L, b2l_data_idx, "objects");
  209. lua_getfield(L, -1, object_name);
  210. if (lua_istable(L, -1)) {
  211. lua_getfield(L, -1, "type");
  212. ret = !strcmp(lua_tostring(L, -1), "MESH");
  213. }
  214. lua_settop(L, prev_top);
  215. return ret;
  216. }