render.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. #include "render.h"
  2. #include "texture.h"
  3. #include "bsp.h"
  4. #include "cache.h"
  5. #include "common.h"
  6. #include "profiler.h"
  7. #include "atto/app.h"
  8. #define RENDER_ERRORCHECK
  9. //#define RENDER_GL_TRACE
  10. #define RENDER_GL_PROFILE_FUNC profileEvent
  11. #ifndef RENDER_ASSERT
  12. #define RENDER_ASSERT(cond) \
  13. if (!(cond)) { \
  14. aAppDebugPrintf("ERROR @ %s:%d: (%s) failed", __FILE__, __LINE__, #cond); \
  15. aAppTerminate(-1); \
  16. }
  17. #endif /* ifndef RENDER_ASSERT */
  18. #ifdef RENDER_GL_PROFILE_FUNC
  19. #define RENDER_GL_PROFILE_PREAMBLE const ATimeUs profile_time_start__ = aAppTime();
  20. #define RENDER_GL_PROFILE_START const ATimeUs agl_profile_start_ = aAppTime();
  21. #define RENDER_GL_PROFILE_END RENDER_GL_PROFILE_FUNC(__FUNCTION__, aAppTime() - agl_profile_start_);
  22. #define RENDER_GL_PROFILE_END_NAME(name) RENDER_GL_PROFILE_FUNC(name, aAppTime() - agl_profile_start_);
  23. #else
  24. #define RENDER_GL_PROFILE_PREAMBLE
  25. #define RENDER_GL_PROFILE_FUNC(...)
  26. #endif
  27. #if 0 //ndef RENDER_GL_DEBUG
  28. #define GL_CALL(f) (f)
  29. #else
  30. #if 0
  31. #include <stdlib.h> /* abort() */
  32. static void a__GlPrintError(const char *message, int error) {
  33. const char *errstr = "UNKNOWN";
  34. switch (error) {
  35. case GL_INVALID_ENUM: errstr = "GL_INVALID_ENUM"; break;
  36. case GL_INVALID_VALUE: errstr = "GL_INVALID_VALUE"; break;
  37. case GL_INVALID_OPERATION: errstr = "GL_INVALID_OPERATION"; break;
  38. #ifdef GL_STACK_OVERFLOW
  39. case GL_STACK_OVERFLOW: errstr = "GL_STACK_OVERFLOW"; break;
  40. #endif
  41. #ifdef GL_STACK_UNDERFLOW
  42. case GL_STACK_UNDERFLOW: errstr = "GL_STACK_UNDERFLOW"; break;
  43. #endif
  44. case GL_OUT_OF_MEMORY: errstr = "GL_OUT_OF_MEMORY"; break;
  45. #ifdef GL_TABLE_TOO_LARGE
  46. case GL_TABLE_TOO_LARGE: errstr = "GL_TABLE_TOO_LARGE"; break;
  47. #endif
  48. };
  49. PRINTF("%s %s (%#x)", message, errstr, error);
  50. }
  51. #define RENDER_GL_GETERROR(f) \
  52. const int glerror = glGetError(); \
  53. if (glerror != GL_NO_ERROR) { \
  54. a__GlPrintError(__FILE__ ":" RENDER__GL_STR(__LINE__) ": " #f " returned ", glerror); \
  55. abort(); \
  56. }
  57. #else
  58. #define RENDER_GL_GETERROR(f)
  59. #endif
  60. #define RENDER__GL_STR__(s) #s
  61. #define RENDER__GL_STR(s) RENDER__GL_STR__(s)
  62. #ifdef RENDER_GL_TRACE
  63. #define RENDER_GL_TRACE_PRINT PRINTF
  64. #else
  65. #define RENDER_GL_TRACE_PRINT(...)
  66. #endif
  67. #define GL_CALL(f) do{\
  68. RENDER_GL_TRACE_PRINT("%s", #f); \
  69. RENDER_GL_PROFILE_PREAMBLE \
  70. f; \
  71. RENDER_GL_PROFILE_FUNC(#f, aAppTime() - profile_time_start__); \
  72. RENDER_GL_GETERROR(f) \
  73. } while(0)
  74. #endif /* RENDER_GL_DEBUG */
  75. #ifdef _WIN32
  76. #define WGL__FUNCLIST \
  77. WGL__FUNCLIST_DO(PFNGLGENBUFFERSPROC, GenBuffers) \
  78. WGL__FUNCLIST_DO(PFNGLBINDBUFFERPROC, BindBuffer) \
  79. WGL__FUNCLIST_DO(PFNGLBUFFERDATAPROC, BufferData) \
  80. WGL__FUNCLIST_DO(PFNGLGETATTRIBLOCATIONPROC, GetAttribLocation) \
  81. WGL__FUNCLIST_DO(PFNGLACTIVETEXTUREPROC, ActiveTexture) \
  82. WGL__FUNCLIST_DO(PFNGLCREATESHADERPROC, CreateShader) \
  83. WGL__FUNCLIST_DO(PFNGLSHADERSOURCEPROC, ShaderSource) \
  84. WGL__FUNCLIST_DO(PFNGLCOMPILESHADERPROC, CompileShader) \
  85. WGL__FUNCLIST_DO(PFNGLATTACHSHADERPROC, AttachShader) \
  86. WGL__FUNCLIST_DO(PFNGLDELETESHADERPROC, DeleteShader) \
  87. WGL__FUNCLIST_DO(PFNGLGETSHADERIVPROC, GetShaderiv) \
  88. WGL__FUNCLIST_DO(PFNGLGETSHADERINFOLOGPROC, GetShaderInfoLog) \
  89. WGL__FUNCLIST_DO(PFNGLCREATEPROGRAMPROC, CreateProgram) \
  90. WGL__FUNCLIST_DO(PFNGLLINKPROGRAMPROC, LinkProgram) \
  91. WGL__FUNCLIST_DO(PFNGLGETPROGRAMINFOLOGPROC, GetProgramInfoLog) \
  92. WGL__FUNCLIST_DO(PFNGLDELETEPROGRAMPROC, DeleteProgram) \
  93. WGL__FUNCLIST_DO(PFNGLGETPROGRAMIVPROC, GetProgramiv) \
  94. WGL__FUNCLIST_DO(PFNGLUSEPROGRAMPROC, UseProgram) \
  95. WGL__FUNCLIST_DO(PFNGLGETUNIFORMLOCATIONPROC, GetUniformLocation) \
  96. WGL__FUNCLIST_DO(PFNGLUNIFORM1FPROC, Uniform1f) \
  97. WGL__FUNCLIST_DO(PFNGLUNIFORM2FPROC, Uniform2f) \
  98. WGL__FUNCLIST_DO(PFNGLUNIFORM1IPROC, Uniform1i) \
  99. WGL__FUNCLIST_DO(PFNGLUNIFORMMATRIX4FVPROC, UniformMatrix4fv) \
  100. WGL__FUNCLIST_DO(PFNGLENABLEVERTEXATTRIBARRAYPROC, EnableVertexAttribArray) \
  101. WGL__FUNCLIST_DO(PFNGLVERTEXATTRIBPOINTERPROC, VertexAttribPointer) \
  102. WGL__FUNCLIST_DO(PFNGLGENERATEMIPMAPPROC, GenerateMipmap) \
  103. #define WGL__FUNCLIST_DO(T,N) T gl##N = 0;
  104. WGL__FUNCLIST
  105. #undef WGL__FUNCLIST_DO
  106. #endif /* ifdef _WIN32 */
  107. typedef GLint RProgram;
  108. static GLint render_ShaderCreate(GLenum type, const char *sources[]) {
  109. int n;
  110. GLuint shader = glCreateShader(type);
  111. for (n = 0; sources[n]; ++n);
  112. GL_CALL(glShaderSource(shader, n, (const GLchar **)sources, 0));
  113. GL_CALL(glCompileShader(shader));
  114. #ifdef RENDER_ERRORCHECK
  115. {
  116. GLint status;
  117. GL_CALL(glGetShaderiv(shader, GL_COMPILE_STATUS, &status));
  118. if (status != GL_TRUE) {
  119. char buffer[1024];
  120. GL_CALL(glGetShaderInfoLog(shader, sizeof(buffer), 0, buffer));
  121. PRINTF("Shader compilation error: %s", buffer);
  122. GL_CALL(glDeleteShader(shader));
  123. shader = 0;
  124. }
  125. }
  126. #endif
  127. return shader;
  128. }
  129. static RProgram render_ProgramCreate(const char *common, const char *vertex, const char *fragment) {
  130. GLuint program;
  131. GLuint vertex_shader, fragment_shader;
  132. const char *sources[] = {
  133. common, fragment, 0
  134. };
  135. fragment_shader = render_ShaderCreate(GL_FRAGMENT_SHADER, sources);
  136. if (fragment_shader == 0)
  137. return -1;
  138. sources[1] = vertex;
  139. vertex_shader = render_ShaderCreate(GL_VERTEX_SHADER, sources);
  140. if (vertex_shader == 0) {
  141. GL_CALL(glDeleteShader(fragment_shader));
  142. return -2;
  143. }
  144. program = glCreateProgram();
  145. GL_CALL(glAttachShader(program, fragment_shader));
  146. GL_CALL(glAttachShader(program, vertex_shader));
  147. GL_CALL(glLinkProgram(program));
  148. GL_CALL(glDeleteShader(fragment_shader));
  149. GL_CALL(glDeleteShader(vertex_shader));
  150. #ifdef RENDER_ERRORCHECK
  151. {
  152. GLint status;
  153. GL_CALL(glGetProgramiv(program, GL_LINK_STATUS, &status));
  154. if (status != GL_TRUE) {
  155. char buffer[1024];
  156. GL_CALL(glGetProgramInfoLog(program, sizeof(buffer), 0, buffer));
  157. PRINTF("Program linking error: %s", buffer);
  158. GL_CALL(glDeleteProgram(program));
  159. return -3;
  160. }
  161. }
  162. #endif
  163. return program;
  164. }
  165. void renderTextureCreate(RTexture *texture, RTextureCreateParams params) {
  166. GLenum internal, format, type;
  167. GL_CALL(glGenTextures(1, &texture->gl_name));
  168. switch (params.format) {
  169. case RTexFormat_RGB565:
  170. internal = format = GL_RGB; type = GL_UNSIGNED_SHORT_5_6_5; break;
  171. }
  172. GL_CALL(glBindTexture(GL_TEXTURE_2D, texture->gl_name));
  173. GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, internal, params.width, params.height, 0,
  174. format, type, params.pixels));
  175. GL_CALL(glGenerateMipmap(GL_TEXTURE_2D));
  176. GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR));
  177. GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
  178. GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
  179. GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
  180. texture->width = params.width;
  181. texture->height = params.height;
  182. texture->format = params.format;
  183. }
  184. void renderBufferCreate(RBuffer *buffer, RBufferType type, int size, const void *data) {
  185. GL_CALL(glGenBuffers(1, &buffer->gl_name));
  186. GL_CALL(glBindBuffer(type, buffer->gl_name));
  187. GL_CALL(glBufferData(type, size, data, GL_STATIC_DRAW));
  188. }
  189. static const char lmgen_common_src[] =
  190. "varying vec2 v_lightmap_uv, v_tex_uv;\n"
  191. "varying vec3 v_normal;\n";
  192. static const char lmgen_vertex_src[] =
  193. "attribute vec3 a_vertex, a_normal;\n"
  194. "attribute vec2 a_lightmap_uv, a_tex_uv;\n"
  195. "uniform mat4 u_mvp;\n"
  196. "void main() {\n"
  197. "v_lightmap_uv = a_lightmap_uv;\n"
  198. "v_tex_uv = a_tex_uv;\n"
  199. "v_normal = a_normal;\n"
  200. "gl_Position = u_mvp * vec4(a_vertex, 1.);\n"
  201. "}\n";
  202. static const char lmgen_fragment_src[] =
  203. "uniform sampler2D u_lightmap, u_tex0, u_tex1;\n"
  204. "uniform vec2 u_lightmap_size, u_tex0_size, u_tex1_size;\n"
  205. "uniform float u_lmn;\n"
  206. "void main() {\n"
  207. "vec3 tc = vec3(fract(v_tex_uv/u_tex0_size), 0.);\n"
  208. "vec4 albedo = texture2D(u_tex0, v_tex_uv/u_tex0_size);\n"
  209. "albedo = mix(albedo, texture2D(u_tex1, v_tex_uv/u_tex1_size), .0);\n"
  210. "vec3 lm = texture2D(u_lightmap, v_lightmap_uv).xyz;\n"
  211. "vec3 color = albedo.xyz * (vec3(.1) + lm);\n"
  212. "gl_FragColor = vec4(mix(color, tc, u_lmn), 1.);\n"
  213. "}\n";
  214. typedef struct {
  215. const char *name;
  216. int components;
  217. GLenum type;
  218. int stride;
  219. const void *ptr;
  220. int location;
  221. } RAttrib;
  222. typedef struct {
  223. const char *name;
  224. int location;
  225. } RUniform;
  226. static RAttrib lmgen_attribs[] = {
  227. {"a_vertex", 3, GL_FLOAT, sizeof(struct BSPModelVertex), (void*)offsetof(struct BSPModelVertex, vertex), -1},
  228. {"a_normal", 3, GL_FLOAT, sizeof(struct BSPModelVertex), (void*)offsetof(struct BSPModelVertex, normal), -1},
  229. {"a_lightmap_uv", 2, GL_FLOAT, sizeof(struct BSPModelVertex), (void*)offsetof(struct BSPModelVertex, lightmap_uv), -1},
  230. {"a_tex_uv", 2, GL_FLOAT, sizeof(struct BSPModelVertex), (void*)offsetof(struct BSPModelVertex, tex_uv), -1},
  231. {0, 0, 0, 0, 0, -1}
  232. };
  233. static RUniform lmgen_uniforms[] = {
  234. {"u_mvp", -1},
  235. {"u_lmn", -1},
  236. {"u_lightmap", -1},
  237. {"u_tex0", -1},
  238. {"u_tex0_size", -1},
  239. {"u_tex1", -1},
  240. {"u_tex1_size", -1},
  241. {0, -1}
  242. };
  243. static struct {
  244. RProgram lmgen_program;
  245. const RTexture *current_tex0;
  246. } r;
  247. static void renderLocateAttribs(RProgram prog, RAttrib *attribs) {
  248. for(int i = 0; attribs[i].name; ++i) {
  249. attribs[i].location = glGetAttribLocation(prog, attribs[i].name);
  250. if (attribs[i].location < 0)
  251. PRINTF("Cannot locate attribute %s", attribs[i].name);
  252. }
  253. }
  254. static void renderLocateUniforms(RProgram prog, RUniform *uniforms) {
  255. for(int i = 0; uniforms[i].name; ++i) {
  256. uniforms[i].location = glGetUniformLocation(prog, uniforms[i].name);
  257. if (uniforms[i].location < 0)
  258. PRINTF("Cannot locate uniform %s", uniforms[i].name);
  259. }
  260. }
  261. static void renderApplyAttribs(const RAttrib *attribs, const RBuffer *buffer, unsigned int vbo_offset) {
  262. for(int i = 0; attribs[i].name; ++i) {
  263. const RAttrib *a = attribs + i;
  264. if (a->location < 0) continue;
  265. GL_CALL(glEnableVertexAttribArray(a->location));
  266. GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, buffer->gl_name));
  267. GL_CALL(glVertexAttribPointer(a->location, a->components, a->type, GL_FALSE, a->stride, (const char*)a->ptr + vbo_offset * sizeof(struct BSPModelVertex)));
  268. }
  269. }
  270. int renderInit() {
  271. #ifdef _WIN32
  272. #define WGL__FUNCLIST_DO(T, N) \
  273. gl##N = (T)wglGetProcAddress("gl" #N); \
  274. ASSERT(gl##N);
  275. WGL__FUNCLIST
  276. #undef WGL__FUNCLIST_DO
  277. #endif
  278. r.lmgen_program = render_ProgramCreate(lmgen_common_src, lmgen_vertex_src, lmgen_fragment_src);
  279. if (r.lmgen_program <= 0) {
  280. PRINT("Cannot create program for lightmapped generic material");
  281. return 0;
  282. }
  283. renderLocateAttribs(r.lmgen_program, lmgen_attribs);
  284. renderLocateUniforms(r.lmgen_program, lmgen_uniforms);
  285. struct Texture default_texture;
  286. RTextureCreateParams params;
  287. params.format = RTexFormat_RGB565;
  288. params.width = 1;
  289. params.height = 1;
  290. params.pixels = (uint16_t[]){0xffff};
  291. renderTextureCreate(&default_texture.texture, params);
  292. cachePutTexture("opensource/placeholder", &default_texture);
  293. struct Material default_material;
  294. memset(&default_material, 0, sizeof default_material);
  295. default_material.base_texture[0] = cacheGetTexture("opensource/placeholder");
  296. cachePutMaterial("opensource/placeholder", &default_material);
  297. GL_CALL(glEnable(GL_DEPTH_TEST));
  298. GL_CALL(glEnable(GL_CULL_FACE));
  299. r.current_tex0 = 0;
  300. return 1;
  301. }
  302. static int drawCompare(const void *left, const void *right) {
  303. const struct BSPDraw *l = left, *r = right;
  304. const ptrdiff_t diff = l->material - r->material;
  305. if (l->vbo_offset != r->vbo_offset)
  306. return (int)l->vbo_offset - (int)r->vbo_offset;
  307. if (diff == 0)
  308. return l->material->base_texture[0] - r->material->base_texture[0];
  309. return diff;
  310. }
  311. void renderModelOptimize(struct BSPModel *model) {
  312. qsort(model->draws, model->draws_count, sizeof(struct BSPDraw), drawCompare);
  313. }
  314. void renderModelDraw(const struct AMat4f *mvp, float lmn, const struct BSPModel *model) {
  315. if (!model->draws_count) return;
  316. GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, model->ibo.gl_name));
  317. GL_CALL(glUseProgram(r.lmgen_program));
  318. GL_CALL(glActiveTexture(GL_TEXTURE0));
  319. GL_CALL(glBindTexture(GL_TEXTURE_2D, model->lightmap.gl_name));
  320. GL_CALL(glUniformMatrix4fv(lmgen_uniforms[0].location, 1, GL_FALSE, &mvp->X.x));
  321. GL_CALL(glUniform1f(lmgen_uniforms[1].location, lmn));
  322. GL_CALL(glUniform1i(lmgen_uniforms[2].location, 0));
  323. GL_CALL(glUniform1i(lmgen_uniforms[3].location, 1));
  324. GL_CALL(glUniform1i(lmgen_uniforms[5].location, 2));
  325. GL_CALL(glActiveTexture(GL_TEXTURE0 + 1));
  326. int start = model->draws[0].start;
  327. int count = model->draws[0].count;
  328. const struct Material *m = model->draws[0].material;
  329. if (m->base_texture[0]) {
  330. const RTexture *t = &m->base_texture[0]->texture;
  331. if (t != r.current_tex0) {
  332. GL_CALL(glBindTexture(GL_TEXTURE_2D, t->gl_name));
  333. GL_CALL(glUniform2f(lmgen_uniforms[4].location, (float)t->width, (float)t->height));
  334. r.current_tex0 = t;
  335. }
  336. }
  337. renderApplyAttribs(lmgen_attribs, &model->vbo, model->draws->vbo_offset);
  338. for (int i = 1; i < model->draws_count; ++i) {
  339. const struct BSPDraw *d = model->draws + i;
  340. if (drawCompare(d - 1, d) != 0) {
  341. if (-1[d].vbo_offset != d->vbo_offset)
  342. renderApplyAttribs(lmgen_attribs, &model->vbo, d->vbo_offset);
  343. GL_CALL(glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (void*)(sizeof(uint16_t) * start)));
  344. //PRINTF("DRAW start=%d, count=%d", start, count);
  345. const struct Material *m = d->material;
  346. if (m->base_texture[0]) {
  347. const RTexture *t = &m->base_texture[0]->texture;
  348. if (t != r.current_tex0) {
  349. GL_CALL(glBindTexture(GL_TEXTURE_2D, t->gl_name));
  350. GL_CALL(glUniform2f(lmgen_uniforms[4].location, (float)t->width, (float)t->height));
  351. r.current_tex0 = t;
  352. }
  353. }
  354. start = d->start;
  355. count = d->count;
  356. } else {
  357. //PRINTF("start=%d, count=%d; d->start=%d, d->count=%d", start, count, d->start, d->count);
  358. ASSERT(start + count == (int)d->start);
  359. count += d->count;
  360. }
  361. //GL_CALL(glDrawElements(GL_TRIANGLES, d->count, GL_UNSIGNED_SHORT, (void*)(sizeof(uint16_t) * d->start)));
  362. }
  363. //PRINTF("start=%d, count=%d", start, count);
  364. if (count)
  365. GL_CALL(glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT, (void*)(sizeof(uint16_t) * start)));
  366. }
  367. void renderClear() {
  368. glClearColor(.5f,.4f,.2f,0);
  369. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  370. }