427 lines
16 KiB

  1. //
  2. // Lol Engine
  3. //
  4. // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
  5. // (c) 2009-2013 Cédric Lecacheur <jordx@free.fr>
  6. // (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
  7. // This program is free software; you can redistribute it and/or
  8. // modify it under the terms of the Do What The Fuck You Want To
  9. // Public License, Version 2, as published by Sam Hocevar. See
  10. // http://www.wtfpl.net/ for more details.
  11. //
  12. //
  13. // The EasyMesh class
  14. // ------------------
  15. //
  16. #if defined HAVE_CONFIG_H
  17. # include "config.h"
  18. #endif
  19. #include "core.h"
  20. namespace lol
  21. {
  22. LOLFX_RESOURCE_DECLARE(shiny);
  23. LOLFX_RESOURCE_DECLARE(shinyflat);
  24. LOLFX_RESOURCE_DECLARE(shinydebugwireframe);
  25. LOLFX_RESOURCE_DECLARE(shinydebuglighting);
  26. LOLFX_RESOURCE_DECLARE(shinydebugnormal);
  27. LOLFX_RESOURCE_DECLARE(shinydebugUV);
  28. LOLFX_RESOURCE_DECLARE(shiny_SK);
  29. //-----------------------------------------------------------------------------
  30. GpuShaderData::GpuShaderData()
  31. {
  32. m_render_mode = DebugRenderMode::Default;
  33. }
  34. //-----------------------------------------------------------------------------
  35. GpuShaderData::GpuShaderData(uint16_t vert_decl_flags, Shader* shader, DebugRenderMode render_mode)
  36. {
  37. m_render_mode = render_mode;
  38. m_shader = shader;
  39. m_vert_decl_flags = vert_decl_flags;
  40. }
  41. //-----------------------------------------------------------------------------
  42. GpuShaderData::~GpuShaderData()
  43. {
  44. m_shader_uniform.Empty();
  45. m_shader_attrib.Empty();
  46. }
  47. //-----------------------------------------------------------------------------
  48. void GpuShaderData::AddUniform(const lol::String &new_uniform)
  49. {
  50. m_shader_uniform.Push(new_uniform, m_shader->GetUniformLocation(new_uniform.C()));
  51. }
  52. //-----------------------------------------------------------------------------
  53. void GpuShaderData::AddAttribute(VertexUsage usage, int index)
  54. {
  55. m_shader_attrib.Push(m_shader->GetAttribLocation(usage, index));
  56. }
  57. //-----------------------------------------------------------------------------
  58. ShaderUniform const *GpuShaderData::GetUniform(const lol::String &uniform)
  59. {
  60. for (int i = 0; i < m_shader_uniform.Count(); ++i)
  61. if (m_shader_uniform[i].m1 == uniform)
  62. return &m_shader_uniform[i].m2;
  63. return nullptr;
  64. }
  65. //-----------------------------------------------------------------------------
  66. ShaderAttrib const *GpuShaderData::GetAttribute(VertexUsage usage, int index)
  67. {
  68. for (int i = 0; i < m_shader_attrib.Count(); ++i)
  69. if (m_shader_attrib[i].GetUsage() == usage && m_shader_attrib[i].GetIndex() == index)
  70. return &m_shader_attrib[i];
  71. return nullptr;
  72. }
  73. //-----------------------------------------------------------------------------
  74. DefaultShaderData::DefaultShaderData(DebugRenderMode render_mode)
  75. {
  76. bool with_UV = false;
  77. m_render_mode = render_mode;
  78. m_vert_decl_flags = (1 << VertexUsage::Position) |
  79. (1 << VertexUsage::Normal) |
  80. (1 << VertexUsage::Color);
  81. if (render_mode == DebugRenderMode::Default)
  82. m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shiny));
  83. else if (render_mode == DebugRenderMode::Flat)
  84. m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shinyflat));
  85. else if (render_mode == DebugRenderMode::Wireframe)
  86. m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shinydebugwireframe));
  87. else if (render_mode == DebugRenderMode::Lighting)
  88. m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shinydebuglighting));
  89. else if (render_mode == DebugRenderMode::Normal)
  90. m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shinydebugnormal));
  91. else if (render_mode == DebugRenderMode::UV)
  92. {
  93. m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shinydebugUV));
  94. m_vert_decl_flags |= (1 << VertexUsage::TexCoord);
  95. with_UV = true;
  96. }
  97. StoreUniformNames();
  98. SetupDefaultData(with_UV);
  99. }
  100. //-----------------------------------------------------------------------------
  101. DefaultShaderData::DefaultShaderData(uint16_t vert_decl_flags, Shader* shader, bool with_UV)
  102. : GpuShaderData(vert_decl_flags, shader, DebugRenderMode::Default)
  103. {
  104. StoreUniformNames();
  105. SetupDefaultData(with_UV);
  106. }
  107. static const String DefaultUniforms[7] =
  108. {
  109. String("u_Lights"),
  110. String("in_ModelView"),
  111. String("in_View"),
  112. String("in_Inv_View"),
  113. String("in_Proj"),
  114. String("in_NormalMat"),
  115. String("in_Damage")
  116. };
  117. //-----------------------------------------------------------------------------
  118. void DefaultShaderData::StoreUniformNames()
  119. {
  120. }
  121. //-----------------------------------------------------------------------------
  122. void DefaultShaderData::SetupDefaultData(bool with_UV)
  123. {
  124. UNUSED(with_UV);
  125. for (int i = 0; i < 7; i++)
  126. AddUniform(DefaultUniforms[i]);
  127. }
  128. //-----------------------------------------------------------------------------
  129. void DefaultShaderData::SetupShaderDatas(mat4 const &model)
  130. {
  131. mat4 proj = g_scene->GetCamera()->GetProjection();
  132. mat4 view = g_scene->GetCamera()->GetView();
  133. mat4 modelview = view * model;
  134. mat3 normalmat = transpose(inverse(mat3(modelview)));
  135. /* FIXME: this should be hidden in the shader */
  136. Array<Light *> const &lights = g_scene->GetLights();
  137. Array<vec4> light_data;
  138. //This is not very nice, but necessary for emscripten WebGL generation.
  139. float f = 0.f;
  140. /* FIXME: the 4th component of the position can be used for other things */
  141. /* FIXME: GetUniform("blabla") is costly */
  142. for (int i = 0; i < lights.Count(); ++i)
  143. light_data << vec4(lights[i]->GetPosition(), lights[i]->GetType()) << lights[i]->GetColor();
  144. while (light_data.Count() < 8)
  145. light_data << vec4::zero << vec4::zero;
  146. int i = 0;
  147. m_shader->SetUniform(*GetUniform(DefaultUniforms[i++]), light_data);
  148. m_shader->SetUniform(*GetUniform(DefaultUniforms[i++]), modelview);
  149. m_shader->SetUniform(*GetUniform(DefaultUniforms[i++]), view);
  150. m_shader->SetUniform(*GetUniform(DefaultUniforms[i++]), inverse(view));
  151. m_shader->SetUniform(*GetUniform(DefaultUniforms[i++]), proj);
  152. m_shader->SetUniform(*GetUniform(DefaultUniforms[i++]), normalmat);
  153. m_shader->SetUniform(*GetUniform(DefaultUniforms[i++]), f);
  154. }
  155. //-----------------------------------------------------------------------------
  156. GpuEasyMeshData::GpuEasyMeshData()
  157. {
  158. m_vertexcount = 0;
  159. m_indexcount = 0;
  160. m_ibo = nullptr;
  161. }
  162. //-----------------------------------------------------------------------------
  163. GpuEasyMeshData::~GpuEasyMeshData()
  164. {
  165. m_gpudatas.Empty();
  166. m_vdatas.Empty();
  167. if (m_ibo)
  168. delete(m_ibo);
  169. }
  170. #define BUILD_VFLAG(bool_value, flag_value, check_flag) \
  171. bool bool_value = (check_flag & (1 << flag_value)) != 0; \
  172. check_flag &= ~(1 << flag_value);
  173. #define BUILD_VFLAG_OR(bool_value, flag_value, check_flag) \
  174. bool_value = (bool_value || (check_flag & (1 << flag_value)) != 0); \
  175. check_flag &= ~(1 << flag_value);
  176. #define BUILD_VFLAG_COUNT(bool_value, flag_value, check_flag, count_value) \
  177. BUILD_VFLAG(bool_value, flag_value, check_flag) \
  178. count_value += (int)bool_value;
  179. //-----------------------------------------------------------------------------
  180. void GpuEasyMeshData::AddGpuData(GpuShaderData* gpudata, EasyMesh* src_mesh)
  181. {
  182. uint16_t vflags = gpudata->m_vert_decl_flags;
  183. BUILD_VFLAG(has_position, VertexUsage::Position, vflags);
  184. BUILD_VFLAG(has_normal, VertexUsage::Normal, vflags);
  185. BUILD_VFLAG(has_color, VertexUsage::Color, vflags);
  186. BUILD_VFLAG(has_texcoord, VertexUsage::TexCoord, vflags);
  187. BUILD_VFLAG_OR(has_texcoord, VertexUsage::TexCoordExt, vflags);
  188. ASSERT(!vflags, "Vertex Usage setup is not implemented for %s, feel free to do so.",
  189. VertexUsage::GetNameList(vflags).C());
  190. if (has_position) gpudata->AddAttribute(VertexUsage::Position, 0);
  191. if (has_normal) gpudata->AddAttribute(VertexUsage::Normal, 0);
  192. if (has_color) gpudata->AddAttribute(VertexUsage::Color, 0);
  193. if (has_texcoord) gpudata->AddAttribute(VertexUsage::TexCoord, 0);
  194. SetupVertexData(gpudata->m_vert_decl_flags, src_mesh);
  195. if (!m_ibo)
  196. {
  197. Array<uint16_t> indexlist;
  198. for (int i = 0; i < src_mesh->m_indices.Count(); i += 3)
  199. {
  200. indexlist << src_mesh->m_indices[i + 0];
  201. indexlist << src_mesh->m_indices[i + 1];
  202. indexlist << src_mesh->m_indices[i + 2];
  203. }
  204. m_ibo = new IndexBuffer(indexlist.Bytes());
  205. void *indices = m_ibo->Lock(0, 0);
  206. memcpy(indices, &indexlist[0], indexlist.Bytes());
  207. m_ibo->Unlock();
  208. m_indexcount = indexlist.Count();
  209. }
  210. //init to a minimum of gpudata->m_render_mode size
  211. if (m_gpudatas.Count() <= gpudata->m_render_mode)
  212. {
  213. int i = m_gpudatas.Count();
  214. int max = gpudata->m_render_mode + 1;
  215. m_gpudatas.Reserve(max);
  216. for (; i < max; i++)
  217. m_gpudatas << nullptr;
  218. }
  219. m_gpudatas[gpudata->m_render_mode] = gpudata;
  220. }
  221. //-----------------------------------------------------------------------------
  222. void GpuEasyMeshData::SetupVertexData(uint16_t vflags, EasyMesh* src_mesh)
  223. {
  224. for (int i = 0; i < m_vdatas.Count(); ++i)
  225. if (m_vdatas[i].m1 == vflags)
  226. return;
  227. VertexDeclaration* new_vdecl = nullptr;
  228. VertexBuffer* new_vbo = nullptr;
  229. void *vbo_data = nullptr;
  230. int vbo_bytes = 0;
  231. #define COPY_VBO \
  232. vbo_data = &vertexlist[0]; \
  233. vbo_bytes = vertexlist.Bytes(); \
  234. m_vertexcount = vertexlist.Count(); \
  235. new_vbo = new VertexBuffer(vbo_bytes); \
  236. void *mesh = new_vbo->Lock(0, 0); \
  237. memcpy(mesh, vbo_data, vbo_bytes); \
  238. new_vbo->Unlock();
  239. //Keep a count of the flags
  240. uint16_t saveflags = vflags;
  241. int flagnb = 0;
  242. BUILD_VFLAG_COUNT(has_position, VertexUsage::Position, saveflags, flagnb);
  243. BUILD_VFLAG_COUNT(has_normal, VertexUsage::Normal, saveflags, flagnb);
  244. BUILD_VFLAG_COUNT(has_color, VertexUsage::Color, saveflags, flagnb);
  245. BUILD_VFLAG_COUNT(has_texcoord, VertexUsage::TexCoord, saveflags, flagnb);
  246. BUILD_VFLAG_COUNT(has_texcoordExt,VertexUsage::TexCoordExt, saveflags, flagnb);
  247. ASSERT(!saveflags, "Vertex Declaration setup is not implemented for %s, feel free to do so.",
  248. VertexUsage::GetNameList(vflags).C());
  249. if (flagnb == 5 && has_position && has_normal && has_color && has_texcoord && has_texcoordExt)
  250. {
  251. new_vdecl = new VertexDeclaration(
  252. VertexStream<vec3,vec3,u8vec4,vec4>(
  253. VertexUsage::Position,
  254. VertexUsage::Normal,
  255. VertexUsage::Color,
  256. VertexUsage::TexCoord));
  257. Array<vec3, vec3, u8vec4, vec4> vertexlist;
  258. for (int i = 0; i < src_mesh->m_vert.Count(); i++)
  259. vertexlist.Push(src_mesh->m_vert[i].m_coord,
  260. src_mesh->m_vert[i].m_normal,
  261. (u8vec4)(src_mesh->m_vert[i].m_color * 255.f),
  262. src_mesh->m_vert[i].m_texcoord);
  263. COPY_VBO;
  264. }
  265. else if (flagnb == 4 && has_position && has_normal && has_color && has_texcoord)
  266. {
  267. new_vdecl = new VertexDeclaration(
  268. VertexStream<vec3,vec3,u8vec4,vec2>(
  269. VertexUsage::Position,
  270. VertexUsage::Normal,
  271. VertexUsage::Color,
  272. VertexUsage::TexCoord));
  273. Array<vec3, vec3, u8vec4, vec2> vertexlist;
  274. for (int i = 0; i < src_mesh->m_vert.Count(); i++)
  275. vertexlist.Push(src_mesh->m_vert[i].m_coord,
  276. src_mesh->m_vert[i].m_normal,
  277. (u8vec4)(src_mesh->m_vert[i].m_color * 255.f),
  278. src_mesh->m_vert[i].m_texcoord.xy);
  279. COPY_VBO;
  280. }
  281. else if (flagnb == 4 && has_position && has_color && has_texcoord && has_texcoordExt)
  282. {
  283. new_vdecl = new VertexDeclaration(VertexStream<vec3,vec4,vec4>(VertexUsage::Position, VertexUsage::Color, VertexUsage::TexCoord));
  284. Array<vec3, vec4, vec4> vertexlist;
  285. for (int i = 0; i < src_mesh->m_vert.Count(); i++)
  286. vertexlist.Push(src_mesh->m_vert[i].m_coord, src_mesh->m_vert[i].m_color, src_mesh->m_vert[i].m_texcoord);
  287. COPY_VBO;
  288. }
  289. else if (flagnb == 3 && has_position && has_normal && has_color)
  290. {
  291. new_vdecl = new VertexDeclaration(
  292. VertexStream<vec3,vec3,u8vec4>(
  293. VertexUsage::Position,
  294. VertexUsage::Normal,
  295. VertexUsage::Color));
  296. Array<vec3,vec3,u8vec4> vertexlist;
  297. for (int i = 0; i < src_mesh->m_vert.Count(); i++)
  298. vertexlist.Push(src_mesh->m_vert[i].m_coord,
  299. src_mesh->m_vert[i].m_normal,
  300. (u8vec4)(src_mesh->m_vert[i].m_color * 255.f));
  301. COPY_VBO;
  302. }
  303. else if (flagnb == 3 && has_position && has_texcoord && has_texcoordExt)
  304. {
  305. new_vdecl = new VertexDeclaration(VertexStream<vec3,vec4>(VertexUsage::Position, VertexUsage::TexCoord));
  306. Array<vec3, vec4> vertexlist;
  307. for (int i = 0; i < src_mesh->m_vert.Count(); i++)
  308. vertexlist.Push(src_mesh->m_vert[i].m_coord, src_mesh->m_vert[i].m_texcoord);
  309. COPY_VBO;
  310. }
  311. else if (flagnb == 2 && has_position && has_texcoord)
  312. {
  313. new_vdecl = new VertexDeclaration(VertexStream<vec3,vec2>(VertexUsage::Position, VertexUsage::TexCoord));
  314. Array<vec3, vec2> vertexlist;
  315. for (int i = 0; i < src_mesh->m_vert.Count(); i++)
  316. vertexlist.Push(src_mesh->m_vert[i].m_coord, src_mesh->m_vert[i].m_texcoord.xy);
  317. COPY_VBO;
  318. }
  319. else if (flagnb == 2 && has_position && has_color)
  320. {
  321. new_vdecl = new VertexDeclaration(VertexStream<vec3,u8vec4>(VertexUsage::Position, VertexUsage::Color));
  322. Array<vec3, u8vec4> vertexlist;
  323. for (int i = 0; i < src_mesh->m_vert.Count(); i++)
  324. vertexlist.Push(src_mesh->m_vert[i].m_coord, (u8vec4)(src_mesh->m_vert[i].m_color * 255.f));
  325. COPY_VBO;
  326. }
  327. else
  328. ASSERT(0, "Vertex Declaration combination is not implemented for %s, feel free to do so.",
  329. VertexUsage::GetNameList(vflags).C());
  330. m_vdatas.Push(vflags, new_vdecl, new_vbo);
  331. }
  332. //-----------------------------------------------------------------------------
  333. void GpuEasyMeshData::RenderMeshData(mat4 const &model, int render_mode)
  334. {
  335. ASSERT(0 <= render_mode && render_mode < m_gpudatas.Count(), "render mode is not in the defined range");
  336. ASSERT(m_gpudatas[render_mode], "gpu datas for this render mode don't exist");
  337. GpuShaderData& gpu_sd = *(m_gpudatas[render_mode]);
  338. int vdecl_idx = 0;
  339. for (; vdecl_idx < m_vdatas.Count(); ++vdecl_idx)
  340. if (m_vdatas[vdecl_idx].m1 == gpu_sd.m_vert_decl_flags)
  341. break;
  342. if (vdecl_idx >= m_vdatas.Count())
  343. return;
  344. uint16_t vflags = m_vdatas[vdecl_idx].m1;
  345. VertexDeclaration* vdecl = m_vdatas[vdecl_idx].m2;
  346. VertexBuffer* vbo = m_vdatas[vdecl_idx].m3;
  347. gpu_sd.m_shader->Bind();
  348. gpu_sd.SetupShaderDatas(model);
  349. vdecl->Bind();
  350. BUILD_VFLAG(has_position, VertexUsage::Position, vflags);
  351. BUILD_VFLAG(has_normal, VertexUsage::Normal, vflags);
  352. BUILD_VFLAG(has_color, VertexUsage::Color, vflags);
  353. BUILD_VFLAG(has_texcoord, VertexUsage::TexCoord, vflags);
  354. BUILD_VFLAG_OR(has_texcoord,VertexUsage::TexCoordExt, vflags);
  355. ASSERT(!vflags, "Vertex Stream setup is not implemented for %s, feel free to do so.",
  356. VertexUsage::GetNameList(vflags).C());
  357. int idx = 0;
  358. ShaderAttrib Attribs[4] = { lol::ShaderAttrib(), lol::ShaderAttrib(), lol::ShaderAttrib(), lol::ShaderAttrib() };
  359. if (has_position) Attribs[idx++] = *gpu_sd.GetAttribute(VertexUsage::Position, 0);
  360. if (has_normal) Attribs[idx++] = *gpu_sd.GetAttribute(VertexUsage::Normal, 0);
  361. if (has_color) Attribs[idx++] = *gpu_sd.GetAttribute(VertexUsage::Color, 0);
  362. if (has_texcoord) Attribs[idx++] = *gpu_sd.GetAttribute(VertexUsage::TexCoord, 0);
  363. vdecl->SetStream(vbo, Attribs[0], Attribs[1], Attribs[2], Attribs[3]);
  364. m_ibo->Bind();
  365. vdecl->DrawIndexedElements(MeshPrimitive::Triangles, 0, 0, m_vertexcount, 0, m_indexcount);
  366. m_ibo->Unbind();
  367. vdecl->Unbind();
  368. }
  369. } /* namespace lol */