25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

easymeshrender.cpp 18 KiB

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 Cdric 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 */