466 wiersze
18 KiB

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