babylon.renderingGroup.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. module BABYLON {
  2. export class RenderingGroup {
  3. private _scene: Scene
  4. private _opaqueSubMeshes = new BABYLON.SmartArray<SubMesh>(256);
  5. private _transparentSubMeshes = new BABYLON.SmartArray<SubMesh>(256);
  6. private _alphaTestSubMeshes = new BABYLON.SmartArray<SubMesh>(256);
  7. private _activeVertices: number;
  8. constructor(public index: number, scene: Scene) {
  9. this._scene = scene;
  10. }
  11. public render(customRenderFunction: (opaqueSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, beforeTransparents: () => void) => void,
  12. beforeTransparents): boolean {
  13. if (customRenderFunction) {
  14. customRenderFunction(this._opaqueSubMeshes, this._alphaTestSubMeshes, this._transparentSubMeshes, beforeTransparents);
  15. return true;
  16. }
  17. if (this._opaqueSubMeshes.length === 0 && this._alphaTestSubMeshes.length === 0 && this._transparentSubMeshes.length === 0) {
  18. return false;
  19. }
  20. var engine = this._scene.getEngine();
  21. // Opaque
  22. var subIndex: number;
  23. var submesh: SubMesh;
  24. for (subIndex = 0; subIndex < this._opaqueSubMeshes.length; subIndex++) {
  25. submesh = this._opaqueSubMeshes.data[subIndex];
  26. this._activeVertices += submesh.verticesCount;
  27. submesh.render();
  28. }
  29. // Alpha test
  30. engine.setAlphaTesting(true);
  31. for (subIndex = 0; subIndex < this._alphaTestSubMeshes.length; subIndex++) {
  32. submesh = this._alphaTestSubMeshes.data[subIndex];
  33. this._activeVertices += submesh.verticesCount;
  34. submesh.render();
  35. }
  36. engine.setAlphaTesting(false);
  37. if (beforeTransparents) {
  38. beforeTransparents();
  39. }
  40. // Transparent
  41. if (this._transparentSubMeshes.length) {
  42. // Sorting
  43. for (subIndex = 0; subIndex < this._transparentSubMeshes.length; subIndex++) {
  44. submesh = this._transparentSubMeshes.data[subIndex];
  45. submesh._alphaIndex = submesh.getMesh().alphaIndex;
  46. submesh._distanceToCamera = submesh.getBoundingInfo().boundingSphere.centerWorld.subtract(this._scene.activeCamera.position).length();
  47. }
  48. var sortedArray = this._transparentSubMeshes.data.slice(0, this._transparentSubMeshes.length);
  49. sortedArray.sort((a, b) => {
  50. // Alpha index first
  51. if (a._alphaIndex > b._alphaIndex) {
  52. return 1;
  53. }
  54. if (a._alphaIndex < b._alphaIndex) {
  55. return -1;
  56. }
  57. // Then distance to camera
  58. if (a._distanceToCamera < b._distanceToCamera) {
  59. return 1;
  60. }
  61. if (a._distanceToCamera > b._distanceToCamera) {
  62. return -1;
  63. }
  64. return 0;
  65. });
  66. // Rendering
  67. engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
  68. for (subIndex = 0; subIndex < sortedArray.length; subIndex++) {
  69. submesh = sortedArray[subIndex];
  70. this._activeVertices += submesh.verticesCount;
  71. submesh.render();
  72. }
  73. engine.setAlphaMode(BABYLON.Engine.ALPHA_DISABLE);
  74. }
  75. return true;
  76. }
  77. public prepare(): void {
  78. this._opaqueSubMeshes.reset();
  79. this._transparentSubMeshes.reset();
  80. this._alphaTestSubMeshes.reset();
  81. }
  82. public dispatch(subMesh: SubMesh): void {
  83. var material = subMesh.getMaterial();
  84. var mesh = subMesh.getMesh();
  85. if (material.needAlphaBlending() || mesh.visibility < 1.0 || mesh.hasVertexAlpha) { // Transparent
  86. this._transparentSubMeshes.push(subMesh);
  87. } else if (material.needAlphaTesting()) { // Alpha test
  88. this._alphaTestSubMeshes.push(subMesh);
  89. } else {
  90. this._opaqueSubMeshes.push(subMesh); // Opaque
  91. }
  92. }
  93. }
  94. }