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