screenSpaceReflectionPostProcess.js 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. import { __decorate } from "../tslib.es6.js";
  2. import { PostProcess } from "./postProcess.js";
  3. import { GeometryBufferRenderer } from "../Rendering/geometryBufferRenderer.js";
  4. import { serialize } from "../Misc/decorators.js";
  5. import { SerializationHelper } from "../Misc/decorators.serialization.js";
  6. import { ScreenSpaceReflectionsConfiguration } from "../Rendering/screenSpaceReflectionsConfiguration.js";
  7. import "../Shaders/screenSpaceReflection.fragment.js";
  8. import { RegisterClass } from "../Misc/typeStore.js";
  9. import { Logger } from "../Misc/logger.js";
  10. /**
  11. * The ScreenSpaceReflectionPostProcess performs realtime reflections using only and only the available informations on the screen (positions and normals).
  12. * Basically, the screen space reflection post-process will compute reflections according the material's reflectivity.
  13. * @deprecated Use the new SSRRenderingPipeline instead.
  14. */
  15. export class ScreenSpaceReflectionPostProcess extends PostProcess {
  16. get _geometryBufferRenderer() {
  17. if (!this._forceGeometryBuffer) {
  18. return null;
  19. }
  20. return this._scene.geometryBufferRenderer;
  21. }
  22. get _prePassRenderer() {
  23. if (this._forceGeometryBuffer) {
  24. return null;
  25. }
  26. return this._scene.prePassRenderer;
  27. }
  28. /**
  29. * Gets a string identifying the name of the class
  30. * @returns "ScreenSpaceReflectionPostProcess" string
  31. */
  32. getClassName() {
  33. return "ScreenSpaceReflectionPostProcess";
  34. }
  35. /**
  36. * Creates a new instance of ScreenSpaceReflectionPostProcess.
  37. * @param name The name of the effect.
  38. * @param scene The scene containing the objects to calculate reflections.
  39. * @param options The required width/height ratio to downsize to before computing the render pass.
  40. * @param camera The camera to apply the render pass to.
  41. * @param samplingMode The sampling mode to be used when computing the pass. (default: 0)
  42. * @param engine The engine which the post process will be applied. (default: current engine)
  43. * @param reusable If the post process can be reused on the same frame. (default: false)
  44. * @param textureType Type of textures used when performing the post process. (default: 0)
  45. * @param blockCompilation If compilation of the shader should not be done in the constructor. The updateEffect method can be used to compile the shader at a later time. (default: true)
  46. * @param forceGeometryBuffer If this post process should use geometry buffer instead of prepass (default: false)
  47. */
  48. constructor(name, scene, options, camera, samplingMode, engine, reusable, textureType = 0, blockCompilation = false, forceGeometryBuffer = false) {
  49. super(name, "screenSpaceReflection", ["projection", "view", "threshold", "reflectionSpecularFalloffExponent", "strength", "stepSize", "roughnessFactor"], ["textureSampler", "normalSampler", "positionSampler", "reflectivitySampler"], options, camera, samplingMode, engine, reusable, "#define SSR_SUPPORTED\n#define REFLECTION_SAMPLES 64\n#define SMOOTH_STEPS 5\n", textureType, undefined, null, blockCompilation);
  50. /**
  51. * Gets or sets a reflection threshold mainly used to adjust the reflection's height.
  52. */
  53. this.threshold = 1.2;
  54. /**
  55. * Gets or sets the current reflection strength. 1.0 is an ideal value but can be increased/decreased for particular results.
  56. */
  57. this.strength = 1;
  58. /**
  59. * Gets or sets the falloff exponent used while computing fresnel. More the exponent is high, more the reflections will be discrete.
  60. */
  61. this.reflectionSpecularFalloffExponent = 3;
  62. /**
  63. * Gets or sets the step size used to iterate until the effect finds the color of the reflection's pixel. Typically in interval [0.1, 1.0]
  64. */
  65. this.step = 1.0;
  66. /**
  67. * Gets or sets the factor applied when computing roughness. Default value is 0.2.
  68. */
  69. this.roughnessFactor = 0.2;
  70. this._forceGeometryBuffer = false;
  71. this._enableSmoothReflections = false;
  72. this._reflectionSamples = 64;
  73. this._smoothSteps = 5;
  74. this._forceGeometryBuffer = forceGeometryBuffer;
  75. if (this._forceGeometryBuffer) {
  76. // Get geometry buffer renderer and update effect
  77. const geometryBufferRenderer = scene.enableGeometryBufferRenderer();
  78. if (geometryBufferRenderer) {
  79. if (geometryBufferRenderer.isSupported) {
  80. geometryBufferRenderer.enablePosition = true;
  81. geometryBufferRenderer.enableReflectivity = true;
  82. if (geometryBufferRenderer.generateNormalsInWorldSpace) {
  83. Logger.Error("ScreenSpaceReflectionPostProcess does not support generateNormalsInWorldSpace=true for the geometry buffer renderer!");
  84. }
  85. }
  86. }
  87. }
  88. else {
  89. const prePassRenderer = scene.enablePrePassRenderer();
  90. prePassRenderer?.markAsDirty();
  91. if (prePassRenderer?.generateNormalsInWorldSpace) {
  92. Logger.Error("ScreenSpaceReflectionPostProcess does not support generateNormalsInWorldSpace=true for the prepass renderer!");
  93. }
  94. this._prePassEffectConfiguration = new ScreenSpaceReflectionsConfiguration();
  95. }
  96. this._updateEffectDefines();
  97. // On apply, send uniforms
  98. this.onApply = (effect) => {
  99. const geometryBufferRenderer = this._geometryBufferRenderer;
  100. const prePassRenderer = this._prePassRenderer;
  101. if (!prePassRenderer && !geometryBufferRenderer) {
  102. return;
  103. }
  104. if (geometryBufferRenderer) {
  105. // Samplers
  106. const positionIndex = geometryBufferRenderer.getTextureIndex(GeometryBufferRenderer.POSITION_TEXTURE_TYPE);
  107. const roughnessIndex = geometryBufferRenderer.getTextureIndex(GeometryBufferRenderer.REFLECTIVITY_TEXTURE_TYPE);
  108. effect.setTexture("normalSampler", geometryBufferRenderer.getGBuffer().textures[1]);
  109. effect.setTexture("positionSampler", geometryBufferRenderer.getGBuffer().textures[positionIndex]);
  110. effect.setTexture("reflectivitySampler", geometryBufferRenderer.getGBuffer().textures[roughnessIndex]);
  111. }
  112. else if (prePassRenderer) {
  113. // Samplers
  114. const positionIndex = prePassRenderer.getIndex(1);
  115. const roughnessIndex = prePassRenderer.getIndex(3);
  116. const normalIndex = prePassRenderer.getIndex(6);
  117. effect.setTexture("normalSampler", prePassRenderer.getRenderTarget().textures[normalIndex]);
  118. effect.setTexture("positionSampler", prePassRenderer.getRenderTarget().textures[positionIndex]);
  119. effect.setTexture("reflectivitySampler", prePassRenderer.getRenderTarget().textures[roughnessIndex]);
  120. }
  121. // Uniforms
  122. const camera = scene.activeCamera;
  123. if (!camera) {
  124. return;
  125. }
  126. const viewMatrix = camera.getViewMatrix(true);
  127. const projectionMatrix = camera.getProjectionMatrix(true);
  128. effect.setMatrix("projection", projectionMatrix);
  129. effect.setMatrix("view", viewMatrix);
  130. effect.setFloat("threshold", this.threshold);
  131. effect.setFloat("reflectionSpecularFalloffExponent", this.reflectionSpecularFalloffExponent);
  132. effect.setFloat("strength", this.strength);
  133. effect.setFloat("stepSize", this.step);
  134. effect.setFloat("roughnessFactor", this.roughnessFactor);
  135. };
  136. this._isSceneRightHanded = scene.useRightHandedSystem;
  137. }
  138. /**
  139. * Gets whether or not smoothing reflections is enabled.
  140. * Enabling smoothing will require more GPU power and can generate a drop in FPS.
  141. */
  142. get enableSmoothReflections() {
  143. return this._enableSmoothReflections;
  144. }
  145. /**
  146. * Sets whether or not smoothing reflections is enabled.
  147. * Enabling smoothing will require more GPU power and can generate a drop in FPS.
  148. */
  149. set enableSmoothReflections(enabled) {
  150. if (enabled === this._enableSmoothReflections) {
  151. return;
  152. }
  153. this._enableSmoothReflections = enabled;
  154. this._updateEffectDefines();
  155. }
  156. /**
  157. * Gets the number of samples taken while computing reflections. More samples count is high,
  158. * more the post-process wil require GPU power and can generate a drop in FPS. Basically in interval [25, 100].
  159. */
  160. get reflectionSamples() {
  161. return this._reflectionSamples;
  162. }
  163. /**
  164. * Sets the number of samples taken while computing reflections. More samples count is high,
  165. * more the post-process wil require GPU power and can generate a drop in FPS. Basically in interval [25, 100].
  166. */
  167. set reflectionSamples(samples) {
  168. if (samples === this._reflectionSamples) {
  169. return;
  170. }
  171. this._reflectionSamples = samples;
  172. this._updateEffectDefines();
  173. }
  174. /**
  175. * Gets the number of samples taken while smoothing reflections. More samples count is high,
  176. * more the post-process will require GPU power and can generate a drop in FPS.
  177. * Default value (5.0) work pretty well in all cases but can be adjusted.
  178. */
  179. get smoothSteps() {
  180. return this._smoothSteps;
  181. }
  182. /*
  183. * Sets the number of samples taken while smoothing reflections. More samples count is high,
  184. * more the post-process will require GPU power and can generate a drop in FPS.
  185. * Default value (5.0) work pretty well in all cases but can be adjusted.
  186. */
  187. set smoothSteps(steps) {
  188. if (steps === this._smoothSteps) {
  189. return;
  190. }
  191. this._smoothSteps = steps;
  192. this._updateEffectDefines();
  193. }
  194. _updateEffectDefines() {
  195. const defines = [];
  196. if (this._geometryBufferRenderer || this._prePassRenderer) {
  197. defines.push("#define SSR_SUPPORTED");
  198. }
  199. if (this._enableSmoothReflections) {
  200. defines.push("#define ENABLE_SMOOTH_REFLECTIONS");
  201. }
  202. if (this._isSceneRightHanded) {
  203. defines.push("#define RIGHT_HANDED_SCENE");
  204. }
  205. defines.push("#define REFLECTION_SAMPLES " + (this._reflectionSamples >> 0));
  206. defines.push("#define SMOOTH_STEPS " + (this._smoothSteps >> 0));
  207. this.updateEffect(defines.join("\n"));
  208. }
  209. /**
  210. * @internal
  211. */
  212. static _Parse(parsedPostProcess, targetCamera, scene, rootUrl) {
  213. return SerializationHelper.Parse(() => {
  214. return new ScreenSpaceReflectionPostProcess(parsedPostProcess.name, scene, parsedPostProcess.options, targetCamera, parsedPostProcess.renderTargetSamplingMode, scene.getEngine(), parsedPostProcess.textureType, parsedPostProcess.reusable);
  215. }, parsedPostProcess, scene, rootUrl);
  216. }
  217. }
  218. __decorate([
  219. serialize()
  220. ], ScreenSpaceReflectionPostProcess.prototype, "threshold", void 0);
  221. __decorate([
  222. serialize()
  223. ], ScreenSpaceReflectionPostProcess.prototype, "strength", void 0);
  224. __decorate([
  225. serialize()
  226. ], ScreenSpaceReflectionPostProcess.prototype, "reflectionSpecularFalloffExponent", void 0);
  227. __decorate([
  228. serialize()
  229. ], ScreenSpaceReflectionPostProcess.prototype, "step", void 0);
  230. __decorate([
  231. serialize()
  232. ], ScreenSpaceReflectionPostProcess.prototype, "roughnessFactor", void 0);
  233. __decorate([
  234. serialize()
  235. ], ScreenSpaceReflectionPostProcess.prototype, "enableSmoothReflections", null);
  236. __decorate([
  237. serialize()
  238. ], ScreenSpaceReflectionPostProcess.prototype, "reflectionSamples", null);
  239. __decorate([
  240. serialize()
  241. ], ScreenSpaceReflectionPostProcess.prototype, "smoothSteps", null);
  242. RegisterClass("BABYLON.ScreenSpaceReflectionPostProcess", ScreenSpaceReflectionPostProcess);
  243. //# sourceMappingURL=screenSpaceReflectionPostProcess.js.map