SunPostProcess.js 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. import BoundingRectangle from "../Core/BoundingRectangle.js";
  2. import Cartesian2 from "../Core/Cartesian2.js";
  3. import Cartesian4 from "../Core/Cartesian4.js";
  4. import defined from "../Core/defined.js";
  5. import destroyObject from "../Core/destroyObject.js";
  6. import CesiumMath from "../Core/Math.js";
  7. import Matrix4 from "../Core/Matrix4.js";
  8. import Transforms from "../Core/Transforms.js";
  9. import AdditiveBlend from "../Shaders/PostProcessStages/AdditiveBlend.js";
  10. import BrightPass from "../Shaders/PostProcessStages/BrightPass.js";
  11. import GaussianBlur1D from "../Shaders/PostProcessStages/GaussianBlur1D.js";
  12. import PassThrough from "../Shaders/PostProcessStages/PassThrough.js";
  13. import PostProcessStage from "./PostProcessStage.js";
  14. import PostProcessStageComposite from "./PostProcessStageComposite.js";
  15. import PostProcessStageSampleMode from "./PostProcessStageSampleMode.js";
  16. import PostProcessStageTextureCache from "./PostProcessStageTextureCache.js";
  17. import SceneFramebuffer from "./SceneFramebuffer.js";
  18. function SunPostProcess() {
  19. this._sceneFramebuffer = new SceneFramebuffer();
  20. const scale = 0.125;
  21. const stages = new Array(6);
  22. stages[0] = new PostProcessStage({
  23. fragmentShader: PassThrough,
  24. textureScale: scale,
  25. forcePowerOfTwo: true,
  26. sampleMode: PostProcessStageSampleMode.LINEAR,
  27. });
  28. const brightPass = (stages[1] = new PostProcessStage({
  29. fragmentShader: BrightPass,
  30. uniforms: {
  31. avgLuminance: 0.5, // A guess at the average luminance across the entire scene
  32. threshold: 0.25,
  33. offset: 0.1,
  34. },
  35. textureScale: scale,
  36. forcePowerOfTwo: true,
  37. }));
  38. const that = this;
  39. this._delta = 1.0;
  40. this._sigma = 2.0;
  41. this._blurStep = new Cartesian2();
  42. stages[2] = new PostProcessStage({
  43. fragmentShader: GaussianBlur1D,
  44. uniforms: {
  45. step: function () {
  46. that._blurStep.x = that._blurStep.y =
  47. 1.0 / brightPass.outputTexture.width;
  48. return that._blurStep;
  49. },
  50. delta: function () {
  51. return that._delta;
  52. },
  53. sigma: function () {
  54. return that._sigma;
  55. },
  56. direction: 0.0,
  57. },
  58. textureScale: scale,
  59. forcePowerOfTwo: true,
  60. });
  61. stages[3] = new PostProcessStage({
  62. fragmentShader: GaussianBlur1D,
  63. uniforms: {
  64. step: function () {
  65. that._blurStep.x = that._blurStep.y =
  66. 1.0 / brightPass.outputTexture.width;
  67. return that._blurStep;
  68. },
  69. delta: function () {
  70. return that._delta;
  71. },
  72. sigma: function () {
  73. return that._sigma;
  74. },
  75. direction: 1.0,
  76. },
  77. textureScale: scale,
  78. forcePowerOfTwo: true,
  79. });
  80. stages[4] = new PostProcessStage({
  81. fragmentShader: PassThrough,
  82. sampleMode: PostProcessStageSampleMode.LINEAR,
  83. });
  84. this._uCenter = new Cartesian2();
  85. this._uRadius = undefined;
  86. stages[5] = new PostProcessStage({
  87. fragmentShader: AdditiveBlend,
  88. uniforms: {
  89. center: function () {
  90. return that._uCenter;
  91. },
  92. radius: function () {
  93. return that._uRadius;
  94. },
  95. colorTexture2: function () {
  96. return that._sceneFramebuffer.framebuffer.getColorTexture(0);
  97. },
  98. },
  99. });
  100. this._stages = new PostProcessStageComposite({
  101. stages: stages,
  102. });
  103. const textureCache = new PostProcessStageTextureCache(this);
  104. const length = stages.length;
  105. for (let i = 0; i < length; ++i) {
  106. stages[i]._textureCache = textureCache;
  107. }
  108. this._textureCache = textureCache;
  109. this.length = stages.length;
  110. }
  111. SunPostProcess.prototype.get = function (index) {
  112. return this._stages.get(index);
  113. };
  114. SunPostProcess.prototype.getStageByName = function (name) {
  115. const length = this._stages.length;
  116. for (let i = 0; i < length; ++i) {
  117. const stage = this._stages.get(i);
  118. if (stage.name === name) {
  119. return stage;
  120. }
  121. }
  122. return undefined;
  123. };
  124. const sunPositionECScratch = new Cartesian4();
  125. const sunPositionWCScratch = new Cartesian2();
  126. const sizeScratch = new Cartesian2();
  127. const postProcessMatrix4Scratch = new Matrix4();
  128. function updateSunPosition(postProcess, context, viewport) {
  129. const us = context.uniformState;
  130. const sunPosition = us.sunPositionWC;
  131. const viewMatrix = us.view;
  132. const viewProjectionMatrix = us.viewProjection;
  133. const projectionMatrix = us.projection;
  134. // create up sampled render state
  135. let viewportTransformation = Matrix4.computeViewportTransformation(
  136. viewport,
  137. 0.0,
  138. 1.0,
  139. postProcessMatrix4Scratch
  140. );
  141. const sunPositionEC = Matrix4.multiplyByPoint(
  142. viewMatrix,
  143. sunPosition,
  144. sunPositionECScratch
  145. );
  146. let sunPositionWC = Transforms.pointToGLWindowCoordinates(
  147. viewProjectionMatrix,
  148. viewportTransformation,
  149. sunPosition,
  150. sunPositionWCScratch
  151. );
  152. sunPositionEC.x += CesiumMath.SOLAR_RADIUS;
  153. const limbWC = Transforms.pointToGLWindowCoordinates(
  154. projectionMatrix,
  155. viewportTransformation,
  156. sunPositionEC,
  157. sunPositionEC
  158. );
  159. const sunSize =
  160. Cartesian2.magnitude(Cartesian2.subtract(limbWC, sunPositionWC, limbWC)) *
  161. 30.0 *
  162. 2.0;
  163. const size = sizeScratch;
  164. size.x = sunSize;
  165. size.y = sunSize;
  166. postProcess._uCenter = Cartesian2.clone(sunPositionWC, postProcess._uCenter);
  167. postProcess._uRadius = Math.max(size.x, size.y) * 0.15;
  168. const width = context.drawingBufferWidth;
  169. const height = context.drawingBufferHeight;
  170. const stages = postProcess._stages;
  171. const firstStage = stages.get(0);
  172. const downSampleWidth = firstStage.outputTexture.width;
  173. const downSampleHeight = firstStage.outputTexture.height;
  174. const downSampleViewport = new BoundingRectangle();
  175. downSampleViewport.width = downSampleWidth;
  176. downSampleViewport.height = downSampleHeight;
  177. // create down sampled render state
  178. viewportTransformation = Matrix4.computeViewportTransformation(
  179. downSampleViewport,
  180. 0.0,
  181. 1.0,
  182. postProcessMatrix4Scratch
  183. );
  184. sunPositionWC = Transforms.pointToGLWindowCoordinates(
  185. viewProjectionMatrix,
  186. viewportTransformation,
  187. sunPosition,
  188. sunPositionWCScratch
  189. );
  190. size.x *= downSampleWidth / width;
  191. size.y *= downSampleHeight / height;
  192. const scissorRectangle = firstStage.scissorRectangle;
  193. scissorRectangle.x = Math.max(sunPositionWC.x - size.x * 0.5, 0.0);
  194. scissorRectangle.y = Math.max(sunPositionWC.y - size.y * 0.5, 0.0);
  195. scissorRectangle.width = Math.min(size.x, width);
  196. scissorRectangle.height = Math.min(size.y, height);
  197. for (let i = 1; i < 4; ++i) {
  198. BoundingRectangle.clone(scissorRectangle, stages.get(i).scissorRectangle);
  199. }
  200. }
  201. SunPostProcess.prototype.clear = function (context, passState, clearColor) {
  202. this._sceneFramebuffer.clear(context, passState, clearColor);
  203. this._textureCache.clear(context);
  204. };
  205. SunPostProcess.prototype.update = function (passState) {
  206. const context = passState.context;
  207. const viewport = passState.viewport;
  208. const sceneFramebuffer = this._sceneFramebuffer;
  209. sceneFramebuffer.update(context, viewport);
  210. const framebuffer = sceneFramebuffer.framebuffer;
  211. this._textureCache.update(context);
  212. this._stages.update(context, false);
  213. updateSunPosition(this, context, viewport);
  214. return framebuffer;
  215. };
  216. SunPostProcess.prototype.execute = function (context) {
  217. const colorTexture = this._sceneFramebuffer.framebuffer.getColorTexture(0);
  218. const stages = this._stages;
  219. const length = stages.length;
  220. stages.get(0).execute(context, colorTexture);
  221. for (let i = 1; i < length; ++i) {
  222. stages.get(i).execute(context, stages.get(i - 1).outputTexture);
  223. }
  224. };
  225. SunPostProcess.prototype.copy = function (context, framebuffer) {
  226. if (!defined(this._copyColorCommand)) {
  227. const that = this;
  228. this._copyColorCommand = context.createViewportQuadCommand(PassThrough, {
  229. uniformMap: {
  230. colorTexture: function () {
  231. return that._stages.get(that._stages.length - 1).outputTexture;
  232. },
  233. },
  234. owner: this,
  235. });
  236. }
  237. this._copyColorCommand.framebuffer = framebuffer;
  238. this._copyColorCommand.execute(context);
  239. };
  240. SunPostProcess.prototype.isDestroyed = function () {
  241. return false;
  242. };
  243. SunPostProcess.prototype.destroy = function () {
  244. this._textureCache.destroy();
  245. this._stages.destroy();
  246. return destroyObject(this);
  247. };
  248. export default SunPostProcess;