SunPostProcess.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /*global define*/
  2. define([
  3. '../Core/BoundingRectangle',
  4. '../Core/Cartesian2',
  5. '../Core/Cartesian4',
  6. '../Core/Color',
  7. '../Core/defaultValue',
  8. '../Core/defined',
  9. '../Core/destroyObject',
  10. '../Core/Math',
  11. '../Core/Matrix4',
  12. '../Core/PixelFormat',
  13. '../Core/Transforms',
  14. '../Renderer/ClearCommand',
  15. '../Renderer/PassState',
  16. '../Renderer/PixelDatatype',
  17. '../Renderer/RenderbufferFormat',
  18. '../Shaders/PostProcessFilters/AdditiveBlend',
  19. '../Shaders/PostProcessFilters/BrightPass',
  20. '../Shaders/PostProcessFilters/GaussianBlur1D',
  21. '../Shaders/PostProcessFilters/PassThrough'
  22. ], function(
  23. BoundingRectangle,
  24. Cartesian2,
  25. Cartesian4,
  26. Color,
  27. defaultValue,
  28. defined,
  29. destroyObject,
  30. CesiumMath,
  31. Matrix4,
  32. PixelFormat,
  33. Transforms,
  34. ClearCommand,
  35. PassState,
  36. PixelDatatype,
  37. RenderbufferFormat,
  38. AdditiveBlend,
  39. BrightPass,
  40. GaussianBlur1D,
  41. PassThrough) {
  42. "use strict";
  43. var SunPostProcess = function() {
  44. this._fbo = undefined;
  45. this._downSampleFBO1 = undefined;
  46. this._downSampleFBO2 = undefined;
  47. this._clearFBO1Command = undefined;
  48. this._clearFBO2Command = undefined;
  49. this._downSampleCommand = undefined;
  50. this._brightPassCommand = undefined;
  51. this._blurXCommand = undefined;
  52. this._blurYCommand = undefined;
  53. this._blendCommand = undefined;
  54. this._fullScreenCommand = undefined;
  55. this._downSamplePassState = new PassState();
  56. this._downSamplePassState.scissorTest = {
  57. enable : true,
  58. rectangle : new BoundingRectangle()
  59. };
  60. this._upSamplePassState = new PassState();
  61. this._upSamplePassState.scissorTest = {
  62. enabled : true,
  63. rectangle : new BoundingRectangle()
  64. };
  65. this._uCenter = new Cartesian2();
  66. this._uRadius = undefined;
  67. this._blurStep = new Cartesian2();
  68. };
  69. SunPostProcess.prototype.clear = function(context, color) {
  70. var clear = this._clearFBO1Command;
  71. Color.clone(defaultValue(color, Color.BLACK), clear.color);
  72. clear.execute(context);
  73. clear = this._clearFBO2Command;
  74. Color.clone(defaultValue(color, Color.BLACK), clear.color);
  75. clear.execute(context);
  76. };
  77. SunPostProcess.prototype.execute = function(context, framebuffer) {
  78. this._downSampleCommand.execute(context, this._downSamplePassState);
  79. this._brightPassCommand.execute(context, this._downSamplePassState);
  80. this._blurXCommand.execute(context, this._downSamplePassState);
  81. this._blurYCommand.execute(context, this._downSamplePassState);
  82. this._fullScreenCommand.framebuffer = framebuffer;
  83. this._blendCommand.framebuffer = framebuffer;
  84. this._fullScreenCommand.execute(context);
  85. this._blendCommand.execute(context, this._upSamplePassState);
  86. };
  87. var viewportBoundingRectangle = new BoundingRectangle();
  88. var downSampleViewportBoundingRectangle = new BoundingRectangle();
  89. var sunPositionECScratch = new Cartesian4();
  90. var sunPositionWCScratch = new Cartesian2();
  91. var sizeScratch = new Cartesian2();
  92. var postProcessMatrix4Scratch= new Matrix4();
  93. SunPostProcess.prototype.update = function(context) {
  94. var width = context.drawingBufferWidth;
  95. var height = context.drawingBufferHeight;
  96. var that = this;
  97. if (!defined(this._downSampleCommand)) {
  98. this._clearFBO1Command = new ClearCommand({
  99. color : new Color()
  100. });
  101. this._clearFBO2Command = new ClearCommand({
  102. color : new Color()
  103. });
  104. var rs;
  105. var uniformMap = {};
  106. this._downSampleCommand = context.createViewportQuadCommand(PassThrough, {
  107. renderState : rs,
  108. uniformMap : uniformMap,
  109. owner : this
  110. });
  111. uniformMap = {
  112. u_avgLuminance : function() {
  113. // A guess at the average luminance across the entire scene
  114. return 0.5;
  115. },
  116. u_threshold : function() {
  117. return 0.25;
  118. },
  119. u_offset : function() {
  120. return 0.1;
  121. }
  122. };
  123. this._brightPassCommand = context.createViewportQuadCommand(BrightPass, {
  124. renderState : rs,
  125. uniformMap : uniformMap,
  126. owner : this
  127. });
  128. var delta = 1.0;
  129. var sigma = 2.0;
  130. uniformMap = {
  131. delta : function() {
  132. return delta;
  133. },
  134. sigma : function() {
  135. return sigma;
  136. },
  137. direction : function() {
  138. return 0.0;
  139. }
  140. };
  141. this._blurXCommand = context.createViewportQuadCommand(GaussianBlur1D, {
  142. renderState : rs,
  143. uniformMap : uniformMap,
  144. owner : this
  145. });
  146. uniformMap = {
  147. delta : function() {
  148. return delta;
  149. },
  150. sigma : function() {
  151. return sigma;
  152. },
  153. direction : function() {
  154. return 1.0;
  155. }
  156. };
  157. this._blurYCommand = context.createViewportQuadCommand(GaussianBlur1D, {
  158. renderState : rs,
  159. uniformMap : uniformMap,
  160. owner : this
  161. });
  162. uniformMap = {
  163. u_center : function() {
  164. return that._uCenter;
  165. },
  166. u_radius : function() {
  167. return that._uRadius;
  168. }
  169. };
  170. this._blendCommand = context.createViewportQuadCommand(AdditiveBlend, {
  171. renderState : rs,
  172. uniformMap : uniformMap,
  173. owner : this
  174. });
  175. uniformMap = {};
  176. this._fullScreenCommand = context.createViewportQuadCommand(PassThrough, {
  177. renderState : rs,
  178. uniformMap : uniformMap,
  179. owner : this
  180. });
  181. }
  182. var downSampleWidth = Math.pow(2.0, Math.ceil(Math.log(width) / Math.log(2)) - 2.0);
  183. var downSampleHeight = Math.pow(2.0, Math.ceil(Math.log(height) / Math.log(2)) - 2.0);
  184. var downSampleSize = Math.max(downSampleWidth, downSampleHeight);
  185. var viewport = viewportBoundingRectangle;
  186. viewport.width = width;
  187. viewport.height = height;
  188. var downSampleViewport = downSampleViewportBoundingRectangle;
  189. downSampleViewport.width = downSampleSize;
  190. downSampleViewport.height = downSampleSize;
  191. var fbo = this._fbo;
  192. var colorTexture = (defined(fbo) && fbo.getColorTexture(0)) || undefined;
  193. if (!defined(colorTexture) || colorTexture.width !== width || colorTexture.height !== height) {
  194. fbo = fbo && fbo.destroy();
  195. this._downSampleFBO1 = this._downSampleFBO1 && this._downSampleFBO1.destroy();
  196. this._downSampleFBO2 = this._downSampleFBO2 && this._downSampleFBO2.destroy();
  197. this._blurStep.x = this._blurStep.y = 1.0 / downSampleSize;
  198. var colorTextures = [context.createTexture2D({
  199. width : width,
  200. height : height
  201. })];
  202. if (context.depthTexture) {
  203. fbo = this._fbo = context.createFramebuffer({
  204. colorTextures :colorTextures,
  205. depthTexture : context.createTexture2D({
  206. width : width,
  207. height : height,
  208. pixelFormat : PixelFormat.DEPTH_COMPONENT,
  209. pixelDatatype : PixelDatatype.UNSIGNED_SHORT
  210. })
  211. });
  212. } else {
  213. fbo = this._fbo = context.createFramebuffer({
  214. colorTextures : colorTextures,
  215. depthRenderbuffer : context.createRenderbuffer({
  216. format : RenderbufferFormat.DEPTH_COMPONENT16
  217. })
  218. });
  219. }
  220. this._downSampleFBO1 = context.createFramebuffer({
  221. colorTextures : [context.createTexture2D({
  222. width : downSampleSize,
  223. height : downSampleSize
  224. })]
  225. });
  226. this._downSampleFBO2 = context.createFramebuffer({
  227. colorTextures : [context.createTexture2D({
  228. width : downSampleSize,
  229. height : downSampleSize
  230. })]
  231. });
  232. this._clearFBO1Command.framebuffer = this._downSampleFBO1;
  233. this._clearFBO2Command.framebuffer = this._downSampleFBO2;
  234. this._downSampleCommand.framebuffer = this._downSampleFBO1;
  235. this._brightPassCommand.framebuffer = this._downSampleFBO2;
  236. this._blurXCommand.framebuffer = this._downSampleFBO1;
  237. this._blurYCommand.framebuffer = this._downSampleFBO2;
  238. var downSampleRenderState = context.createRenderState({
  239. viewport : downSampleViewport
  240. });
  241. var upSampleRenderState = context.createRenderState();
  242. this._downSampleCommand.uniformMap.u_texture = function() {
  243. return fbo.getColorTexture(0);
  244. };
  245. this._downSampleCommand.renderState = downSampleRenderState;
  246. this._brightPassCommand.uniformMap.u_texture = function() {
  247. return that._downSampleFBO1.getColorTexture(0);
  248. };
  249. this._brightPassCommand.renderState = downSampleRenderState;
  250. this._blurXCommand.uniformMap.u_texture = function() {
  251. return that._downSampleFBO2.getColorTexture(0);
  252. };
  253. this._blurXCommand.uniformMap.u_step = function() {
  254. return that._blurStep;
  255. };
  256. this._blurXCommand.renderState = downSampleRenderState;
  257. this._blurYCommand.uniformMap.u_texture = function() {
  258. return that._downSampleFBO1.getColorTexture(0);
  259. };
  260. this._blurYCommand.uniformMap.u_step = function() {
  261. return that._blurStep;
  262. };
  263. this._blurYCommand.renderState = downSampleRenderState;
  264. this._blendCommand.uniformMap.u_texture0 = function() {
  265. return fbo.getColorTexture(0);
  266. };
  267. this._blendCommand.uniformMap.u_texture1 = function() {
  268. return that._downSampleFBO2.getColorTexture(0);
  269. };
  270. this._blendCommand.renderState = upSampleRenderState;
  271. this._fullScreenCommand.uniformMap.u_texture = function() {
  272. return fbo.getColorTexture(0);
  273. };
  274. this._fullScreenCommand.renderState = upSampleRenderState;
  275. }
  276. var us = context.uniformState;
  277. var sunPosition = us.sunPositionWC;
  278. var viewMatrix = us.view;
  279. var viewProjectionMatrix = us.viewProjection;
  280. var projectionMatrix = us.projection;
  281. // create up sampled render state
  282. var viewportTransformation = Matrix4.computeViewportTransformation(viewport, 0.0, 1.0, postProcessMatrix4Scratch);
  283. var sunPositionEC = Matrix4.multiplyByPoint(viewMatrix, sunPosition, sunPositionECScratch);
  284. var sunPositionWC = Transforms.pointToGLWindowCoordinates(viewProjectionMatrix, viewportTransformation, sunPosition, sunPositionWCScratch);
  285. sunPositionEC.x += CesiumMath.SOLAR_RADIUS;
  286. var limbWC = Transforms.pointToGLWindowCoordinates(projectionMatrix, viewportTransformation, sunPositionEC, sunPositionEC);
  287. var sunSize = Cartesian2.magnitude(Cartesian2.subtract(limbWC, sunPositionWC, limbWC)) * 30.0 * 2.0;
  288. var size = sizeScratch;
  289. size.x = sunSize;
  290. size.y = sunSize;
  291. var scissorRectangle = this._upSamplePassState.scissorTest.rectangle;
  292. scissorRectangle.x = Math.max(sunPositionWC.x - size.x * 0.5, 0.0);
  293. scissorRectangle.y = Math.max(sunPositionWC.y - size.y * 0.5, 0.0);
  294. scissorRectangle.width = Math.min(size.x, width);
  295. scissorRectangle.height = Math.min(size.y, height);
  296. this._uCenter = Cartesian2.clone(sunPositionWC, this._uCenter);
  297. this._uRadius = Math.max(size.x, size.y) * 0.5;
  298. // create down sampled render state
  299. viewportTransformation = Matrix4.computeViewportTransformation(downSampleViewport, 0.0, 1.0, postProcessMatrix4Scratch);
  300. sunPositionWC = Transforms.pointToGLWindowCoordinates(viewProjectionMatrix, viewportTransformation, sunPosition, sunPositionWCScratch);
  301. size.x *= downSampleWidth / width;
  302. size.y *= downSampleHeight / height;
  303. scissorRectangle = this._downSamplePassState.scissorTest.rectangle;
  304. scissorRectangle.x = Math.max(sunPositionWC.x - size.x * 0.5, 0.0);
  305. scissorRectangle.y = Math.max(sunPositionWC.y - size.y * 0.5, 0.0);
  306. scissorRectangle.width = Math.min(size.x, width);
  307. scissorRectangle.height = Math.min(size.y, height);
  308. this._downSamplePassState.context = context;
  309. this._upSamplePassState.context = context;
  310. return this._fbo;
  311. };
  312. SunPostProcess.prototype.isDestroyed = function() {
  313. return false;
  314. };
  315. SunPostProcess.prototype.destroy = function() {
  316. this._fbo = this._fbo && this._fbo.destroy();
  317. this._downSampleFBO1 = this._downSampleFBO1 && this._downSampleFBO1.destroy();
  318. this._downSampleFBO2 = this._downSampleFBO2 && this._downSampleFBO2.destroy();
  319. this._downSampleCommand = this._downSampleCommand && this._downSampleCommand.shaderProgram && this._downSampleCommand.shaderProgram.destroy();
  320. this._brightPassCommand = this._brightPassCommand && this._brightPassCommand.shaderProgram && this._brightPassCommand.shaderProgram.destroy();
  321. this._blurXCommand = this._blurXCommand && this._blurXCommand.shaderProgram && this._blurXCommand.shaderProgram.destroy();
  322. this._blurYCommand = this._blurYCommand && this._blurYCommand.shaderProgram && this._blurYCommand.shaderProgram.destroy();
  323. this._blendCommand = this._blendCommand && this._blendCommand.shaderProgram && this._blendCommand.shaderProgram.destroy();
  324. this._fullScreenCommand = this._fullScreenCommand && this._fullScreenCommand.shaderProgram && this._fullScreenCommand.shaderProgram.destroy();
  325. return destroyObject(this);
  326. };
  327. return SunPostProcess;
  328. });