program.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. #include "program.h"
  2. #include "geometry.h"
  3. #include <stdio.h>
  4. static int program_gc(lua_State *L)
  5. {
  6. struct program *p = lua_touserdata(L, -1);
  7. if (p)
  8. program_destroy(p);
  9. return 0;
  10. }
  11. void program_init(struct program *p)
  12. {
  13. p->program = glCreateProgram();
  14. p->vertex_shader = glCreateShader(GL_VERTEX_SHADER);
  15. p->fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
  16. p->vertex_text = "";
  17. p->fragment_text = "";
  18. p->linked = false;
  19. glAttachShader(p->program, p->vertex_shader);
  20. glAttachShader(p->program, p->fragment_shader);
  21. }
  22. void lprogram_create(lua_State *L)
  23. {
  24. struct program *program = lua_newuserdata(L, sizeof(struct program));
  25. program_init(program);
  26. int program_idx = lua_gettop(L);
  27. lua_newtable(L);
  28. lua_pushcfunction(L, program_gc);
  29. lua_setfield(L, -2, "__gc");
  30. lua_setmetatable(L, program_idx);
  31. }
  32. bool lprogram_set_shaders(lua_State *L, const char *vs_text, const char *fs_text)
  33. {
  34. struct program *program = lua_touserdata(L, -1);
  35. if ((vs_text && fs_text) && (strcmp(program->vertex_text, vs_text) || strcmp(program->fragment_text, fs_text))) {
  36. program->linked = false;
  37. program->vertex_text = strdup(vs_text);
  38. program->fragment_text = strdup(fs_text);
  39. if (!program_compile(program)) {
  40. return false;
  41. }
  42. glBindAttribLocation(program->program, ATTRIBUTE_VERTEX, "vertex");
  43. glBindAttribLocation(program->program, ATTRIBUTE_NORMAL, "normal");
  44. glBindAttribLocation(program->program, ATTRIBUTE_UV, "uv");
  45. glBindAttribLocation(program->program, ATTRIBUTE_TANGENT, "tangent");
  46. glBindAttribLocation(program->program, ATTRIBUTE_WEIGHT0, "weights[0]");
  47. glBindAttribLocation(program->program, ATTRIBUTE_WEIGHT1, "weights[1]");
  48. glBindAttribLocation(program->program, ATTRIBUTE_WEIGHT2, "weights[2]");
  49. glBindAttribLocation(program->program, ATTRIBUTE_WEIGHT3, "weights[3]");
  50. glBindAttribLocation(program->program, ATTRIBUTE_WEIGHT4, "weights[4]");
  51. glBindAttribLocation(program->program, ATTRIBUTE_WEIGHT5, "weights[5]");
  52. program_link(program);
  53. }
  54. return program->linked;
  55. }
  56. bool program_compile(struct program *p)
  57. {
  58. glShaderSource(p->vertex_shader, 1, &p->vertex_text, NULL);
  59. glShaderSource(p->fragment_shader, 1, &p->fragment_text, NULL);
  60. glCompileShader(p->vertex_shader);
  61. glCompileShader(p->fragment_shader);
  62. char info_log[1000];
  63. GLint ret;
  64. glGetShaderiv(p->vertex_shader, GL_COMPILE_STATUS, &ret);
  65. if (ret == GL_FALSE) {
  66. glGetShaderInfoLog(p->vertex_shader, 1000, NULL, info_log);
  67. fprintf(stderr, "Vertex shader compile failed:\n %s", info_log);
  68. return false;
  69. }
  70. glGetShaderiv(p->fragment_shader, GL_COMPILE_STATUS, &ret);
  71. if (ret == GL_FALSE) {
  72. glGetShaderInfoLog(p->fragment_shader, 1000, NULL, info_log);
  73. fprintf(stderr, "Fragment shader compile failed:\n %s", info_log);
  74. return false;
  75. }
  76. return true;
  77. }
  78. bool program_link(struct program *p)
  79. {
  80. GLint link_status;
  81. glLinkProgram(p->program);
  82. glGetProgramiv(p->program, GL_LINK_STATUS, &link_status);
  83. if (link_status == GL_FALSE) {
  84. char info_log[1000];
  85. glGetProgramInfoLog(p->program, 1000, NULL, info_log);
  86. fprintf(stderr, "Program link failed:\n %s\n", info_log);
  87. }
  88. p->linked = link_status == GL_TRUE;
  89. return link_status;
  90. }
  91. void program_destroy(struct program *p)
  92. {
  93. glDeleteProgram(p->program);
  94. glDeleteShader(p->vertex_shader);
  95. glDeleteShader(p->fragment_shader);
  96. }