You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

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