gaussianSplattingMaterial.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import { SerializationHelper } from "../../Misc/decorators.serialization.js";
  2. import { VertexBuffer } from "../../Buffers/buffer.js";
  3. import { MaterialDefines } from "../../Materials/materialDefines.js";
  4. import { PushMaterial } from "../../Materials/pushMaterial.js";
  5. import { RegisterClass } from "../../Misc/typeStore.js";
  6. import { addClipPlaneUniforms, bindClipPlane } from "../clipPlaneMaterialHelper.js";
  7. import { Camera } from "../../Cameras/camera.js";
  8. import "../../Shaders/gaussianSplatting.fragment.js";
  9. import "../../Shaders/gaussianSplatting.vertex.js";
  10. import { BindFogParameters, BindLogDepth, PrepareAttributesForInstances, PrepareDefinesForAttributes, PrepareDefinesForFrameBoundValues, PrepareDefinesForMisc, PrepareUniformsAndSamplersList, } from "../materialHelper.functions.js";
  11. /**
  12. * @internal
  13. */
  14. class GaussianSplattingMaterialDefines extends MaterialDefines {
  15. /**
  16. * Constructor of the defines.
  17. */
  18. constructor() {
  19. super();
  20. this.FOG = false;
  21. this.THIN_INSTANCES = true;
  22. this.LOGARITHMICDEPTH = false;
  23. this.CLIPPLANE = false;
  24. this.CLIPPLANE2 = false;
  25. this.CLIPPLANE3 = false;
  26. this.CLIPPLANE4 = false;
  27. this.CLIPPLANE5 = false;
  28. this.CLIPPLANE6 = false;
  29. this.rebuild();
  30. }
  31. }
  32. /**
  33. * GaussianSplattingMaterial material used to render Gaussian Splatting
  34. * @experimental
  35. */
  36. export class GaussianSplattingMaterial extends PushMaterial {
  37. /**
  38. * Instantiates a Gaussian Splatting Material in the given scene
  39. * @param name The friendly name of the material
  40. * @param scene The scene to add the material to
  41. */
  42. constructor(name, scene) {
  43. super(name, scene);
  44. this.backFaceCulling = false;
  45. }
  46. /**
  47. * Gets a boolean indicating that current material needs to register RTT
  48. */
  49. get hasRenderTargetTextures() {
  50. return false;
  51. }
  52. /**
  53. * Specifies whether or not this material should be rendered in alpha test mode.
  54. * @returns false
  55. */
  56. needAlphaTesting() {
  57. return false;
  58. }
  59. /**
  60. * Specifies whether or not this material should be rendered in alpha blend mode.
  61. * @returns true
  62. */
  63. needAlphaBlending() {
  64. return true;
  65. }
  66. /**
  67. * Checks whether the material is ready to be rendered for a given mesh.
  68. * @param mesh The mesh to render
  69. * @param subMesh The submesh to check against
  70. * @returns true if all the dependencies are ready (Textures, Effects...)
  71. */
  72. isReadyForSubMesh(mesh, subMesh) {
  73. const useInstances = true;
  74. const drawWrapper = subMesh._drawWrapper;
  75. if (drawWrapper.effect && this.isFrozen) {
  76. if (drawWrapper._wasPreviouslyReady && drawWrapper._wasPreviouslyUsingInstances === useInstances) {
  77. return true;
  78. }
  79. }
  80. if (!subMesh.materialDefines) {
  81. subMesh.materialDefines = new GaussianSplattingMaterialDefines();
  82. }
  83. const scene = this.getScene();
  84. const defines = subMesh.materialDefines;
  85. if (this._isReadyForSubMesh(subMesh)) {
  86. return true;
  87. }
  88. const engine = scene.getEngine();
  89. // Misc.
  90. PrepareDefinesForMisc(mesh, scene, this._useLogarithmicDepth, this.pointsCloud, this.fogEnabled, false, defines);
  91. // Values that need to be evaluated on every frame
  92. PrepareDefinesForFrameBoundValues(scene, engine, this, defines, useInstances, null, true);
  93. // Attribs
  94. PrepareDefinesForAttributes(mesh, defines, false, false);
  95. // Get correct effect
  96. if (defines.isDirty) {
  97. defines.markAsProcessed();
  98. scene.resetCachedMaterial();
  99. //Attributes
  100. const attribs = [VertexBuffer.PositionKind, "splatIndex"];
  101. PrepareAttributesForInstances(attribs, defines);
  102. const uniforms = ["world", "view", "projection", "vFogInfos", "vFogColor", "logarithmicDepthConstant", "viewport", "dataTextureSize", "focal"];
  103. const samplers = ["covariancesATexture", "covariancesBTexture", "centersTexture", "colorsTexture"];
  104. const uniformBuffers = ["Scene", "Mesh"];
  105. PrepareUniformsAndSamplersList({
  106. uniformsNames: uniforms,
  107. uniformBuffersNames: uniformBuffers,
  108. samplers: samplers,
  109. defines: defines,
  110. });
  111. addClipPlaneUniforms(uniforms);
  112. const join = defines.toString();
  113. const effect = scene.getEngine().createEffect("gaussianSplatting", {
  114. attributes: attribs,
  115. uniformsNames: uniforms,
  116. uniformBuffersNames: uniformBuffers,
  117. samplers: samplers,
  118. defines: join,
  119. onCompiled: this.onCompiled,
  120. onError: this.onError,
  121. }, engine);
  122. subMesh.setEffect(effect, defines, this._materialContext);
  123. }
  124. if (!subMesh.effect || !subMesh.effect.isReady()) {
  125. return false;
  126. }
  127. defines._renderId = scene.getRenderId();
  128. drawWrapper._wasPreviouslyReady = true;
  129. drawWrapper._wasPreviouslyUsingInstances = useInstances;
  130. return true;
  131. }
  132. /**
  133. * Binds the submesh to this material by preparing the effect and shader to draw
  134. * @param world defines the world transformation matrix
  135. * @param mesh defines the mesh containing the submesh
  136. * @param subMesh defines the submesh to bind the material to
  137. */
  138. bindForSubMesh(world, mesh, subMesh) {
  139. const scene = this.getScene();
  140. const defines = subMesh.materialDefines;
  141. if (!defines) {
  142. return;
  143. }
  144. const effect = subMesh.effect;
  145. if (!effect) {
  146. return;
  147. }
  148. this._activeEffect = effect;
  149. // Matrices Mesh.
  150. mesh.getMeshUniformBuffer().bindToEffect(effect, "Mesh");
  151. mesh.transferToEffect(world);
  152. // Bind data
  153. const mustRebind = this._mustRebind(scene, effect, subMesh, mesh.visibility);
  154. if (mustRebind) {
  155. this.bindView(effect);
  156. this.bindViewProjection(effect);
  157. const engine = scene.getEngine();
  158. const camera = this.getScene().activeCamera;
  159. const renderWidth = engine.getRenderWidth();
  160. const renderHeight = engine.getRenderHeight();
  161. this._activeEffect.setFloat2("viewport", renderWidth, renderHeight);
  162. let focal = 1000;
  163. if (camera) {
  164. if (camera.fovMode == Camera.FOVMODE_VERTICAL_FIXED) {
  165. focal = renderHeight / 2.0 / Math.tan(camera.fov / 2.0);
  166. }
  167. else {
  168. focal = renderWidth / 2.0 / Math.tan(camera.fov / 2.0);
  169. }
  170. }
  171. this._activeEffect.setFloat2("focal", focal, focal);
  172. const gsMesh = mesh;
  173. if (gsMesh.covariancesATexture) {
  174. const textureSize = gsMesh.covariancesATexture.getSize();
  175. effect.setFloat2("dataTextureSize", textureSize.width, textureSize.height);
  176. effect.setTexture("covariancesATexture", gsMesh.covariancesATexture);
  177. effect.setTexture("covariancesBTexture", gsMesh.covariancesBTexture);
  178. effect.setTexture("centersTexture", gsMesh.centersTexture);
  179. effect.setTexture("colorsTexture", gsMesh.colorsTexture);
  180. }
  181. // Clip plane
  182. bindClipPlane(effect, this, scene);
  183. }
  184. else if (scene.getEngine()._features.needToAlwaysBindUniformBuffers) {
  185. this._needToBindSceneUbo = true;
  186. }
  187. // Fog
  188. BindFogParameters(scene, mesh, effect);
  189. // Log. depth
  190. if (this.useLogarithmicDepth) {
  191. BindLogDepth(defines, effect, scene);
  192. }
  193. this._afterBind(mesh, this._activeEffect, subMesh);
  194. }
  195. /**
  196. * Clones the material.
  197. * @param name The cloned name.
  198. * @returns The cloned material.
  199. */
  200. clone(name) {
  201. return SerializationHelper.Clone(() => new GaussianSplattingMaterial(name, this.getScene()), this);
  202. }
  203. /**
  204. * Serializes the current material to its JSON representation.
  205. * @returns The JSON representation.
  206. */
  207. serialize() {
  208. const serializationObject = super.serialize();
  209. serializationObject.customType = "BABYLON.GaussianSplattingMaterial";
  210. return serializationObject;
  211. }
  212. /**
  213. * Gets the class name of the material
  214. * @returns "GaussianSplattingMaterial"
  215. */
  216. getClassName() {
  217. return "GaussianSplattingMaterial";
  218. }
  219. /**
  220. * Parse a JSON input to create back a Gaussian Splatting material.
  221. * @param source The JSON data to parse
  222. * @param scene The scene to create the parsed material in
  223. * @param rootUrl The root url of the assets the material depends upon
  224. * @returns the instantiated GaussianSplattingMaterial.
  225. */
  226. static Parse(source, scene, rootUrl) {
  227. return SerializationHelper.Parse(() => new GaussianSplattingMaterial(source.name, scene), source, scene, rootUrl);
  228. }
  229. }
  230. RegisterClass("BABYLON.GaussianSplattingMaterial", GaussianSplattingMaterial);
  231. //# sourceMappingURL=gaussianSplattingMaterial.js.map