fluidRenderingObject.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. import { EffectWrapper } from "../../Materials/effectRenderer.js";
  2. import { Observable } from "../../Misc/observable.js";
  3. /**
  4. * Defines the base object used for fluid rendering.
  5. * It is based on a list of vertices (particles)
  6. */
  7. export class FluidRenderingObject {
  8. /** Gets or sets the size of the particle */
  9. get particleSize() {
  10. return this._particleSize;
  11. }
  12. set particleSize(size) {
  13. if (size === this._particleSize) {
  14. return;
  15. }
  16. this._particleSize = size;
  17. this.onParticleSizeChanged.notifyObservers(this);
  18. }
  19. /** Indicates if the object uses instancing or not */
  20. get useInstancing() {
  21. return !this.indexBuffer;
  22. }
  23. /** Indicates if velocity of particles should be used when rendering the object. The vertex buffer set must contain a "velocity" buffer for this to work! */
  24. get useVelocity() {
  25. return this._useVelocity;
  26. }
  27. set useVelocity(use) {
  28. if (this._useVelocity === use || !this._hasVelocity()) {
  29. return;
  30. }
  31. this._useVelocity = use;
  32. this._effectsAreDirty = true;
  33. }
  34. _hasVelocity() {
  35. return !!this.vertexBuffers?.velocity;
  36. }
  37. /**
  38. * Gets the index buffer (or null if the object is using instancing)
  39. */
  40. get indexBuffer() {
  41. return null;
  42. }
  43. /**
  44. * @returns the name of the class
  45. */
  46. getClassName() {
  47. return "FluidRenderingObject";
  48. }
  49. /**
  50. * Instantiates a fluid rendering object
  51. * @param scene The scene the object is part of
  52. */
  53. constructor(scene) {
  54. /** Defines the priority of the object. Objects will be rendered in ascending order of priority */
  55. this.priority = 0;
  56. this._particleSize = 0.1;
  57. /** Observable triggered when the size of the particle is changed */
  58. this.onParticleSizeChanged = new Observable();
  59. /** Defines the alpha value of a particle */
  60. this.particleThicknessAlpha = 0.05;
  61. this._useVelocity = false;
  62. this._scene = scene;
  63. this._engine = scene.getEngine();
  64. this._effectsAreDirty = true;
  65. this._depthEffectWrapper = null;
  66. this._thicknessEffectWrapper = null;
  67. }
  68. _createEffects() {
  69. const uniformNames = ["view", "projection", "particleRadius", "size"];
  70. const attributeNames = ["position", "offset"];
  71. const defines = [];
  72. this._effectsAreDirty = false;
  73. if (this.useVelocity) {
  74. attributeNames.push("velocity");
  75. defines.push("#define FLUIDRENDERING_VELOCITY");
  76. }
  77. if (this._scene.useRightHandedSystem) {
  78. defines.push("#define FLUIDRENDERING_RHS");
  79. }
  80. this._depthEffectWrapper = new EffectWrapper({
  81. engine: this._engine,
  82. useShaderStore: true,
  83. vertexShader: "fluidRenderingParticleDepth",
  84. fragmentShader: "fluidRenderingParticleDepth",
  85. attributeNames,
  86. uniformNames,
  87. samplerNames: [],
  88. defines,
  89. });
  90. uniformNames.push("particleAlpha");
  91. this._thicknessEffectWrapper = new EffectWrapper({
  92. engine: this._engine,
  93. useShaderStore: true,
  94. vertexShader: "fluidRenderingParticleThickness",
  95. fragmentShader: "fluidRenderingParticleThickness",
  96. attributeNames: ["position", "offset"],
  97. uniformNames,
  98. samplerNames: [],
  99. });
  100. }
  101. /**
  102. * Indicates if the object is ready to be rendered
  103. * @returns True if everything is ready for the object to be rendered, otherwise false
  104. */
  105. isReady() {
  106. if (this._effectsAreDirty) {
  107. this._createEffects();
  108. }
  109. if (!this._depthEffectWrapper || !this._thicknessEffectWrapper) {
  110. return false;
  111. }
  112. const depthEffect = this._depthEffectWrapper._drawWrapper.effect;
  113. const thicknessEffect = this._thicknessEffectWrapper._drawWrapper.effect;
  114. return depthEffect.isReady() && thicknessEffect.isReady();
  115. }
  116. /**
  117. * Render the depth texture for this object
  118. */
  119. renderDepthTexture() {
  120. const numParticles = this.numParticles;
  121. if (!this._depthEffectWrapper || numParticles === 0) {
  122. return;
  123. }
  124. const depthDrawWrapper = this._depthEffectWrapper._drawWrapper;
  125. const depthEffect = depthDrawWrapper.effect;
  126. this._engine.enableEffect(depthDrawWrapper);
  127. this._engine.bindBuffers(this.vertexBuffers, this.indexBuffer, depthEffect);
  128. depthEffect.setMatrix("view", this._scene.getViewMatrix());
  129. depthEffect.setMatrix("projection", this._scene.getProjectionMatrix());
  130. depthEffect.setFloat2("size", this._particleSize, this._particleSize);
  131. depthEffect.setFloat("particleRadius", this._particleSize / 2);
  132. if (this.useInstancing) {
  133. this._engine.drawArraysType(7, 0, 4, numParticles);
  134. }
  135. else {
  136. this._engine.drawElementsType(0, 0, numParticles);
  137. }
  138. }
  139. /**
  140. * Render the thickness texture for this object
  141. */
  142. renderThicknessTexture() {
  143. const numParticles = this.numParticles;
  144. if (!this._thicknessEffectWrapper || numParticles === 0) {
  145. return;
  146. }
  147. const thicknessDrawWrapper = this._thicknessEffectWrapper._drawWrapper;
  148. const thicknessEffect = thicknessDrawWrapper.effect;
  149. this._engine.setAlphaMode(6);
  150. this._engine.setDepthWrite(false);
  151. this._engine.enableEffect(thicknessDrawWrapper);
  152. this._engine.bindBuffers(this.vertexBuffers, this.indexBuffer, thicknessEffect);
  153. thicknessEffect.setMatrix("view", this._scene.getViewMatrix());
  154. thicknessEffect.setMatrix("projection", this._scene.getProjectionMatrix());
  155. thicknessEffect.setFloat("particleAlpha", this.particleThicknessAlpha);
  156. thicknessEffect.setFloat2("size", this._particleSize, this._particleSize);
  157. if (this.useInstancing) {
  158. this._engine.drawArraysType(7, 0, 4, numParticles);
  159. }
  160. else {
  161. this._engine.drawElementsType(0, 0, numParticles);
  162. }
  163. this._engine.setDepthWrite(true);
  164. this._engine.setAlphaMode(0);
  165. }
  166. /**
  167. * Render the diffuse texture for this object
  168. */
  169. renderDiffuseTexture() {
  170. // do nothing by default
  171. }
  172. /**
  173. * Releases the ressources used by the class
  174. */
  175. dispose() {
  176. this._depthEffectWrapper?.dispose();
  177. this._thicknessEffectWrapper?.dispose();
  178. }
  179. }
  180. //# sourceMappingURL=fluidRenderingObject.js.map