Renderer Instancing.cpp 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. /******************************************************************************
  4. Rendering is sorted by:
  5. -Shaders
  6. -Materials
  7. -Meshes
  8. -Instances
  9. Most Materials will use only 1 Shader (only few cases will use more)
  10. Because of that, Materials have one link ('MaterialShader') to the Shader already included in Material object (to reduce overhead).
  11. In cases where Material needs another shader, then that link can point to next link in 'MaterialShaders' container (this is a linked list, where links can continuously point to next links in that container)
  12. With this mechanism we have unique MaterialShader objects (Material -> Shader), however during rendering we need to have links the other way around (Shader -> Material).
  13. Because first we set Shaders, then iterate all Materials belonging to this Shader.
  14. All draw calls will store 'ShaderDraw' first, and then that object will have a linked list of all Materials belonging to this Shader ('ShaderMaterial' objects).
  15. Then 'ShaderMaterial' has a linked list of all meshes 'ShaderMaterialMesh', which then have instances '*ShaderMaterialMeshInstance'.
  16. 'ShaderMaterial' needs to be separate from 'MaterialShader', because:
  17. 'MaterialShader' is a linked list of shaders for 1 material
  18. 'ShaderMaterial' is a linked list of materials for 1 shader
  19. However all instances are managed per MeshPart.Variation, which is not perfect, because for example, MeshPart can have multiple variations, and some of them may have the same material.
  20. Even though material is the same, they will not be instanced together. We would have to manage some sort of "unique variation" list in the MeshPart, which would complicate things.
  21. TODO: most of (highlight, shader_param_changes, stencil) instance parameters are never used, can we do something about it? to remove overhead and memory usage
  22. TODO: on stereo rendering some pixels are wasted, use a stencil mask, see - http://media.steampowered.com/apps/valve/2015/Alex_Vlachos_Advanced_VR_Rendering_GDC2015.pdf
  23. /******************************************************************************/
  24. #define MAX_MATRIX_INSTANCE (GL ? MAX_MATRIX_DX9 : MAX_MATRIX_DX10) // if instancing is supported then we have all possible matrixes
  25. /******************************************************************************/
  26. namespace EE{
  27. /******************************************************************************/
  28. static Color Highlight;
  29. Bool _SetHighlight(C Color &color)
  30. {
  31. if(color!=Highlight){Renderer.highlight->set(Highlight=color); return true;}
  32. return false;
  33. }
  34. void SetDrawMask ( UInt draw_mask ) {Renderer._mesh_draw_mask =draw_mask;}
  35. void SetVariation ( Int variation ) {Renderer._mesh_variation_1 =variation-1;} // offset it over here, instead of every time in mesh draw
  36. void SetHighlight (C Color &color ) {Renderer._mesh_highlight =color;}
  37. void SetStencilValue( Bool terrain ) {Renderer._mesh_stencil_value=(terrain ? STENCIL_REF_TERRAIN : STENCIL_REF_ZERO);}
  38. void SetStencilMode ( Bool terrain_only) {Renderer._mesh_stencil_mode =(terrain_only ? STENCIL_TERRAIN_TEST : STENCIL_NONE );}
  39. void SetBlendAlpha (ALPHA_MODE alpha ) {Renderer._mesh_blend_alpha =alpha;}
  40. void SetEarlyZ ( Bool on ) {Renderer._mesh_early_z =on;}
  41. void SetBehindBias ( Flt distance ) {Sh.h_BehindBias->setConditional(distance);}
  42. static INLINE void DisableSkinning() {Sh.h_VtxSkinning->setConditional(0.0f);}
  43. static INLINE void EnableSkinning() {Sh.h_VtxSkinning->setConditional(1.0f);}
  44. /******************************************************************************
  45. // SHADER PARAM CHANGES
  46. /******************************************************************************/
  47. void LinkShaderParamChanges(const_mem_addr C Memc<ShaderParamChange> &changes)
  48. {
  49. if(!Renderer._shader_param_changes)Renderer._shader_param_changes=&changes;else Exit("Trying to 'LinkShaderParamChanges' while there are other changes that weren't unlinked.");
  50. }
  51. void UnlinkShaderParamChanges(const_mem_addr C Memc<ShaderParamChange> &changes)
  52. {
  53. if(Renderer._shader_param_changes==&changes)Renderer._shader_param_changes=null;else Exit("Trying to 'UnlinkShaderParamChanges' that weren't linked.");
  54. }
  55. struct ShaderParamRestore
  56. {
  57. ShaderParam *param;
  58. Vec4 value;
  59. void restore()C {param->setSafe(value);} // have to use 'setSafe' because the 'ShaderParam' can be smaller than what we're setting
  60. void operator=(ShaderParam *param) {T.param=param; T.value=*(Vec4*)param->_data;} // set param and remember its current value
  61. };
  62. static Memc<ShaderParamRestore> RestoreChanges;
  63. static C Memc<ShaderParamChange > *LastChanges;
  64. static Bool SetShaderParamChanges(C Memc<ShaderParamChange> *changes=null)
  65. {
  66. if(LastChanges!=changes)
  67. {
  68. // restore previous changes if any
  69. REPAO(RestoreChanges).restore(); // restore in backwards order
  70. RestoreChanges.clear();
  71. // apply new changes
  72. if(LastChanges=changes)REPA(*LastChanges)
  73. {
  74. C ShaderParamChange &change=(*LastChanges)[i];
  75. if(change.param)
  76. {
  77. RestoreChanges.add(change.param); // add for restoration
  78. change.param->setSafe(change.value); // apply change, have to use 'setSafe' because the 'ShaderParam' can be smaller than what we're setting
  79. }
  80. }
  81. return true;
  82. }
  83. return false;
  84. }
  85. /******************************************************************************/
  86. void ShaderMaterial::unlink()
  87. {
  88. #if SUPPORT_MATERIAL_CHANGE_IN_RENDERING
  89. if(..)material->unlink(); // need to detect if this is 'material' or 'umm', and we can't check smm->mesh->_umm because this could have already been changed with MeshPart.material call, or this could be ShaderMaterial for shadow which ignores umm
  90. else umm ->unlink();
  91. #else
  92. if(ShaderMaterialMesh *smm=ShaderMaterialMeshes.addr(first_shader_material_mesh))
  93. {
  94. if(C Material *material=smm->Variation().material())material->unlink();
  95. if( UniqueMultiMaterialData *umm =smm->mesh->_umm )umm ->unlink();
  96. }
  97. #endif
  98. }
  99. /******************************************************************************/
  100. Memc<Material::MaterialShader > MaterialShaders;
  101. Memc< ShaderDraw > ShaderDraws, MultiMaterialShaderDraws;
  102. Memc< ShaderMaterial > ShaderMaterials;
  103. Memc< ShaderMaterialMesh > ShaderMaterialMeshes;
  104. Memc< SolidShaderMaterialMeshInstance> SolidShaderMaterialMeshInstances;
  105. Memc<ShadowShaderMaterialMeshInstance> ShadowShaderMaterialMeshInstances;
  106. Memc< AmbientInstance> AmbientInstances;
  107. Memc< SkeletonShader > SkeletonShaders;
  108. Memc< SkeletonBlendShader > SkeletonBlendShaders;
  109. Memc< SkeletonShaderMaterial > SkeletonShaderMaterials, SkeletonBlendShaderMaterials;
  110. Memc< SkeletonShaderMaterialMeshInstance> SkeletonShadowShaderMaterialMeshInstances;
  111. Memc<SkeletonSolidShaderMaterialMeshInstance> SkeletonSolidShaderMaterialMeshInstances;
  112. Memc<SkeletonBlendShaderMaterialMeshInstance> SkeletonBlendShaderMaterialMeshInstances;
  113. SkeletonInstances SkeletonSolidInstances, SkeletonShadowInstances;
  114. Memc<SkeletonAmbientInstance > SkeletonAmbientInstances;
  115. BlendInstancesClass BlendInstances;
  116. ClothInstances SolidClothInstances, ShadowClothInstances;
  117. GameObjects PaletteObjects, Palette1Objects, OverlayObjects, SolidObjects, AmbientObjects, OutlineObjects, BehindObjects;
  118. GameAreas PaletteAreas , Palette1Areas;
  119. /******************************************************************************/
  120. #if 0 // this doesn't work, because we need to adjust ViewMatrix and not ProjMatrix (for example Shadows in Forward Renderer will not work, because VS_PS.pos in shaders depends on ViewMatrix only, it affects shadows, and reflections, etc.)
  121. // precomputed view matrixes were generated for the first eye, so for next eye we need to adjust the projection matrix (instead of adjusting camera and recalculating view matrixes which would be slower)
  122. static void BeginPrecomputedViewMatrix() {if(/*Renderer._stereo && */Renderer._eye!=0)SetProjMatrix(ProjMatrixEyeOffset[Renderer._eye], -D.eyeDistance());}
  123. static void EndPrecomputedViewMatrix() {if(/*Renderer._stereo && */Renderer._eye!=0)SetProjMatrix(ProjMatrixEyeOffset[Renderer._eye]);}
  124. struct EyeCache
  125. {
  126. Int cur_eye, normal_eye, precomputed_eye;
  127. EyeCache() {cur_eye=normal_eye=Renderer._eye; precomputed_eye=0;}
  128. void setEye(Int eye) {if(cur_eye!=eye){cur_eye=eye; SetProjMatrix(ProjMatrixEyeOffset[Renderer._eye], eye ? 0 : -D.eyeDistance());}}
  129. INLINE void BeginPrecomputedViewMatrix() {setEye(precomputed_eye);}
  130. INLINE void EndPrecomputedViewMatrix() {setEye( normal_eye);}
  131. };
  132. static INLINE void SetViewOffset() {}
  133. static INLINE void SetViewMatrix(C Matrix &view_matrix, Int i=0) {ViewMatrix[i]=view_matrix;} // !! Warning: this doesn't call 'setChanged' !!
  134. #else
  135. static INLINE void BeginPrecomputedViewMatrix() {}
  136. static INLINE void EndPrecomputedViewMatrix() {}
  137. struct EyeCache
  138. {
  139. INLINE void BeginPrecomputedViewMatrix() {}
  140. INLINE void EndPrecomputedViewMatrix() {}
  141. };
  142. static Flt ViewOffset;
  143. static INLINE void SetViewOffset() {ViewOffset=(Renderer._eye ? -D.eyeDistance() : 0);}
  144. static INLINE void SetViewMatrix(C Matrix &view_matrix, Int i=0) {ViewMatrix[i]=view_matrix; ViewMatrix[i]._x+=ViewOffset;} // !! Warning: this doesn't call 'setChanged' !!
  145. #endif
  146. /******************************************************************************/
  147. // EARLY Z
  148. /******************************************************************************/
  149. #if SUPPORT_EARLY_Z
  150. Memc<EarlyZInstance> EarlyZInstances[2];
  151. Bool HasEarlyZInstances()
  152. {
  153. return (EarlyZInstances[0].elms()+EarlyZInstances[1].elms())>0;
  154. }
  155. void DrawEarlyZInstances()
  156. {
  157. SetViewOffset();
  158. BeginPrecomputedViewMatrix();
  159. D.depth(true);
  160. SetMatrixCount();
  161. DisableSkinning();
  162. Renderer._shader_early_z->start(); // this shader doesn't require any textures
  163. // TODO: this could be optimized to group in state changes (mesh->instance) and allow instancing
  164. FREPA(EarlyZInstances)
  165. {
  166. C Memc<EarlyZInstance> &instances=EarlyZInstances[i];
  167. if(instances.elms())
  168. {
  169. D.cull(i);
  170. FREPA(instances)
  171. {
  172. C EarlyZInstance &instance=instances[i];
  173. SetViewMatrix(instance.view_matrix); Sh.h_ViewMatrix->setChanged();
  174. Renderer._shader_early_z->commit();
  175. instance.mesh->set().drawFull();
  176. }
  177. }
  178. }
  179. ShaderEnd();
  180. EndPrecomputedViewMatrix();
  181. }
  182. void ClearEarlyZInstances()
  183. {
  184. EarlyZInstances[0].clear();
  185. EarlyZInstances[1].clear();
  186. }
  187. #endif
  188. /******************************************************************************/
  189. // SOLID
  190. /******************************************************************************/
  191. static INLINE void DrawSolidInstances(Bool forward)
  192. {
  193. SetViewOffset();
  194. BeginPrecomputedViewMatrix();
  195. const Bool instancing=D.hwInstancing();
  196. D.depth(true);
  197. // solid
  198. SetMatrixCount();
  199. DisableSkinning();
  200. FREPA(ShaderDraws)
  201. {
  202. ShaderDraw &shader_draw=ShaderDraws[i]; shader_draw.unlink(); // have to unlink 'shader_draw' instead of 'shader' (because it can be FRST)
  203. Shader &shader =shader_draw.shader->getShader(forward); shader.start();
  204. for(ShaderMaterial *shader_material=&ShaderMaterials[shader_draw.first_shader_material]; ; )
  205. {
  206. ShaderMaterialMesh *shader_material_mesh=&ShaderMaterialMeshes[shader_material->first_shader_material_mesh];
  207. #if SUPPORT_MATERIAL_CHANGE_IN_RENDERING
  208. C Material &material =*shader_material->material;
  209. #else
  210. C MeshPart::Variation *variation =&shader_material_mesh->Variation(); // have to access 'variation' here, because we need it to access 'material' since we're not storing it in the 'ShaderMaterial'
  211. C Material &material = variation->getMaterial();
  212. #endif
  213. material.unlinkSolid(); material.setSolid(); D.cull(material.cull); shader.commitTex();
  214. for(;;)
  215. {
  216. C MeshPart &mesh=*shader_material_mesh->mesh;
  217. #if SUPPORT_MATERIAL_CHANGE_IN_RENDERING
  218. mesh.unlinkSolid();
  219. #else
  220. variation->unlinkSolid();
  221. #endif
  222. C MeshRender &render=mesh.render.set();
  223. C Bool instancing_mesh=(instancing && !(render.flag()&VTX_SKIN)); // can do instancing only if mesh doesn't have skinning (otherwise a skinned shader is set which does not use instancing)
  224. Sh.h_VtxHeightmap->setConditional(mesh._vtx_heightmap);
  225. for(SolidShaderMaterialMeshInstance *instance=&SolidShaderMaterialMeshInstances[shader_material_mesh->first_instance]; ; )
  226. {
  227. SetViewMatrix (instance->view_matrix ); Sh.h_ViewMatrix->setChanged();
  228. SetFastVel (instance->vel );
  229. SetFastAngVel (instance->ang_vel_shader );
  230. _SetHighlight (instance->highlight );
  231. SetShaderParamChanges(instance->shader_param_changes);
  232. D.stencilRef (instance->stencil_value );
  233. Int instances=1;
  234. if( instancing_mesh)for(; instance->next_instance>=0; )
  235. {
  236. SolidShaderMaterialMeshInstance &next=SolidShaderMaterialMeshInstances[instance->next_instance];
  237. if(next.highlight ==instance->highlight
  238. && next.shader_param_changes==instance->shader_param_changes
  239. && next.stencil_value ==instance->stencil_value
  240. #if !PER_INSTANCE_VEL
  241. && next.vel==instance->vel
  242. #endif
  243. #if !PER_INSTANCE_ANG_VEL
  244. && next.ang_vel_shader==instance->ang_vel_shader
  245. #endif
  246. )
  247. {
  248. instance=&next;
  249. SetViewMatrix(next.view_matrix, instances);
  250. #if PER_INSTANCE_VEL
  251. SetFastVel(instances, next.vel);
  252. #endif
  253. #if PER_INSTANCE_ANG_VEL
  254. not supported
  255. #endif
  256. if(++instances>=MAX_MATRIX_INSTANCE)break;
  257. }else break;
  258. }
  259. SetMatrixCount(instances); shader.commit(); if(instances>1)render.drawInstanced(instances);else render.drawFull();
  260. if(instance->next_instance<0)break;
  261. instance=&SolidShaderMaterialMeshInstances[instance->next_instance];
  262. }
  263. if(shader_material_mesh->next_shader_material_mesh<0)break;
  264. shader_material_mesh=&ShaderMaterialMeshes[shader_material_mesh->next_shader_material_mesh];
  265. #if !SUPPORT_MATERIAL_CHANGE_IN_RENDERING
  266. variation =&shader_material_mesh->Variation();
  267. #endif
  268. }
  269. SetShaderParamChanges(); // this must be called here before setting new shader params, because we may have some 'ShaderParamRestore' that we need to apply before any new shader params, for example if we don't call it here, and a new material is set, and we process 'SetShaderParamChanges' later, then it could restore the material values that are now old because new material was already set
  270. ShaderEnd(); // needs to be called after every 'commitTex'
  271. if(shader_material->next_shader_material<0)break;
  272. shader_material=&ShaderMaterials[shader_material->next_shader_material];
  273. }
  274. }
  275. D.stencilRef(0);
  276. EndPrecomputedViewMatrix();
  277. // skeleton
  278. EnableSkinning();
  279. FREPA(SkeletonSolidInstances)
  280. {
  281. SkeletonInstance &skel=SkeletonSolidInstances[i]; skel.unlinkSolid(); skel.anim_skel->setMatrix();
  282. for(SkeletonShader *skel_shader=&skel.skel_shader; ; )
  283. {
  284. Shader &shader=skel_shader->shader->getShader(forward); shader.start();
  285. for(SkeletonShaderMaterial *skel_shader_material=&skel_shader->material; ; )
  286. {
  287. C Material &material=*skel_shader_material->material; material.setSolid(); D.cull(material.cull); shader.commitTex();
  288. Bool shader_params_changed=true;
  289. for(SkeletonSolidShaderMaterialMeshInstance *instance=&SkeletonSolidShaderMaterialMeshInstances[skel_shader_material->first_mesh_instance]; ; )
  290. {
  291. shader_params_changed|=_SetHighlight (instance->highlight);
  292. shader_params_changed|= SetShaderParamChanges(instance->shader_param_changes);
  293. if(shader_params_changed){shader_params_changed=false; shader.commit();}
  294. instance->mesh->set().draw(); // for skeleton have to use 'draw' instead of 'drawFull'
  295. if(instance->next_instance<0)break;
  296. instance=&SkeletonSolidShaderMaterialMeshInstances[instance->next_instance];
  297. }
  298. SetShaderParamChanges(); // this must be called here before setting new shader params, because we may have some 'ShaderParamRestore' that we need to apply before any new shader params, for example if we don't call it here, and a new material is set, and we process 'SetShaderParamChanges' later, then it could restore the material values that are now old because new material was already set
  299. ShaderEnd(); // needs to be called after every 'commitTex'
  300. if(skel_shader_material->next_skeleton_shader_material<0)break;
  301. skel_shader_material=&SkeletonShaderMaterials[skel_shader_material->next_skeleton_shader_material];
  302. }
  303. if(skel_shader->next_skeleton_shader<0)break;
  304. skel_shader=&SkeletonShaders[skel_shader->next_skeleton_shader];
  305. }
  306. }
  307. // cloth
  308. if(SolidClothInstances.elms())
  309. {
  310. SetOneMatrix ();
  311. SetFastAngVel ();
  312. SetVtxNrmMulAdd(false);
  313. {
  314. SetDefaultVAO(); D.vf(VI._vf3D_cloth.vf); // OpenGL requires setting 1)VAO 2)VB+IB 3)VF
  315. FREPA(SolidClothInstances)
  316. {
  317. ClothInstance &ci=SolidClothInstances[i];
  318. Shader &shader = ci.shader ->getShader(forward);
  319. C Material &material=*ci.material; material.setSolid(); D.cull(material.cull);
  320. SetFastVel (ci.vel );
  321. _SetHighlight(ci.highlight);
  322. shader.begin(); ci.cloth->_drawPhysical();
  323. ShaderEnd();
  324. }
  325. }
  326. SetVtxNrmMulAdd(true);
  327. }
  328. BeginPrecomputedViewMatrix();
  329. // multi material (at last stage, because these are usually heightmaps on the bottom)
  330. #define MULTI_MATERIAL_INSTANCING 0 // these are heightmaps, and we never need instancing for them because they're drawn only 1 time each
  331. SetMatrixCount();
  332. DisableSkinning();
  333. FREPA(MultiMaterialShaderDraws)
  334. {
  335. ShaderDraw &shader_draw=MultiMaterialShaderDraws[i]; shader_draw.unlink(); // have to unlink 'shader_draw' instead of 'shader' (because it can be FRST)
  336. Shader &shader =shader_draw.shader->getShader(forward); shader.start();
  337. for(ShaderMaterial *shader_material=&ShaderMaterials[shader_draw.first_shader_material]; ; )
  338. {
  339. ShaderMaterialMesh *shader_material_mesh=&ShaderMaterialMeshes[shader_material->first_shader_material_mesh];
  340. #if SUPPORT_MATERIAL_CHANGE_IN_RENDERING
  341. UniqueMultiMaterialData &umm =*shader_material->umm; umm.unlink();
  342. #else
  343. UniqueMultiMaterialData &umm =*shader_material_mesh->mesh->_umm; umm.unlink();
  344. #endif
  345. C UniqueMultiMaterialKey &umm_key =UniqueMultiMaterialMap.dataInMapToKey(umm);
  346. Bool cull=true;
  347. if(C Material *m=umm_key.m[0]){m->setMulti(0); cull&=m->cull;}else{MaterialDefault.setMulti(0); cull&=MaterialDefault.cull;}
  348. if(C Material *m=umm_key.m[1]){m->setMulti(1); cull&=m->cull;}
  349. if(C Material *m=umm_key.m[2]){m->setMulti(2); cull&=m->cull;}
  350. if(C Material *m=umm_key.m[3]){m->setMulti(3); cull&=m->cull;}
  351. D.cull(cull); shader.commitTex();
  352. for(;;)
  353. {
  354. C MeshPart &mesh =*shader_material_mesh->mesh;
  355. C MeshRender &render = mesh.render.set();
  356. #if SUPPORT_MATERIAL_CHANGE_IN_RENDERING
  357. mesh.unlinkSolid();
  358. #else
  359. C MeshPart::Variation &variation= shader_material_mesh->Variation(); variation.unlinkSolid();
  360. #endif
  361. #if MULTI_MATERIAL_INSTANCING
  362. C Bool instancing_mesh=(instancing && !(render.flag()&VTX_SKIN)); // can do instancing only if mesh doesn't have skinning (otherwise a skinned shader is set which does not use instancing)
  363. #endif
  364. Sh.h_VtxHeightmap->setConditional(mesh._vtx_heightmap);
  365. for(SolidShaderMaterialMeshInstance *instance=&SolidShaderMaterialMeshInstances[shader_material_mesh->first_instance]; ; )
  366. {
  367. SetViewMatrix (instance->view_matrix ); Sh.h_ViewMatrix->setChanged();
  368. SetFastVel (instance->vel );
  369. SetFastAngVel (instance->ang_vel_shader );
  370. _SetHighlight (instance->highlight );
  371. SetShaderParamChanges(instance->shader_param_changes);
  372. D.stencilRef (instance->stencil_value );
  373. Int instances=1;
  374. #if MULTI_MATERIAL_INSTANCING
  375. if( instancing_mesh)for(; instance->next_instance>=0; )
  376. {
  377. SolidShaderMaterialMeshInstance &next=SolidShaderMaterialMeshInstances[instance->next_instance];
  378. if(next.highlight ==instance->highlight
  379. && next.shader_param_changes==instance->shader_param_changes
  380. && next.stencil_value ==instance->stencil_value
  381. #if !PER_INSTANCE_VEL
  382. && next.vel==instance->vel
  383. #endif
  384. #if !PER_INSTANCE_ANG_VEL
  385. && next.ang_vel_shader==instance->ang_vel_shader
  386. #endif
  387. )
  388. {
  389. instance=&next;
  390. SetViewMatrix(next.view_matrix, instances);
  391. #if PER_INSTANCE_VEL
  392. SetFastVel(instances, next.vel);
  393. #endif
  394. #if PER_INSTANCE_ANG_VEL
  395. not supported
  396. #endif
  397. if(++instances>=MAX_MATRIX_INSTANCE)break;
  398. }else break;
  399. }
  400. SetMatrixCount(instances);
  401. #endif
  402. shader.commit(); if(instances>1)render.drawInstanced(instances);else render.drawFull();
  403. if(instance->next_instance<0)break;
  404. instance=&SolidShaderMaterialMeshInstances[instance->next_instance];
  405. }
  406. if(shader_material_mesh->next_shader_material_mesh<0)break;
  407. shader_material_mesh=&ShaderMaterialMeshes[shader_material_mesh->next_shader_material_mesh];
  408. }
  409. SetShaderParamChanges(); // this must be called here before setting new shader params, because we may have some 'ShaderParamRestore' that we need to apply before any new shader params, for example if we don't call it here, and a new material is set, and we process 'SetShaderParamChanges' later, then it could restore the material values that are now old because new material was already set
  410. ShaderEnd(); // needs to be called after every 'commitTex'
  411. if(shader_material->next_shader_material<0)break;
  412. shader_material=&ShaderMaterials[shader_material->next_shader_material];
  413. }
  414. }
  415. D.stencilRef(0);
  416. // finish
  417. _SetHighlight(TRANSPARENT);
  418. EndPrecomputedViewMatrix();
  419. FREPAO(SolidObjects)->drawSolid();
  420. }
  421. void ClearSolidInstances()
  422. {
  423. MaterialShaders .clear();
  424. ShaderDraws .clear(); MultiMaterialShaderDraws.clear();
  425. ShaderMaterials .clear();
  426. ShaderMaterialMeshes .clear();
  427. SolidShaderMaterialMeshInstances.clear();
  428. SkeletonShaders .clear();
  429. SkeletonShaderMaterials .clear();
  430. SkeletonSolidShaderMaterialMeshInstances.clear();
  431. SkeletonSolidInstances .clear();
  432. SolidClothInstances.clear();
  433. SolidObjects.clear();
  434. }
  435. void DrawSolidInstances()
  436. {
  437. if(Renderer._cur_type!=RT_FORWARD)DrawSolidInstances(false);
  438. else DrawSolidInstances(true );
  439. }
  440. /******************************************************************************/
  441. // AMBIENT
  442. /******************************************************************************/
  443. static Int Compare(C AmbientInstance &a, C AmbientInstance &b)
  444. {
  445. #if SUPPORT_MATERIAL_CHANGE_IN_RENDERING
  446. if(Int c=ComparePtr(a.shader , b.shader ))return c;
  447. if(Int c=ComparePtr(a.material , b.material ))return c;
  448. #else
  449. if(Int c=ComparePtr(a.variation->shader[RM_AMBIENT], b.variation->shader[RM_AMBIENT]))return c;
  450. if(Int c=ComparePtr(a.variation->material() , b.variation->material() ))return c;
  451. #endif
  452. if(Int c=ComparePtr(a.mesh , b.mesh ))return c;
  453. return 0;
  454. }
  455. static Int Compare(C SkeletonAmbientInstance &a, C SkeletonAmbientInstance &b)
  456. {
  457. if(Int c=ComparePtr(a.anim_skel , b.anim_skel ))return c;
  458. #if SUPPORT_MATERIAL_CHANGE_IN_RENDERING
  459. if(Int c=ComparePtr(a.shader , b.shader ))return c;
  460. if(Int c=ComparePtr(a.material , b.material ))return c;
  461. #else
  462. if(Int c=ComparePtr(a.variation->shader[RM_AMBIENT], b.variation->shader[RM_AMBIENT]))return c;
  463. if(Int c=ComparePtr(a.variation->material() , b.variation->material() ))return c;
  464. #endif
  465. if(Int c=ComparePtr(a.mesh , b.mesh ))return c;
  466. return 0;
  467. }
  468. void SortAmbientInstances()
  469. {
  470. #if SUPPORT_MATERIAL_AMBIENT
  471. AmbientInstances.sort(Compare);
  472. SkeletonAmbientInstances.sort(Compare);
  473. #endif
  474. }
  475. void DrawAmbientInstances()
  476. {
  477. #if SUPPORT_MATERIAL_AMBIENT
  478. SetViewOffset();
  479. BeginPrecomputedViewMatrix();
  480. SetMatrixCount();
  481. DisableSkinning();
  482. FREPA(AmbientInstances)
  483. {
  484. // TODO: this could be optimized to group in state changes (shader->material->mesh->instance) and allow instancing, this is already sorted, we would just need to detect changes between this and next instance
  485. C AmbientInstance &instance = AmbientInstances[i];
  486. C MeshPart &mesh =*instance.mesh;
  487. #if SUPPORT_MATERIAL_CHANGE_IN_RENDERING
  488. Shader &shader =*instance.shader;
  489. C Material &material =*instance.material;
  490. #else
  491. C MeshPart::Variation &variation= instance.Variation();
  492. Shader &shader =*variation.shader[RM_AMBIENT];
  493. C Material &material = variation.getMaterial();
  494. #endif
  495. material.setAmbient(); D.cull(material.cull);
  496. SetViewMatrix (instance.view_matrix ); Sh.h_ViewMatrix->setChanged();
  497. SetShaderParamChanges(instance.shader_param_changes);
  498. shader.begin(); mesh.render.set().drawFull(); ShaderEnd();
  499. SetShaderParamChanges(); // this must be called here before setting new shader params, because we may have some 'ShaderParamRestore' that we need to apply before any new shader params, for example if we don't call it here, and a new material is set, and we process 'SetShaderParamChanges' later, then it could restore the material values that are now old because new material was already set
  500. }
  501. EndPrecomputedViewMatrix();
  502. EnableSkinning();
  503. FREPA(SkeletonAmbientInstances)
  504. {
  505. // TODO: this could be optimized to group in state changes (shader->material->mesh->instance), this is already sorted, we would just need to detect changes between this and next instance
  506. C SkeletonAmbientInstance &instance = SkeletonAmbientInstances[i];
  507. C MeshPart &mesh =*instance.mesh;
  508. #if SUPPORT_MATERIAL_CHANGE_IN_RENDERING
  509. Shader &shader =*instance.shader;
  510. C Material &material =*instance.material;
  511. #else
  512. C MeshPart::Variation &variation= instance.Variation();
  513. Shader &shader =*variation.shader[RM_AMBIENT];
  514. C Material &material = variation.getMaterial();
  515. #endif
  516. material.setAmbient(); D.cull(material.cull);
  517. instance.anim_skel->setMatrix();
  518. SetShaderParamChanges(instance.shader_param_changes);
  519. shader.begin(); mesh.render.set().draw(); ShaderEnd(); // for skeleton have to use 'draw' instead of 'drawFull'
  520. SetShaderParamChanges(); // this must be called here before setting new shader params, because we may have some 'ShaderParamRestore' that we need to apply before any new shader params, for example if we don't call it here, and a new material is set, and we process 'SetShaderParamChanges' later, then it could restore the material values that are now old because new material was already set
  521. }
  522. #endif
  523. FREPAO(AmbientObjects)->drawAmbient();
  524. }
  525. void ClearAmbientInstances()
  526. {
  527. AmbientInstances.clear();
  528. SkeletonAmbientInstances.clear();
  529. AmbientObjects .clear();
  530. }
  531. /******************************************************************************/
  532. // SHADOW
  533. /******************************************************************************/
  534. static Int MaterialShadersNum, ShaderDrawsNum, ShaderMaterialsNum, ShaderMaterialMeshesNum, SkeletonShadersNum, SkeletonShaderMaterialsNum;
  535. void PrepareShadowInstances()
  536. {
  537. // remember current number of elements in these containers (they may already have data in Forward renderer)
  538. MaterialShadersNum =MaterialShaders .elms();
  539. ShaderDrawsNum =ShaderDraws .elms();
  540. ShaderMaterialsNum =ShaderMaterials .elms();
  541. ShaderMaterialMeshesNum=ShaderMaterialMeshes.elms();
  542. SkeletonShadersNum =SkeletonShaders .elms();
  543. SkeletonShaderMaterialsNum=SkeletonShaderMaterials.elms();
  544. }
  545. void DrawShadowInstances()
  546. {
  547. // this doesn't require 'ViewOffset' and 'BeginPrecomputedViewMatrix' because shadows are drawn only 1 time, and not for each eye
  548. const Bool instancing=D.hwInstancing();
  549. // solid
  550. SetMatrixCount();
  551. DisableSkinning();
  552. for(Int i=ShaderDrawsNum; i<ShaderDraws.elms(); i++)
  553. {
  554. ShaderDraw &shader_draw=ShaderDraws[i]; shader_draw.unlink();
  555. Shader &shader =shader_draw.shader->getShader(false); shader.start();
  556. #if !SUPPORT_MATERIAL_CHANGE_IN_RENDERING
  557. Bool reuse_default_material=ReuseDefaultMaterialForNonSkinnedShadowShader(&shader);
  558. #endif
  559. for(ShaderMaterial *shader_material=&ShaderMaterials[shader_draw.first_shader_material]; ; )
  560. {
  561. ShaderMaterialMesh *shader_material_mesh=&ShaderMaterialMeshes[shader_material->first_shader_material_mesh];
  562. #if SUPPORT_MATERIAL_CHANGE_IN_RENDERING
  563. C Material &material =*shader_material->material;
  564. #else
  565. C MeshPart::Variation *variation =&shader_material_mesh->Variation(); // have to access 'variation' here, because we need it to access 'material' since we're not storing it in the 'ShaderMaterial'
  566. C Material &material = variation->getShadowMaterial(reuse_default_material);
  567. #endif
  568. material.unlinkShadow(); material.setShadow(); D.cull(material.cull); shader.commitTex();
  569. for(;;)
  570. {
  571. C MeshPart &mesh =*shader_material_mesh->mesh;
  572. C MeshRender &render= mesh.render.set();
  573. C Bool instancing_mesh=(instancing && !(render.flag()&VTX_SKIN)); // can do instancing only if mesh doesn't have skinning (otherwise a skinned shader is set which does not use instancing)
  574. #if SUPPORT_MATERIAL_CHANGE_IN_RENDERING
  575. mesh.unlinkShadow();
  576. #else
  577. variation->unlinkShadow();
  578. #endif
  579. for(ShadowShaderMaterialMeshInstance *instance=&ShadowShaderMaterialMeshInstances[shader_material_mesh->first_instance]; ; )
  580. {
  581. ViewMatrix[0] =instance->view_matrix ; Sh.h_ViewMatrix->setChanged(); // this doesn't need 'ViewOffset'
  582. SetShaderParamChanges(instance->shader_param_changes);
  583. Int instances=1;
  584. if( instancing_mesh)for(; instance->next_instance>=0; )
  585. {
  586. ShadowShaderMaterialMeshInstance &next=ShadowShaderMaterialMeshInstances[instance->next_instance];
  587. if(next.shader_param_changes==instance->shader_param_changes)
  588. {
  589. instance=&next;
  590. ViewMatrix[instances]=next.view_matrix; // this doesn't need 'ViewOffset'
  591. if(++instances>=MAX_MATRIX_INSTANCE)break;
  592. }else break;
  593. }
  594. SetMatrixCount(instances); shader.commit(); if(instances>1)render.drawInstanced(instances);else render.drawFull();
  595. if(instance->next_instance<0)break;
  596. instance=&ShadowShaderMaterialMeshInstances[instance->next_instance];
  597. }
  598. if(shader_material_mesh->next_shader_material_mesh<0)break;
  599. shader_material_mesh=&ShaderMaterialMeshes[shader_material_mesh->next_shader_material_mesh];
  600. #if !SUPPORT_MATERIAL_CHANGE_IN_RENDERING
  601. variation =&shader_material_mesh->Variation();
  602. #endif
  603. }
  604. SetShaderParamChanges(); // this must be called here before setting new shader params, because we may have some 'ShaderParamRestore' that we need to apply before any new shader params, for example if we don't call it here, and a new material is set, and we process 'SetShaderParamChanges' later, then it could restore the material values that are now old because new material was already set
  605. ShaderEnd(); // needs to be called after every 'commitTex'
  606. if(shader_material->next_shader_material<0)break;
  607. shader_material=&ShaderMaterials[shader_material->next_shader_material];
  608. }
  609. }
  610. // skeleton
  611. EnableSkinning();
  612. FREPA(SkeletonShadowInstances)
  613. {
  614. SkeletonInstance &skel=SkeletonShadowInstances[i]; skel.unlinkShadow(); skel.anim_skel->setMatrix();
  615. for(SkeletonShader *skel_shader=&skel.skel_shader; ; )
  616. {
  617. Shader &shader=skel_shader->shader->getShader(false); shader.start();
  618. for(SkeletonShaderMaterial *skel_shader_material=&skel_shader->material; ; )
  619. {
  620. C Material &material=*skel_shader_material->material; material.setShadow(); D.cull(material.cull); shader.commitTex();
  621. Bool shader_params_changed=true;
  622. for(SkeletonShaderMaterialMeshInstance *instance=&SkeletonShadowShaderMaterialMeshInstances[skel_shader_material->first_mesh_instance]; ; )
  623. {
  624. shader_params_changed|= SetShaderParamChanges(instance->shader_param_changes);
  625. if(shader_params_changed){shader_params_changed=false; shader.commit();}
  626. instance->mesh->set().draw(); // for skeleton have to use 'draw' instead of 'drawFull'
  627. if(instance->next_instance<0)break;
  628. instance=&SkeletonShadowShaderMaterialMeshInstances[instance->next_instance];
  629. }
  630. SetShaderParamChanges(); // this must be called here before setting new shader params, because we may have some 'ShaderParamRestore' that we need to apply before any new shader params, for example if we don't call it here, and a new material is set, and we process 'SetShaderParamChanges' later, then it could restore the material values that are now old because new material was already set
  631. ShaderEnd(); // needs to be called after every 'commitTex'
  632. if(skel_shader_material->next_skeleton_shader_material<0)break;
  633. skel_shader_material=&SkeletonShaderMaterials[skel_shader_material->next_skeleton_shader_material];
  634. }
  635. if(skel_shader->next_skeleton_shader<0)break;
  636. skel_shader=&SkeletonShaders[skel_shader->next_skeleton_shader];
  637. }
  638. }
  639. // we can't just clear all containers, because in Forward renderer there's still data needed for solid shaders which are processed after shadows, so restore to what we had before drawing shadows
  640. MaterialShaders .setNum(MaterialShadersNum);
  641. ShaderDraws .setNum( ShaderDrawsNum);
  642. ShaderMaterials .setNum( ShaderMaterialsNum);
  643. ShaderMaterialMeshes .setNum( ShaderMaterialMeshesNum);
  644. ShadowShaderMaterialMeshInstances.clear ();
  645. SkeletonShaders .setNum(SkeletonShadersNum);
  646. SkeletonShaderMaterials .setNum(SkeletonShaderMaterialsNum);
  647. SkeletonShadowShaderMaterialMeshInstances.clear();
  648. SkeletonShadowInstances .clear();
  649. // physical
  650. if(ShadowClothInstances.elms())
  651. {
  652. SetOneMatrix ();
  653. SetVtxNrmMulAdd(false);
  654. // cloth
  655. {
  656. SetDefaultVAO(); D.vf(VI._vf3D_cloth.vf); // OpenGL requires setting 1)VAO 2)VB+IB 3)VF
  657. FREPA(ShadowClothInstances)
  658. {
  659. ClothInstance &ci=ShadowClothInstances[i];
  660. Shader &shader = ci.shader ->asShader();
  661. C Material &material=*ci.material; material.setShadow(); D.cull(material.cull);
  662. shader.begin(); ci.cloth->_drawPhysical();
  663. ShaderEnd();
  664. }
  665. ShadowClothInstances.clear();
  666. }
  667. SetVtxNrmMulAdd(true);
  668. }
  669. }
  670. /******************************************************************************/
  671. // BLEND
  672. /******************************************************************************/
  673. Int Compare(C BlendInstance &a, C BlendInstance &b)
  674. {
  675. if(Int z=Compare (a.z , b.z ))return z;
  676. // compare other values in case 'z' is the same (which means the same object draws many parts with the same matrix, which may cause flickering)
  677. if(Int c=ComparePtr(a.s.shader , b.s.shader ))return c;
  678. if(Int c=ComparePtr(a.s.material, b.s.material))return c;
  679. if(Int c=ComparePtr(a.s.mesh , b.s.mesh ))return c;
  680. return 0;
  681. }
  682. void ClearBlendInstances()
  683. {
  684. BlendInstances .clear();
  685. SkeletonBlendShaders .clear();
  686. SkeletonBlendShaderMaterials .clear();
  687. SkeletonBlendShaderMaterialMeshInstances.clear();
  688. }
  689. void DrawBlendInstances()
  690. {
  691. SetViewOffset();
  692. EyeCache ec;
  693. const ALPHA_MODE alpha =(Renderer.fastCombine() ? ALPHA_BLEND : ALPHA_BLEND_FACTOR);
  694. const Bool instancing=D.hwInstancing();
  695. D.depth(true );
  696. D.alpha(alpha);
  697. REPA(BlendInstances) // go from back to start
  698. {
  699. BlendInstance *object=&BlendInstances[i]; switch(object->type)
  700. {
  701. case BlendInstance::SOLID:
  702. {
  703. ec.BeginPrecomputedViewMatrix();
  704. DisableSkinning();
  705. // this doesn't use velocities
  706. Shader &shader =*object->s.shader ; shader.start();
  707. solid_shader:
  708. C Material &material=*object->s.material; material.setBlend(); D.cull(material.cull); D.depthWrite(material._depth_write); Renderer.needDepthTest(); shader.commitTex(); // !! 'needDepthTest' after 'depthWrite' !!
  709. solid_shader_material:
  710. C MeshRender &render = object->s.mesh->render.set();
  711. _SetHighlight (object->s.highlight);
  712. D.stencil (object->s.stencil_mode);
  713. SetShaderParamChanges(object->s.shader_param_changes);
  714. SetViewMatrix (object->s.view_matrix); Sh.h_ViewMatrix->setChanged();
  715. const Bool instancing_mesh=(instancing && !(render.flag()&VTX_SKIN)); // can do instancing only if mesh doesn't have skinning (otherwise a skinned shader is set which does not use instancing)
  716. Int instances=1;
  717. for(; i; ) // if there's next one
  718. {
  719. BlendInstance &next=BlendInstances[i-1]; // grab next
  720. if(next.s.shader==&shader // same shader
  721. //&& next.type==BlendInstance::SOLID not needed since if the shader is the same, then type should be the same too, make debug assertion below just in case
  722. )
  723. {
  724. DEBUG_ASSERT(next.type==BlendInstance::SOLID, "Blend Instance type");
  725. i--; // we will process this instance
  726. if(next.s.material==&material) // same material
  727. {
  728. if(&next.s.mesh->render==&render
  729. && next.s.highlight==Highlight
  730. && next.s.shader_param_changes==LastChanges
  731. && next.s.stencil_mode==D._stencil)
  732. {
  733. if(instancing_mesh)
  734. {
  735. if(!InRange(instances, MAX_MATRIX_INSTANCE)) // there's no room for this instance
  736. {
  737. SetMatrixCount(instances); shader.commit(); render.drawInstanced(instances); // draw what we have
  738. instances=0; Sh.h_ViewMatrix->setChanged(); // reset counter and mark as modified
  739. }
  740. SetViewMatrix(next.s.view_matrix, instances);
  741. instances++;
  742. }else
  743. {
  744. SetMatrixCount(); shader.commit(); render.drawFull(); // draw what we have
  745. SetViewMatrix(next.s.view_matrix); Sh.h_ViewMatrix->setChanged();
  746. }
  747. }else // we have the same shader/material, but different mesh/params
  748. {
  749. SetMatrixCount(instances); shader.commit(); if(instances>1)render.drawInstanced(instances);else render.drawFull(); // draw what we have
  750. object=&next; goto solid_shader_material;
  751. }
  752. }else // we have the same shader, but different material/mesh/params
  753. {
  754. SetMatrixCount(instances); shader.commit(); if(instances>1)render.drawInstanced(instances);else render.drawFull(); ShaderEnd(); // draw what we have, 'ShaderEnd' needs to be called after every 'commitTex'
  755. SetShaderParamChanges(); // this must be called here before setting new shader params, because we may have some 'ShaderParamRestore' that we need to apply before any new shader params, for example if we don't call it here, and a new material is set, and we process 'SetShaderParamChanges' later, then it could restore the material values that are now old because new material was already set
  756. object=&next; goto solid_shader;
  757. }
  758. }else break;
  759. }
  760. SetMatrixCount(instances); shader.commit(); if(instances>1)render.drawInstanced(instances);else render.drawFull();
  761. SetShaderParamChanges(); // this must be called here before setting new shader params, because we may have some 'ShaderParamRestore' that we need to apply before any new shader params, for example if we don't call it here, and a new material is set, and we process 'SetShaderParamChanges' later, then it could restore the material values that are now old because new material was already set
  762. ShaderEnd(); // needs to be called after every 'commitTex'
  763. }break;
  764. case BlendInstance::SOLID_BLST:
  765. {
  766. ec.BeginPrecomputedViewMatrix();
  767. DisableSkinning();
  768. Shader &shader = object->s.shader->asBlendShader(); shader.start();
  769. solid_blst_shader:
  770. C Material &material=*object->s.material; material.setBlend(); D.cull(material.cull); D.depthWrite(material._depth_write); Renderer.needDepthTest(); shader.commitTex(); // !! 'needDepthTest' after 'depthWrite' !!
  771. solid_blst_shader_material:
  772. C MeshRender &render = object->s.mesh->render.set();
  773. _SetHighlight (object->s.highlight);
  774. D.stencil (object->s.stencil_mode);
  775. SetShaderParamChanges(object->s.shader_param_changes);
  776. SetViewMatrix (object->s.view_matrix); Sh.h_ViewMatrix->setChanged();
  777. SetFastVel (object->s.vel);
  778. SetFastAngVel (object->s.ang_vel_shader);
  779. const Bool instancing_mesh=(instancing && !(render.flag()&VTX_SKIN)); // can do instancing only if mesh doesn't have skinning (otherwise a skinned shader is set which does not use instancing)
  780. Int instances=1;
  781. for(; i; ) // if there's next one
  782. {
  783. BlendInstance &next=BlendInstances[i-1]; // grab next
  784. if(next.s.blst==object->s.blst // same shader
  785. //&& next.type==BlendInstance::SOLID_BLST not needed since if the shader is the same, then type should be the same too, make debug assertion below just in case
  786. )
  787. {
  788. DEBUG_ASSERT(next.type==BlendInstance::SOLID_BLST, "Blend Instance type");
  789. i--; // we will process this instance
  790. if(next.s.material==&material) // same material
  791. {
  792. if(&next.s.mesh->render==&render
  793. #if !PER_INSTANCE_VEL
  794. && next.s.vel==object->s.vel
  795. #endif
  796. #if !PER_INSTANCE_ANG_VEL
  797. && next.s.ang_vel_shader==object->s.ang_vel_shader
  798. #endif
  799. && next.s.highlight==Highlight
  800. && next.s.shader_param_changes==LastChanges
  801. && next.s.stencil_mode==D._stencil)
  802. {
  803. if(instancing_mesh)
  804. {
  805. if(!InRange(instances, MAX_MATRIX_INSTANCE)) // there's no room for this instance
  806. {
  807. SetMatrixCount(instances); shader.commit(); render.drawInstanced(instances); // draw what we have
  808. instances=0; Sh.h_ViewMatrix->setChanged(); // reset counter and mark as modified
  809. }
  810. SetViewMatrix(next.s.view_matrix, instances);
  811. #if PER_INSTANCE_VEL
  812. SetFastVel(instances, next.s.vel);
  813. #endif
  814. #if PER_INSTANCE_ANG_VEL
  815. not supported
  816. #endif
  817. instances++;
  818. }else
  819. {
  820. SetMatrixCount(); shader.commit(); render.drawFull(); // draw what we have
  821. SetViewMatrix (next.s.view_matrix); Sh.h_ViewMatrix->setChanged();
  822. SetFastVel (next.s.vel);
  823. SetFastAngVel (next.s.ang_vel_shader);
  824. }
  825. }else // we have the same shader/material, but different mesh/params
  826. {
  827. SetMatrixCount(instances); shader.commit(); if(instances>1)render.drawInstanced(instances);else render.drawFull(); // draw what we have
  828. object=&next; goto solid_blst_shader_material;
  829. }
  830. }else // we have the same shader, but different material/mesh/params
  831. {
  832. SetMatrixCount(instances); shader.commit(); if(instances>1)render.drawInstanced(instances);else render.drawFull(); ShaderEnd(); // draw what we have, 'ShaderEnd' needs to be called after every 'commitTex'
  833. SetShaderParamChanges(); // this must be called here before setting new shader params, because we may have some 'ShaderParamRestore' that we need to apply before any new shader params, for example if we don't call it here, and a new material is set, and we process 'SetShaderParamChanges' later, then it could restore the material values that are now old because new material was already set
  834. object=&next; goto solid_blst_shader;
  835. }
  836. }else break;
  837. }
  838. SetMatrixCount(instances); shader.commit(); if(instances>1)render.drawInstanced(instances);else render.drawFull();
  839. SetShaderParamChanges(); // this must be called here before setting new shader params, because we may have some 'ShaderParamRestore' that we need to apply before any new shader params, for example if we don't call it here, and a new material is set, and we process 'SetShaderParamChanges' later, then it could restore the material values that are now old because new material was already set
  840. ShaderEnd(); // needs to be called after every 'commitTex'
  841. }break;
  842. case BlendInstance::SOLID_FUR:
  843. {
  844. ec.BeginPrecomputedViewMatrix();
  845. DisableSkinning();
  846. Flt scale=object->s.view_matrix.x.length()/D._view_active.fov_tan.y; if(FovPerspective(D.viewFovMode()))scale/=object->s.view_matrix.pos.z;
  847. D.stencil (STENCIL_NONE);
  848. SetMatrixCount ();
  849. SetFurVelCount ();
  850. SetViewMatrix (object->s.view_matrix); Sh.h_ViewMatrix->setChanged();
  851. SetVelFur (object->s.view_matrix, object->s.vel);
  852. _SetHighlight (object->s.highlight);
  853. SetShaderParamChanges(object->s.shader_param_changes);
  854. Shader &shader =*object->s.shader;
  855. C Material &material=*object->s.material; material.setBlend(); D.cull(material.cull); D.depthWrite(material._depth_write); Renderer.needDepthTest(); // !! 'needDepthTest' after 'depthWrite' !!
  856. C MeshRender &render = object->s.mesh->render.set();
  857. shader.begin(); DrawFur(render, shader, scale);
  858. SetShaderParamChanges(); // this must be called here before setting new shader params, because we may have some 'ShaderParamRestore' that we need to apply before any new shader params, for example if we don't call it here, and a new material is set, and we process 'SetShaderParamChanges' later, then it could restore the material values that are now old because new material was already set
  859. ShaderEnd();
  860. }break;
  861. case BlendInstance::SKELETON:
  862. {
  863. ec.EndPrecomputedViewMatrix();
  864. EnableSkinning();
  865. SkeletonBlendInstance &skel=object->skeleton; skel.unlinkBlend(); skel.anim_skel->setMatrix(); Bool fur_set=false; Flt fur_scale;
  866. for(SkeletonBlendShader *skel_shader=&skel.skel_shader; ; )
  867. {
  868. if(skel_shader->type==BlendInstance::SOLID_FUR && !fur_set)
  869. {
  870. fur_set=true; skel.anim_skel->setFurVel(); // !! needs to be called before 'shader.start' !!
  871. fur_scale=skel.anim_skel->matrix().x.length()/D._view_active.fov_tan.y; if(FovPerspective(D.viewFovMode()))fur_scale/=DistPointPlane(skel.anim_skel->pos(), CamMatrix.pos, CamMatrix.z);
  872. }
  873. Shader &shader=skel_shader->shader->getBlendShader(skel_shader->type==BlendInstance::SOLID_BLST); shader.start();
  874. for(SkeletonShaderMaterial *skel_shader_material=&skel_shader->material; ; )
  875. {
  876. C Material &material=*skel_shader_material->material; material.setBlend(); D.cull(material.cull); D.depthWrite(material._depth_write); Renderer.needDepthTest(); shader.commitTex(); // !! 'needDepthTest' after 'depthWrite' !!
  877. Bool shader_params_changed=true;
  878. for(SkeletonBlendShaderMaterialMeshInstance *instance=&SkeletonBlendShaderMaterialMeshInstances[skel_shader_material->first_mesh_instance]; ; )
  879. {
  880. D.stencil(instance->stencil_mode);
  881. shader_params_changed|=_SetHighlight (instance->highlight);
  882. shader_params_changed|= SetShaderParamChanges(instance->shader_param_changes);
  883. if(shader_params_changed){shader_params_changed=false; shader.commit();}
  884. instance->mesh->set();
  885. if(skel_shader->type!=BlendInstance::SOLID_FUR)instance->mesh->draw(); // for skeleton have to use 'draw' instead of 'drawFull'
  886. else DrawFur(*instance->mesh, shader, fur_scale);
  887. if(instance->next_instance<0)break;
  888. instance=&SkeletonBlendShaderMaterialMeshInstances[instance->next_instance];
  889. }
  890. SetShaderParamChanges(); // this must be called here before setting new shader params, because we may have some 'ShaderParamRestore' that we need to apply before any new shader params, for example if we don't call it here, and a new material is set, and we process 'SetShaderParamChanges' later, then it could restore the material values that are now old because new material was already set
  891. ShaderEnd(); // needs to be called after every 'commitTex'
  892. if(skel_shader_material->next_skeleton_shader_material<0)break;
  893. skel_shader_material=&SkeletonBlendShaderMaterials[skel_shader_material->next_skeleton_shader_material];
  894. }
  895. if(skel_shader->next_skeleton_shader<0)break;
  896. skel_shader=&SkeletonBlendShaders[skel_shader->next_skeleton_shader];
  897. }
  898. }break;
  899. case BlendInstance::BLEND_OBJ : ec.EndPrecomputedViewMatrix(); D.stencil(STENCIL_NONE); _SetHighlight(TRANSPARENT); object->blend_obj -> drawBlend(); D.alpha(alpha); D.depth(true); break;
  900. case BlendInstance:: GAME_OBJ : ec.EndPrecomputedViewMatrix(); D.stencil(STENCIL_NONE); _SetHighlight(TRANSPARENT); object-> game_obj -> drawBlend(); D.alpha(alpha); D.depth(true); break;
  901. case BlendInstance:: GAME_AREA: ec.EndPrecomputedViewMatrix(); D.stencil(STENCIL_NONE); _SetHighlight(TRANSPARENT); object-> game_area->customDrawBlend(); D.alpha(alpha); D.depth(true); break;
  902. }
  903. }
  904. // finish
  905. ec.EndPrecomputedViewMatrix();
  906. D.depthWrite(true);
  907. D.stencil (STENCIL_NONE);
  908. _SetHighlight(TRANSPARENT);
  909. }
  910. /******************************************************************************/
  911. // PALETTE
  912. /******************************************************************************/
  913. void DrawPaletteObjects()
  914. {
  915. FREPAO(PaletteObjects)-> drawPalette();
  916. FREPAO(PaletteAreas )->customDrawPalette();
  917. }
  918. void DrawPalette1Objects()
  919. {
  920. FREPAO(Palette1Objects)-> drawPalette1();
  921. FREPAO(Palette1Areas )->customDrawPalette1();
  922. }
  923. /******************************************************************************/
  924. // OVERLAY
  925. /******************************************************************************/
  926. void DrawOverlayObjects()
  927. {
  928. FREPAO(OverlayObjects)->drawOverlay();
  929. }
  930. /******************************************************************************/
  931. // OUTLINE
  932. /******************************************************************************/
  933. void DrawOutlineObjects()
  934. {
  935. FREPAO(OutlineObjects)->drawOutline();
  936. }
  937. /******************************************************************************/
  938. // BEHIND
  939. /******************************************************************************/
  940. void DrawBehindObjects()
  941. {
  942. FREPAO(BehindObjects)->drawBehind();
  943. }
  944. /******************************************************************************/
  945. // MANAGE
  946. /******************************************************************************/
  947. void ShutInstances()
  948. {
  949. MaterialShaders .del();
  950. ShaderDraws .del();
  951. MultiMaterialShaderDraws .del();
  952. ShaderMaterials .del();
  953. ShaderMaterialMeshes .del();
  954. SolidShaderMaterialMeshInstances.del();
  955. ShadowShaderMaterialMeshInstances.del();
  956. AmbientInstances.del();
  957. SkeletonShaders .del();
  958. SkeletonBlendShaders .del();
  959. SkeletonShaderMaterials .del();
  960. SkeletonBlendShaderMaterials .del();
  961. SkeletonShadowShaderMaterialMeshInstances.del();
  962. SkeletonSolidShaderMaterialMeshInstances .del();
  963. SkeletonBlendShaderMaterialMeshInstances .del();
  964. SkeletonSolidInstances .del();
  965. SkeletonShadowInstances .del();
  966. SkeletonAmbientInstances .del();
  967. BlendInstances.del();
  968. SolidClothInstances.del(); ShadowClothInstances.del();
  969. PaletteObjects.del(); Palette1Objects.del(); OverlayObjects.del(); SolidObjects.del(); AmbientObjects.del(); OutlineObjects.del(); BehindObjects.del();
  970. PaletteAreas .del(); Palette1Areas .del();
  971. }
  972. void InitInstances()
  973. {
  974. //MaterialShaders .reserve(16); no need because this is used only in special cases where materials use more than 1 shader
  975. ShaderDraws .reserve(16);
  976. MultiMaterialShaderDraws .reserve( 4);
  977. ShaderMaterials .reserve(16);
  978. ShaderMaterialMeshes .reserve(16);
  979. SolidShaderMaterialMeshInstances.reserve(16);
  980. ShadowShaderMaterialMeshInstances.reserve(16);
  981. SkeletonShaders .reserve(16);
  982. SkeletonBlendShaders .reserve(16);
  983. SkeletonShaderMaterials .reserve(16);
  984. SkeletonBlendShaderMaterials .reserve(16);
  985. SkeletonShadowShaderMaterialMeshInstances.reserve(16);
  986. SkeletonSolidShaderMaterialMeshInstances .reserve(16);
  987. SkeletonBlendShaderMaterialMeshInstances .reserve(16);
  988. SkeletonSolidInstances .reserve(16);
  989. SkeletonShadowInstances .reserve(16);
  990. BlendInstances .reserve(16);
  991. }
  992. void ClearInstances()
  993. {
  994. Renderer._fur_is=false;
  995. // unlink default materials because shadow draws may reuse them
  996. MaterialDefault .unlink();
  997. MaterialDefaultNoCull.unlink();
  998. #if SUPPORT_EARLY_Z
  999. ClearEarlyZInstances();
  1000. #endif
  1001. MaterialShaders .clear();
  1002. REPAO( ShaderDraws ).unlink(); ShaderDraws .clear();
  1003. REPAO(MultiMaterialShaderDraws ).unlink(); MultiMaterialShaderDraws .clear();
  1004. REPAO( ShaderMaterials ).unlink(); ShaderMaterials .clear(); // !! unlink before 'ShaderMaterialMeshes' !! because 'ShaderMaterial.unlink' makes use of 'ShaderMaterialMeshes'
  1005. REPAO( ShaderMaterialMeshes).unlink(); ShaderMaterialMeshes .clear(); // !! unlink after 'ShaderMaterials' !!
  1006. SolidShaderMaterialMeshInstances.clear();
  1007. ShadowShaderMaterialMeshInstances.clear();
  1008. AmbientInstances.clear();
  1009. SkeletonShaders .clear();
  1010. SkeletonBlendShaders .clear();
  1011. SkeletonShaderMaterials .clear();
  1012. SkeletonBlendShaderMaterials .clear();
  1013. SkeletonShadowShaderMaterialMeshInstances.clear();
  1014. SkeletonSolidShaderMaterialMeshInstances .clear();
  1015. SkeletonBlendShaderMaterialMeshInstances .clear();
  1016. REPAO(SkeletonSolidInstances ).unlinkSolid (); SkeletonSolidInstances .clear();
  1017. REPAO(SkeletonShadowInstances).unlinkShadow(); SkeletonShadowInstances .clear();
  1018. SkeletonAmbientInstances.clear();
  1019. REPAO(BlendInstances).unlink(); BlendInstances.clear();
  1020. SolidClothInstances.clear(); ShadowClothInstances.clear();
  1021. PaletteObjects.clear(); Palette1Objects.clear(); OverlayObjects.clear(); SolidObjects.clear(); AmbientObjects.clear(); OutlineObjects.clear(); BehindObjects.clear();
  1022. PaletteAreas .clear(); Palette1Areas .clear();
  1023. #if DEBUG && 0
  1024. #pragma message("!! Warning: Use this only for debugging !!")
  1025. Materials. lock(); REPA(Materials)DYNAMIC_ASSERT(Materials.lockedData(i).canBeRemoved(), "Material still has some instance references after rendering finished");
  1026. Materials.unlock();
  1027. #endif
  1028. }
  1029. /******************************************************************************/
  1030. }
  1031. /******************************************************************************/