babylon.reflectionProbe.ts 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. module BABYLON {
  2. export interface AbstractScene {
  3. /**
  4. * The list of reflection probes added to the scene
  5. * @see http://doc.babylonjs.com/how_to/how_to_use_reflection_probes
  6. */
  7. reflectionProbes: Array<ReflectionProbe>;
  8. }
  9. /**
  10. * Class used to generate realtime reflection / refraction cube textures
  11. * @see http://doc.babylonjs.com/how_to/how_to_use_reflection_probes
  12. */
  13. export class ReflectionProbe{
  14. private _scene: Scene;
  15. private _renderTargetTexture: RenderTargetTexture;
  16. private _projectionMatrix: Matrix;
  17. private _viewMatrix = Matrix.Identity();
  18. private _target = Vector3.Zero();
  19. private _add = Vector3.Zero();
  20. @serializeAsMeshReference()
  21. private _attachedMesh: Nullable<AbstractMesh>;
  22. private _invertYAxis = false;
  23. /** Gets or sets probe position (center of the cube map) */
  24. @serializeAsVector3()
  25. public position = Vector3.Zero();
  26. /**
  27. * Creates a new reflection probe
  28. * @param name defines the name of the probe
  29. * @param size defines the texture resolution (for each face)
  30. * @param scene defines the hosting scene
  31. * @param generateMipMaps defines if mip maps should be generated automatically (true by default)
  32. * @param useFloat defines if HDR data (flaot data) should be used to store colors (false by default)
  33. */
  34. constructor(
  35. /** defines the name of the probe */
  36. public name: string,
  37. size: number, scene: Scene, generateMipMaps = true, useFloat = false) {
  38. this._scene = scene;
  39. // Create the scene field if not exist.
  40. if (!this._scene.reflectionProbes) {
  41. this._scene.reflectionProbes = new Array<ReflectionProbe>();
  42. }
  43. this._scene.reflectionProbes.push(this);
  44. this._renderTargetTexture = new RenderTargetTexture(name, size, scene, generateMipMaps, true, useFloat ? Engine.TEXTURETYPE_FLOAT : Engine.TEXTURETYPE_UNSIGNED_INT, true);
  45. this._renderTargetTexture.onBeforeRenderObservable.add((faceIndex: number) => {
  46. switch (faceIndex) {
  47. case 0:
  48. this._add.copyFromFloats(1, 0, 0);
  49. break;
  50. case 1:
  51. this._add.copyFromFloats(-1, 0, 0);
  52. break;
  53. case 2:
  54. this._add.copyFromFloats(0, this._invertYAxis ? 1 : -1, 0);
  55. break;
  56. case 3:
  57. this._add.copyFromFloats(0, this._invertYAxis ? -1 : 1, 0);
  58. break;
  59. case 4:
  60. this._add.copyFromFloats(0, 0, 1);
  61. break;
  62. case 5:
  63. this._add.copyFromFloats(0, 0, -1);
  64. break;
  65. }
  66. if (this._attachedMesh) {
  67. this.position.copyFrom(this._attachedMesh.getAbsolutePosition());
  68. }
  69. this.position.addToRef(this._add, this._target);
  70. Matrix.LookAtLHToRef(this.position, this._target, Vector3.Up(), this._viewMatrix);
  71. if (scene.activeCamera) {
  72. this._projectionMatrix = Matrix.PerspectiveFovLH(Math.PI / 2, 1, scene.activeCamera.minZ, scene.activeCamera.maxZ);
  73. scene.setTransformMatrix(this._viewMatrix, this._projectionMatrix);
  74. }
  75. scene._forcedViewPosition = this.position;
  76. });
  77. this._renderTargetTexture.onAfterUnbindObservable.add(() => {
  78. scene._forcedViewPosition = null;
  79. scene.updateTransformMatrix(true);
  80. });
  81. }
  82. /** Gets or sets the number of samples to use for multi-sampling (0 by default). Required WebGL2 */
  83. public get samples(): number {
  84. return this._renderTargetTexture.samples;
  85. }
  86. public set samples(value: number) {
  87. this._renderTargetTexture.samples = value;
  88. }
  89. /** Gets or sets the refresh rate to use (on every frame by default) */
  90. public get refreshRate(): number {
  91. return this._renderTargetTexture.refreshRate;
  92. }
  93. public set refreshRate(value: number) {
  94. this._renderTargetTexture.refreshRate = value;
  95. }
  96. /**
  97. * Gets the hosting scene
  98. * @returns a Scene
  99. */
  100. public getScene(): Scene {
  101. return this._scene;
  102. }
  103. /** Gets the internal CubeTexture used to render to */
  104. public get cubeTexture(): RenderTargetTexture {
  105. return this._renderTargetTexture;
  106. }
  107. /** Gets the list of meshes to render */
  108. public get renderList(): Nullable<AbstractMesh[]> {
  109. return this._renderTargetTexture.renderList;
  110. }
  111. /**
  112. * Attach the probe to a specific mesh (Rendering will be done from attached mesh's position)
  113. * @param mesh defines the mesh to attach to
  114. */
  115. public attachToMesh(mesh: Nullable<AbstractMesh>): void {
  116. this._attachedMesh = mesh;
  117. }
  118. /**
  119. * Specifies whether or not the stencil and depth buffer are cleared between two rendering groups
  120. * @param renderingGroupId The rendering group id corresponding to its index
  121. * @param autoClearDepthStencil Automatically clears depth and stencil between groups if true.
  122. */
  123. public setRenderingAutoClearDepthStencil(renderingGroupId: number, autoClearDepthStencil: boolean): void {
  124. this._renderTargetTexture.setRenderingAutoClearDepthStencil(renderingGroupId, autoClearDepthStencil);
  125. }
  126. /**
  127. * Clean all associated resources
  128. */
  129. public dispose() {
  130. var index = this._scene.reflectionProbes.indexOf(this);
  131. if (index !== -1) {
  132. // Remove from the scene if found
  133. this._scene.reflectionProbes.splice(index, 1);
  134. }
  135. if (this._renderTargetTexture) {
  136. this._renderTargetTexture.dispose();
  137. (<any>this._renderTargetTexture) = null;
  138. }
  139. }
  140. /**
  141. * Converts the reflection probe information to a readable string for debug purpose.
  142. * @param fullDetails Supports for multiple levels of logging within scene loading
  143. * @returns the human readable reflection probe info
  144. */
  145. public toString(fullDetails?: boolean): string {
  146. var ret = "Name: " + this.name;
  147. if (fullDetails) {
  148. ret += ", position: " + this.position.toString();
  149. if (this._attachedMesh) {
  150. ret += ", attached mesh: " + this._attachedMesh.name;
  151. }
  152. }
  153. return ret;
  154. }
  155. /**
  156. * Get the class name of the relfection probe.
  157. * @returns "ReflectionProbe"
  158. */
  159. public getClassName(): string {
  160. return "ReflectionProbe";
  161. }
  162. /**
  163. * Serialize the reflection probe to a JSON representation we can easily use in the resepective Parse function.
  164. * @returns The JSON representation of the texture
  165. */
  166. public serialize(): any {
  167. const serializationObject = SerializationHelper.Serialize(this, this._renderTargetTexture.serialize());
  168. serializationObject.isReflectionProbe = true;
  169. return serializationObject;
  170. }
  171. /**
  172. * Parse the JSON representation of a reflection probe in order to recreate the reflection probe in the given scene.
  173. * @param parsedReflectionProbe Define the JSON representation of the reflection probe
  174. * @param scene Define the scene the parsed reflection probe should be instantiated in
  175. * @param rootUrl Define the root url of the parsing sequence in the case of relative dependencies
  176. * @returns The parsed reflection probe if successful
  177. */
  178. public static Parse(parsedReflectionProbe: any, scene: Scene, rootUrl: string): Nullable<ReflectionProbe> {
  179. let reflectionProbe: Nullable<ReflectionProbe> = null;
  180. if (scene.reflectionProbes) {
  181. for (let index = 0; index < scene.reflectionProbes.length; index++) {
  182. const rp = scene.reflectionProbes[index];
  183. if (rp.name === parsedReflectionProbe.name) {
  184. reflectionProbe = rp;
  185. break;
  186. }
  187. }
  188. }
  189. reflectionProbe = SerializationHelper.Parse(() => reflectionProbe || new ReflectionProbe(parsedReflectionProbe.name, parsedReflectionProbe.renderTargetSize, scene, parsedReflectionProbe._generateMipMaps), parsedReflectionProbe, scene, rootUrl);
  190. reflectionProbe.cubeTexture._waitingRenderList = parsedReflectionProbe.renderList;
  191. if (parsedReflectionProbe._attachedMesh) {
  192. reflectionProbe.attachToMesh(scene.getMeshByID(parsedReflectionProbe._attachedMesh));
  193. }
  194. return reflectionProbe;
  195. }
  196. }
  197. }