babylon.depthRenderer.ts 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. module BABYLON {
  2. export class DepthRenderer {
  3. private _scene: Scene;
  4. private _depthMap: RenderTargetTexture;
  5. private _effect: Effect;
  6. private _cachedDefines: string;
  7. constructor(scene: Scene, type: number = Engine.TEXTURETYPE_FLOAT) {
  8. this._scene = scene;
  9. var engine = scene.getEngine();
  10. // Render target
  11. this._depthMap = new RenderTargetTexture("depthMap", { width: engine.getRenderWidth(), height: engine.getRenderHeight() }, this._scene, false, true, type);
  12. this._depthMap.wrapU = Texture.CLAMP_ADDRESSMODE;
  13. this._depthMap.wrapV = Texture.CLAMP_ADDRESSMODE;
  14. this._depthMap.refreshRate = 1;
  15. this._depthMap.renderParticles = false;
  16. this._depthMap.renderList = null;
  17. // set default depth value to 1.0 (far away)
  18. this._depthMap.onClearObservable.add((engine: Engine) => {
  19. engine.clear(new Color4(1.0, 1.0, 1.0, 1.0), true, true, true);
  20. });
  21. // Custom render function
  22. var renderSubMesh = (subMesh: SubMesh): void => {
  23. var mesh = subMesh.getRenderingMesh();
  24. var scene = this._scene;
  25. var engine = scene.getEngine();
  26. let material = subMesh.getMaterial();
  27. if (!material) {
  28. return;
  29. }
  30. // Culling and reverse (right handed system)
  31. engine.setState(material.backFaceCulling, 0, false, scene.useRightHandedSystem);
  32. // Managing instances
  33. var batch = mesh._getInstancesRenderList(subMesh._id);
  34. if (batch.mustReturn) {
  35. return;
  36. }
  37. var hardwareInstancedRendering = (engine.getCaps().instancedArrays) && (batch.visibleInstances[subMesh._id] !== null);
  38. if (this.isReady(subMesh, hardwareInstancedRendering) && scene.activeCamera) {
  39. engine.enableEffect(this._effect);
  40. mesh._bind(subMesh, this._effect, Material.TriangleFillMode);
  41. this._effect.setMatrix("viewProjection", scene.getTransformMatrix());
  42. this._effect.setFloat2("depthValues", scene.activeCamera.minZ, scene.activeCamera.minZ + scene.activeCamera.maxZ);
  43. // Alpha test
  44. if (material && material.needAlphaTesting()) {
  45. var alphaTexture = material.getAlphaTestTexture();
  46. if (alphaTexture) {
  47. this._effect.setTexture("diffuseSampler", alphaTexture);
  48. this._effect.setMatrix("diffuseMatrix", alphaTexture.getTextureMatrix());
  49. }
  50. }
  51. // Bones
  52. if (mesh.useBones && mesh.computeBonesUsingShaders && mesh.skeleton) {
  53. this._effect.setMatrices("mBones", mesh.skeleton.getTransformMatrices(mesh));
  54. }
  55. // Draw
  56. mesh._processRendering(subMesh, this._effect, Material.TriangleFillMode, batch, hardwareInstancedRendering,
  57. (isInstance, world) => this._effect.setMatrix("world", world));
  58. }
  59. };
  60. this._depthMap.customRenderFunction = (opaqueSubMeshes: SmartArray<SubMesh>, alphaTestSubMeshes: SmartArray<SubMesh>, transparentSubMeshes: SmartArray<SubMesh>, depthOnlySubMeshes: SmartArray<SubMesh>): void => {
  61. var index;
  62. if (depthOnlySubMeshes.length) {
  63. engine.setColorWrite(false);
  64. for (index = 0; index < depthOnlySubMeshes.length; index++) {
  65. renderSubMesh(depthOnlySubMeshes.data[index]);
  66. }
  67. engine.setColorWrite(true);
  68. }
  69. for (index = 0; index < opaqueSubMeshes.length; index++) {
  70. renderSubMesh(opaqueSubMeshes.data[index]);
  71. }
  72. for (index = 0; index < alphaTestSubMeshes.length; index++) {
  73. renderSubMesh(alphaTestSubMeshes.data[index]);
  74. }
  75. };
  76. }
  77. public isReady(subMesh: SubMesh, useInstances: boolean): boolean {
  78. var material: any = subMesh.getMaterial();
  79. if (material.disableDepthWrite) {
  80. return false;
  81. }
  82. var defines = [];
  83. var attribs = [VertexBuffer.PositionKind];
  84. var mesh = subMesh.getMesh();
  85. // Alpha test
  86. if (material && material.needAlphaTesting()) {
  87. defines.push("#define ALPHATEST");
  88. if (mesh.isVerticesDataPresent(VertexBuffer.UVKind)) {
  89. attribs.push(VertexBuffer.UVKind);
  90. defines.push("#define UV1");
  91. }
  92. if (mesh.isVerticesDataPresent(VertexBuffer.UV2Kind)) {
  93. attribs.push(VertexBuffer.UV2Kind);
  94. defines.push("#define UV2");
  95. }
  96. }
  97. // Bones
  98. if (mesh.useBones && mesh.computeBonesUsingShaders) {
  99. attribs.push(VertexBuffer.MatricesIndicesKind);
  100. attribs.push(VertexBuffer.MatricesWeightsKind);
  101. if (mesh.numBoneInfluencers > 4) {
  102. attribs.push(VertexBuffer.MatricesIndicesExtraKind);
  103. attribs.push(VertexBuffer.MatricesWeightsExtraKind);
  104. }
  105. defines.push("#define NUM_BONE_INFLUENCERS " + mesh.numBoneInfluencers);
  106. defines.push("#define BonesPerMesh " + (mesh.skeleton ? mesh.skeleton.bones.length + 1 : 0));
  107. } else {
  108. defines.push("#define NUM_BONE_INFLUENCERS 0");
  109. }
  110. // Instances
  111. if (useInstances) {
  112. defines.push("#define INSTANCES");
  113. attribs.push("world0");
  114. attribs.push("world1");
  115. attribs.push("world2");
  116. attribs.push("world3");
  117. }
  118. // Get correct effect
  119. var join = defines.join("\n");
  120. if (this._cachedDefines !== join) {
  121. this._cachedDefines = join;
  122. this._effect = this._scene.getEngine().createEffect("depth",
  123. attribs,
  124. ["world", "mBones", "viewProjection", "diffuseMatrix", "depthValues"],
  125. ["diffuseSampler"], join);
  126. }
  127. return this._effect.isReady();
  128. }
  129. public getDepthMap(): RenderTargetTexture {
  130. return this._depthMap;
  131. }
  132. // Methods
  133. public dispose(): void {
  134. this._depthMap.dispose();
  135. }
  136. }
  137. }