PostProcessStageLibrary.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. import buildModuleUrl from '../Core/buildModuleUrl.js';
  2. import Color from '../Core/Color.js';
  3. import createGuid from '../Core/createGuid.js';
  4. import defined from '../Core/defined.js';
  5. import defineProperties from '../Core/defineProperties.js';
  6. import Ellipsoid from '../Core/Ellipsoid.js';
  7. import AcesTonemapping from '../Shaders/PostProcessStages/AcesTonemappingStage.js';
  8. import AmbientOcclusionGenerate from '../Shaders/PostProcessStages/AmbientOcclusionGenerate.js';
  9. import AmbientOcclusionModulate from '../Shaders/PostProcessStages/AmbientOcclusionModulate.js';
  10. import BlackAndWhite from '../Shaders/PostProcessStages/BlackAndWhite.js';
  11. import BloomComposite from '../Shaders/PostProcessStages/BloomComposite.js';
  12. import Brightness from '../Shaders/PostProcessStages/Brightness.js';
  13. import ContrastBias from '../Shaders/PostProcessStages/ContrastBias.js';
  14. import DepthOfField from '../Shaders/PostProcessStages/DepthOfField.js';
  15. import DepthView from '../Shaders/PostProcessStages/DepthView.js';
  16. import EdgeDetection from '../Shaders/PostProcessStages/EdgeDetection.js';
  17. import FilmicTonemapping from '../Shaders/PostProcessStages/FilmicTonemapping.js';
  18. import FXAA from '../Shaders/PostProcessStages/FXAA.js';
  19. import GaussianBlur1D from '../Shaders/PostProcessStages/GaussianBlur1D.js';
  20. import LensFlare from '../Shaders/PostProcessStages/LensFlare.js';
  21. import ModifiedReinhardTonemapping from '../Shaders/PostProcessStages/ModifiedReinhardTonemapping.js';
  22. import NightVision from '../Shaders/PostProcessStages/NightVision.js';
  23. import ReinhardTonemapping from '../Shaders/PostProcessStages/ReinhardTonemapping.js';
  24. import Silhouette from '../Shaders/PostProcessStages/Silhouette.js';
  25. import FXAA3_11 from '../ThirdParty/Shaders/FXAA3_11.js';
  26. import AutoExposure from './AutoExposure.js';
  27. import PostProcessStage from './PostProcessStage.js';
  28. import PostProcessStageComposite from './PostProcessStageComposite.js';
  29. import PostProcessStageSampleMode from './PostProcessStageSampleMode.js';
  30. /**
  31. * Contains functions for creating common post-process stages.
  32. *
  33. * @exports PostProcessStageLibrary
  34. */
  35. var PostProcessStageLibrary = {};
  36. function createBlur(name) {
  37. var delta = 1.0;
  38. var sigma = 2.0;
  39. var stepSize = 1.0;
  40. var blurShader = '#define USE_STEP_SIZE\n' + GaussianBlur1D;
  41. var blurX = new PostProcessStage({
  42. name : name + '_x_direction',
  43. fragmentShader : blurShader,
  44. uniforms: {
  45. delta : delta,
  46. sigma : sigma,
  47. stepSize : stepSize,
  48. direction : 0.0
  49. },
  50. sampleMode : PostProcessStageSampleMode.LINEAR
  51. });
  52. var blurY = new PostProcessStage({
  53. name : name + '_y_direction',
  54. fragmentShader : blurShader,
  55. uniforms: {
  56. delta : delta,
  57. sigma : sigma,
  58. stepSize : stepSize,
  59. direction : 1.0
  60. },
  61. sampleMode : PostProcessStageSampleMode.LINEAR
  62. });
  63. var uniforms = {};
  64. defineProperties(uniforms, {
  65. delta : {
  66. get : function() {
  67. return blurX.uniforms.delta;
  68. },
  69. set : function(value) {
  70. var blurXUniforms = blurX.uniforms;
  71. var blurYUniforms = blurY.uniforms;
  72. blurXUniforms.delta = blurYUniforms.delta = value;
  73. }
  74. },
  75. sigma : {
  76. get : function() {
  77. return blurX.uniforms.sigma;
  78. },
  79. set : function(value) {
  80. var blurXUniforms = blurX.uniforms;
  81. var blurYUniforms = blurY.uniforms;
  82. blurXUniforms.sigma = blurYUniforms.sigma = value;
  83. }
  84. },
  85. stepSize : {
  86. get : function() {
  87. return blurX.uniforms.stepSize;
  88. },
  89. set : function(value) {
  90. var blurXUniforms = blurX.uniforms;
  91. var blurYUniforms = blurY.uniforms;
  92. blurXUniforms.stepSize = blurYUniforms.stepSize = value;
  93. }
  94. }
  95. });
  96. return new PostProcessStageComposite({
  97. name : name,
  98. stages : [blurX, blurY],
  99. uniforms : uniforms
  100. });
  101. }
  102. /**
  103. * Creates a post-process stage that applies a Gaussian blur to the input texture. This stage is usually applied in conjunction with another stage.
  104. * <p>
  105. * This stage has the following uniforms: <code>delta</code>, <code>sigma</code>, and <code>stepSize</code>.
  106. * </p>
  107. * <p>
  108. * <code>delta</code> and <code>sigma</code> are used to compute the weights of a Gaussian filter. The equation is <code>exp((-0.5 * delta * delta) / (sigma * sigma))</code>.
  109. * The default value for <code>delta</code> is <code>1.0</code>. The default value for <code>sigma</code> is <code>2.0</code>.
  110. * <code>stepSize</code> is the distance to the next texel. The default is <code>1.0</code>.
  111. * </p>
  112. * @return {PostProcessStageComposite} A post-process stage that applies a Gaussian blur to the input texture.
  113. */
  114. PostProcessStageLibrary.createBlurStage = function() {
  115. return createBlur('czm_blur');
  116. };
  117. /**
  118. * Creates a post-process stage that applies a depth of field effect.
  119. * <p>
  120. * Depth of field simulates camera focus. Objects in the scene that are in focus
  121. * will be clear whereas objects not in focus will be blurred.
  122. * </p>
  123. * <p>
  124. * This stage has the following uniforms: <code>focalDistance</code>, <code>delta</code>, <code>sigma</code>, and <code>stepSize</code>.
  125. * </p>
  126. * <p>
  127. * <code>focalDistance</code> is the distance in meters from the camera to set the camera focus.
  128. * </p>
  129. * <p>
  130. * <code>delta</code>, <code>sigma</code>, and <code>stepSize</code> are the same properties as {@link PostProcessStageLibrary#createBlurStage}.
  131. * The blur is applied to the areas out of focus.
  132. * </p>
  133. * @return {PostProcessStageComposite} A post-process stage that applies a depth of field effect.
  134. */
  135. PostProcessStageLibrary.createDepthOfFieldStage = function() {
  136. var blur = createBlur('czm_depth_of_field_blur');
  137. var dof = new PostProcessStage({
  138. name : 'czm_depth_of_field_composite',
  139. fragmentShader : DepthOfField,
  140. uniforms : {
  141. focalDistance : 5.0,
  142. blurTexture : blur.name
  143. }
  144. });
  145. var uniforms = {};
  146. defineProperties(uniforms, {
  147. focalDistance : {
  148. get : function() {
  149. return dof.uniforms.focalDistance;
  150. },
  151. set : function(value) {
  152. dof.uniforms.focalDistance = value;
  153. }
  154. },
  155. delta : {
  156. get : function() {
  157. return blur.uniforms.delta;
  158. },
  159. set : function(value) {
  160. blur.uniforms.delta = value;
  161. }
  162. },
  163. sigma : {
  164. get : function() {
  165. return blur.uniforms.sigma;
  166. },
  167. set : function(value) {
  168. blur.uniforms.sigma = value;
  169. }
  170. },
  171. stepSize : {
  172. get : function() {
  173. return blur.uniforms.stepSize;
  174. },
  175. set : function(value) {
  176. blur.uniforms.stepSize = value;
  177. }
  178. }
  179. });
  180. return new PostProcessStageComposite({
  181. name : 'czm_depth_of_field',
  182. stages : [blur, dof],
  183. inputPreviousStageTexture : false,
  184. uniforms : uniforms
  185. });
  186. };
  187. /**
  188. * Whether or not a depth of field stage is supported.
  189. * <p>
  190. * This stage requires the WEBGL_depth_texture extension.
  191. * </p>
  192. *
  193. * @param {Scene} scene The scene.
  194. * @return {Boolean} Whether this post process stage is supported.
  195. *
  196. * @see {Context#depthTexture}
  197. * @see {@link http://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/|WEBGL_depth_texture}
  198. */
  199. PostProcessStageLibrary.isDepthOfFieldSupported = function(scene) {
  200. return scene.context.depthTexture;
  201. };
  202. /**
  203. * Creates a post-process stage that detects edges.
  204. * <p>
  205. * Writes the color to the output texture with alpha set to 1.0 when it is on an edge.
  206. * </p>
  207. * <p>
  208. * This stage has the following uniforms: <code>color</code> and <code>length</code>
  209. * </p>
  210. * <ul>
  211. * <li><code>color</code> is the color of the highlighted edge. The default is {@link Color#BLACK}.</li>
  212. * <li><code>length</code> is the length of the edges in pixels. The default is <code>0.5</code>.</li>
  213. * </ul>
  214. * <p>
  215. * This stage is not supported in 2D.
  216. * </p>
  217. * @return {PostProcessStageComposite} A post-process stage that applies an edge detection effect.
  218. *
  219. * @example
  220. * // multiple silhouette effects
  221. * var yellowEdge = Cesium.PostProcessLibrary.createEdgeDetectionStage();
  222. * yellowEdge.uniforms.color = Cesium.Color.YELLOW;
  223. * yellowEdge.selected = [feature0];
  224. *
  225. * var greenEdge = Cesium.PostProcessLibrary.createEdgeDetectionStage();
  226. * greenEdge.uniforms.color = Cesium.Color.LIME;
  227. * greenEdge.selected = [feature1];
  228. *
  229. * // draw edges around feature0 and feature1
  230. * postProcessStages.add(Cesium.PostProcessLibrary.createSilhouetteEffect([yellowEdge, greenEdge]);
  231. */
  232. PostProcessStageLibrary.createEdgeDetectionStage = function() {
  233. // unique name generated on call so more than one effect can be added
  234. var name = createGuid();
  235. return new PostProcessStage({
  236. name : 'czm_edge_detection_' + name,
  237. fragmentShader : EdgeDetection,
  238. uniforms : {
  239. length : 0.25,
  240. color : Color.clone(Color.BLACK)
  241. }
  242. });
  243. };
  244. /**
  245. * Whether or not an edge detection stage is supported.
  246. * <p>
  247. * This stage requires the WEBGL_depth_texture extension.
  248. * </p>
  249. *
  250. * @param {Scene} scene The scene.
  251. * @return {Boolean} Whether this post process stage is supported.
  252. *
  253. * @see {Context#depthTexture}
  254. * @see {@link http://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/|WEBGL_depth_texture}
  255. */
  256. PostProcessStageLibrary.isEdgeDetectionSupported = function(scene) {
  257. return scene.context.depthTexture;
  258. };
  259. function getSilhouetteEdgeDetection(edgeDetectionStages) {
  260. if (!defined(edgeDetectionStages)) {
  261. return PostProcessStageLibrary.createEdgeDetectionStage();
  262. }
  263. var edgeDetection = new PostProcessStageComposite({
  264. name : 'czm_edge_detection_multiple',
  265. stages : edgeDetectionStages,
  266. inputPreviousStageTexture : false
  267. });
  268. var compositeUniforms = {};
  269. var fsDecl = '';
  270. var fsLoop = '';
  271. for (var i = 0; i < edgeDetectionStages.length; ++i) {
  272. fsDecl += 'uniform sampler2D edgeTexture' + i + '; \n';
  273. fsLoop +=
  274. ' vec4 edge' + i + ' = texture2D(edgeTexture' + i + ', v_textureCoordinates); \n' +
  275. ' if (edge' + i + '.a > 0.0) \n' +
  276. ' { \n' +
  277. ' color = edge' + i + '; \n' +
  278. ' break; \n' +
  279. ' } \n';
  280. compositeUniforms['edgeTexture' + i] = edgeDetectionStages[i].name;
  281. }
  282. var fs =
  283. fsDecl +
  284. 'varying vec2 v_textureCoordinates; \n' +
  285. 'void main() { \n' +
  286. ' vec4 color = vec4(0.0); \n' +
  287. ' for (int i = 0; i < ' + edgeDetectionStages.length + '; i++) \n' +
  288. ' { \n' +
  289. fsLoop +
  290. ' } \n' +
  291. ' gl_FragColor = color; \n' +
  292. '} \n';
  293. var edgeComposite = new PostProcessStage({
  294. name : 'czm_edge_detection_combine',
  295. fragmentShader : fs,
  296. uniforms : compositeUniforms
  297. });
  298. return new PostProcessStageComposite({
  299. name : 'czm_edge_detection_composite',
  300. stages : [edgeDetection, edgeComposite]
  301. });
  302. }
  303. /**
  304. * Creates a post-process stage that applies a silhouette effect.
  305. * <p>
  306. * A silhouette effect composites the color from the edge detection pass with input color texture.
  307. * </p>
  308. * <p>
  309. * This stage has the following uniforms when <code>edgeDetectionStages</code> is <code>undefined</code>: <code>color</code> and <code>length</code>
  310. * </p>
  311. * <p>
  312. * <code>color</code> is the color of the highlighted edge. The default is {@link Color#BLACK}.
  313. * <code>length</code> is the length of the edges in pixels. The default is <code>0.5</code>.
  314. * </p>
  315. * @return {PostProcessStageComposite} A post-process stage that applies a silhouette effect.
  316. */
  317. PostProcessStageLibrary.createSilhouetteStage = function(edgeDetectionStages) {
  318. var edgeDetection = getSilhouetteEdgeDetection(edgeDetectionStages);
  319. var silhouetteProcess = new PostProcessStage({
  320. name : 'czm_silhouette_color_edges',
  321. fragmentShader : Silhouette,
  322. uniforms : {
  323. silhouetteTexture : edgeDetection.name
  324. }
  325. });
  326. return new PostProcessStageComposite({
  327. name : 'czm_silhouette',
  328. stages : [edgeDetection, silhouetteProcess],
  329. inputPreviousStageTexture : false,
  330. uniforms : edgeDetection.uniforms
  331. });
  332. };
  333. /**
  334. * Whether or not a silhouette stage is supported.
  335. * <p>
  336. * This stage requires the WEBGL_depth_texture extension.
  337. * </p>
  338. *
  339. * @param {Scene} scene The scene.
  340. * @return {Boolean} Whether this post process stage is supported.
  341. *
  342. * @see {Context#depthTexture}
  343. * @see {@link http://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/|WEBGL_depth_texture}
  344. */
  345. PostProcessStageLibrary.isSilhouetteSupported = function(scene) {
  346. return scene.context.depthTexture;
  347. };
  348. /**
  349. * Creates a post-process stage that applies a bloom effect to the input texture.
  350. * <p>
  351. * A bloom effect adds glow effect, makes bright areas brighter, and dark areas darker.
  352. * </p>
  353. * <p>
  354. * This post-process stage has the following uniforms: <code>contrast</code>, <code>brightness</code>, <code>glowOnly</code>,
  355. * <code>delta</code>, <code>sigma</code>, and <code>stepSize</code>.
  356. * </p>
  357. * <ul>
  358. * <li><code>contrast</code> is a scalar value in the range [-255.0, 255.0] and affects the contract of the effect. The default value is <code>128.0</code>.</li>
  359. * <li><code>brightness</code> is a scalar value. The input texture RGB value is converted to hue, saturation, and brightness (HSB) then this value is
  360. * added to the brightness. The default value is <code>-0.3</code>.</li>
  361. * <li><code>glowOnly</code> is a boolean value. When <code>true</code>, only the glow effect will be shown. When <code>false</code>, the glow will be added to the input texture.
  362. * The default value is <code>false</code>. This is a debug option for viewing the effects when changing the other uniform values.</li>
  363. * </ul>
  364. * <p>
  365. * <code>delta</code>, <code>sigma</code>, and <code>stepSize</code> are the same properties as {@link PostProcessStageLibrary#createBlurStage}.
  366. * </p>
  367. * @return {PostProcessStageComposite} A post-process stage to applies a bloom effect.
  368. *
  369. * @private
  370. */
  371. PostProcessStageLibrary.createBloomStage = function() {
  372. var contrastBias = new PostProcessStage({
  373. name : 'czm_bloom_contrast_bias',
  374. fragmentShader : ContrastBias,
  375. uniforms : {
  376. contrast : 128.0,
  377. brightness : -0.3
  378. }
  379. });
  380. var blur = createBlur('czm_bloom_blur');
  381. var generateComposite = new PostProcessStageComposite({
  382. name : 'czm_bloom_contrast_bias_blur',
  383. stages : [contrastBias, blur]
  384. });
  385. var bloomComposite = new PostProcessStage({
  386. name : 'czm_bloom_generate_composite',
  387. fragmentShader : BloomComposite,
  388. uniforms : {
  389. glowOnly : false,
  390. bloomTexture : generateComposite.name
  391. }
  392. });
  393. var uniforms = {};
  394. defineProperties(uniforms, {
  395. glowOnly : {
  396. get : function() {
  397. return bloomComposite.uniforms.glowOnly;
  398. },
  399. set : function(value) {
  400. bloomComposite.uniforms.glowOnly = value;
  401. }
  402. },
  403. contrast : {
  404. get : function() {
  405. return contrastBias.uniforms.contrast;
  406. },
  407. set : function(value) {
  408. contrastBias.uniforms.contrast = value;
  409. }
  410. },
  411. brightness : {
  412. get : function() {
  413. return contrastBias.uniforms.brightness;
  414. },
  415. set : function(value) {
  416. contrastBias.uniforms.brightness = value;
  417. }
  418. },
  419. delta : {
  420. get : function() {
  421. return blur.uniforms.delta;
  422. },
  423. set : function(value) {
  424. blur.uniforms.delta = value;
  425. }
  426. },
  427. sigma : {
  428. get : function() {
  429. return blur.uniforms.sigma;
  430. },
  431. set : function(value) {
  432. blur.uniforms.sigma = value;
  433. }
  434. },
  435. stepSize : {
  436. get : function() {
  437. return blur.uniforms.stepSize;
  438. },
  439. set : function(value) {
  440. blur.uniforms.stepSize = value;
  441. }
  442. }
  443. });
  444. return new PostProcessStageComposite({
  445. name : 'czm_bloom',
  446. stages : [generateComposite, bloomComposite],
  447. inputPreviousStageTexture : false,
  448. uniforms : uniforms
  449. });
  450. };
  451. /**
  452. * Creates a post-process stage that Horizon-based Ambient Occlusion (HBAO) to the input texture.
  453. * <p>
  454. * Ambient occlusion simulates shadows from ambient light. These shadows would always be present when the
  455. * surface receives light and regardless of the light's position.
  456. * </p>
  457. * <p>
  458. * The uniforms have the following properties: <code>intensity</code>, <code>bias</code>, <code>lengthCap</code>,
  459. * <code>stepSize</code>, <code>frustumLength</code>, <code>randomTexture</code>, <code>ambientOcclusionOnly</code>,
  460. * <code>delta</code>, <code>sigma</code>, and <code>blurStepSize</code>.
  461. * </p>
  462. * <ul>
  463. * <li><code>intensity</code> is a scalar value used to lighten or darken the shadows exponentially. Higher values make the shadows darker. The default value is <code>3.0</code>.</li>
  464. * <li><code>bias</code> is a scalar value representing an angle in radians. If the dot product between the normal of the sample and the vector to the camera is less than this value,
  465. * sampling stops in the current direction. This is used to remove shadows from near planar edges. The default value is <code>0.1</code>.</li>
  466. * <li><code>lengthCap</code> is a scalar value representing a length in meters. If the distance from the current sample to first sample is greater than this value,
  467. * sampling stops in the current direction. The default value is <code>0.26</code>.</li>
  468. * <li><code>stepSize</code> is a scalar value indicating the distance to the next texel sample in the current direction. The default value is <code>1.95</code>.</li>
  469. * <li><code>frustumLength</code> is a scalar value in meters. If the current fragment has a distance from the camera greater than this value, ambient occlusion is not computed for the fragment.
  470. * The default value is <code>1000.0</code>.</li>
  471. * <li><code>randomTexture</code> is a texture where the red channel is a random value in [0.0, 1.0]. The default value is <code>undefined</code>. This texture needs to be set.</li>
  472. * <li><code>ambientOcclusionOnly</code> is a boolean value. When <code>true</code>, only the shadows generated are written to the output. When <code>false</code>, the input texture is modulated
  473. * with the ambient occlusion. This is a useful debug option for seeing the effects of changing the uniform values. The default value is <code>false</code>.</li>
  474. * </ul>
  475. * <p>
  476. * <code>delta</code>, <code>sigma</code>, and <code>blurStepSize</code> are the same properties as {@link PostProcessStageLibrary#createBlurStage}.
  477. * The blur is applied to the shadows generated from the image to make them smoother.
  478. * </p>
  479. * @return {PostProcessStageComposite} A post-process stage that applies an ambient occlusion effect.
  480. *
  481. * @private
  482. */
  483. PostProcessStageLibrary.createAmbientOcclusionStage = function() {
  484. var generate = new PostProcessStage({
  485. name : 'czm_ambient_occlusion_generate',
  486. fragmentShader : AmbientOcclusionGenerate,
  487. uniforms : {
  488. intensity : 3.0,
  489. bias : 0.1,
  490. lengthCap : 0.26,
  491. stepSize : 1.95,
  492. frustumLength : 1000.0,
  493. randomTexture : undefined
  494. }
  495. });
  496. var blur = createBlur('czm_ambient_occlusion_blur');
  497. blur.uniforms.stepSize = 0.86;
  498. var generateAndBlur = new PostProcessStageComposite({
  499. name : 'czm_ambient_occlusion_generate_blur',
  500. stages : [generate, blur]
  501. });
  502. var ambientOcclusionModulate = new PostProcessStage({
  503. name : 'czm_ambient_occlusion_composite',
  504. fragmentShader : AmbientOcclusionModulate,
  505. uniforms : {
  506. ambientOcclusionOnly : false,
  507. ambientOcclusionTexture : generateAndBlur.name
  508. }
  509. });
  510. var uniforms = {};
  511. defineProperties(uniforms, {
  512. intensity : {
  513. get : function() {
  514. return generate.uniforms.intensity;
  515. },
  516. set : function(value) {
  517. generate.uniforms.intensity = value;
  518. }
  519. },
  520. bias : {
  521. get : function() {
  522. return generate.uniforms.bias;
  523. },
  524. set : function(value) {
  525. generate.uniforms.bias = value;
  526. }
  527. },
  528. lengthCap : {
  529. get : function() {
  530. return generate.uniforms.lengthCap;
  531. },
  532. set : function(value) {
  533. generate.uniforms.lengthCap = value;
  534. }
  535. },
  536. stepSize : {
  537. get : function() {
  538. return generate.uniforms.stepSize;
  539. },
  540. set : function(value) {
  541. generate.uniforms.stepSize = value;
  542. }
  543. },
  544. frustumLength : {
  545. get : function() {
  546. return generate.uniforms.frustumLength;
  547. },
  548. set : function(value) {
  549. generate.uniforms.frustumLength = value;
  550. }
  551. },
  552. randomTexture : {
  553. get : function() {
  554. return generate.uniforms.randomTexture;
  555. },
  556. set : function(value) {
  557. generate.uniforms.randomTexture = value;
  558. }
  559. },
  560. delta : {
  561. get : function() {
  562. return blur.uniforms.delta;
  563. },
  564. set : function(value) {
  565. blur.uniforms.delta = value;
  566. }
  567. },
  568. sigma : {
  569. get : function() {
  570. return blur.uniforms.sigma;
  571. },
  572. set : function(value) {
  573. blur.uniforms.sigma = value;
  574. }
  575. },
  576. blurStepSize : {
  577. get : function() {
  578. return blur.uniforms.stepSize;
  579. },
  580. set : function(value) {
  581. blur.uniforms.stepSize = value;
  582. }
  583. },
  584. ambientOcclusionOnly : {
  585. get : function() {
  586. return ambientOcclusionModulate.uniforms.ambientOcclusionOnly;
  587. },
  588. set : function(value) {
  589. ambientOcclusionModulate.uniforms.ambientOcclusionOnly = value;
  590. }
  591. }
  592. });
  593. return new PostProcessStageComposite({
  594. name : 'czm_ambient_occlusion',
  595. stages : [generateAndBlur, ambientOcclusionModulate],
  596. inputPreviousStageTexture : false,
  597. uniforms : uniforms
  598. });
  599. };
  600. /**
  601. * Whether or not an ambient occlusion stage is supported.
  602. * <p>
  603. * This stage requires the WEBGL_depth_texture extension.
  604. * </p>
  605. *
  606. * @param {Scene} scene The scene.
  607. * @return {Boolean} Whether this post process stage is supported.
  608. *
  609. * @see {Context#depthTexture}
  610. * @see {@link http://www.khronos.org/registry/webgl/extensions/WEBGL_depth_texture/|WEBGL_depth_texture}
  611. */
  612. PostProcessStageLibrary.isAmbientOcclusionSupported = function(scene) {
  613. return scene.context.depthTexture;
  614. };
  615. var fxaaFS =
  616. '#define FXAA_QUALITY_PRESET 39 \n' +
  617. FXAA3_11 + '\n' +
  618. FXAA;
  619. /**
  620. * Creates a post-process stage that applies Fast Approximate Anti-aliasing (FXAA) to the input texture.
  621. * @return {PostProcessStage} A post-process stage that applies Fast Approximate Anti-aliasing to the input texture.
  622. *
  623. * @private
  624. */
  625. PostProcessStageLibrary.createFXAAStage = function() {
  626. return new PostProcessStage({
  627. name : 'czm_FXAA',
  628. fragmentShader : fxaaFS,
  629. sampleMode : PostProcessStageSampleMode.LINEAR
  630. });
  631. };
  632. /**
  633. * Creates a post-process stage that applies ACES tonemapping operator.
  634. * @param {Boolean} useAutoExposure Whether or not to use auto-exposure.
  635. * @return {PostProcessStage} A post-process stage that applies ACES tonemapping operator.
  636. * @private
  637. */
  638. PostProcessStageLibrary.createAcesTonemappingStage = function(useAutoExposure) {
  639. var fs = useAutoExposure ? '#define AUTO_EXPOSURE\n' : '';
  640. fs += AcesTonemapping;
  641. return new PostProcessStage({
  642. name : 'czm_aces',
  643. fragmentShader : fs,
  644. uniforms : {
  645. autoExposure : undefined
  646. }
  647. });
  648. };
  649. /**
  650. * Creates a post-process stage that applies filmic tonemapping operator.
  651. * @param {Boolean} useAutoExposure Whether or not to use auto-exposure.
  652. * @return {PostProcessStage} A post-process stage that applies filmic tonemapping operator.
  653. * @private
  654. */
  655. PostProcessStageLibrary.createFilmicTonemappingStage = function(useAutoExposure) {
  656. var fs = useAutoExposure ? '#define AUTO_EXPOSURE\n' : '';
  657. fs += FilmicTonemapping;
  658. return new PostProcessStage({
  659. name : 'czm_filmic',
  660. fragmentShader : fs,
  661. uniforms : {
  662. autoExposure : undefined
  663. }
  664. });
  665. };
  666. /**
  667. * Creates a post-process stage that applies Reinhard tonemapping operator.
  668. * @param {Boolean} useAutoExposure Whether or not to use auto-exposure.
  669. * @return {PostProcessStage} A post-process stage that applies Reinhard tonemapping operator.
  670. * @private
  671. */
  672. PostProcessStageLibrary.createReinhardTonemappingStage = function(useAutoExposure) {
  673. var fs = useAutoExposure ? '#define AUTO_EXPOSURE\n' : '';
  674. fs += ReinhardTonemapping;
  675. return new PostProcessStage({
  676. name : 'czm_reinhard',
  677. fragmentShader : fs,
  678. uniforms : {
  679. autoExposure : undefined
  680. }
  681. });
  682. };
  683. /**
  684. * Creates a post-process stage that applies modified Reinhard tonemapping operator.
  685. * @param {Boolean} useAutoExposure Whether or not to use auto-exposure.
  686. * @return {PostProcessStage} A post-process stage that applies modified Reinhard tonemapping operator.
  687. * @private
  688. */
  689. PostProcessStageLibrary.createModifiedReinhardTonemappingStage = function(useAutoExposure) {
  690. var fs = useAutoExposure ? '#define AUTO_EXPOSURE\n' : '';
  691. fs += ModifiedReinhardTonemapping;
  692. return new PostProcessStage({
  693. name : 'czm_modified_reinhard',
  694. fragmentShader : fs,
  695. uniforms : {
  696. white : Color.WHITE,
  697. autoExposure : undefined
  698. }
  699. });
  700. };
  701. /**
  702. * Creates a post-process stage that finds the average luminance of the input texture.
  703. * @return {PostProcessStage} A post-process stage that finds the average luminance of the input texture.
  704. * @private
  705. */
  706. PostProcessStageLibrary.createAutoExposureStage = function() {
  707. return new AutoExposure();
  708. };
  709. /**
  710. * Creates a post-process stage that renders the input texture with black and white gradations.
  711. * <p>
  712. * This stage has one uniform value, <code>gradations</code>, which scales the luminance of each pixel.
  713. * </p>
  714. * @return {PostProcessStage} A post-process stage that renders the input texture with black and white gradations.
  715. */
  716. PostProcessStageLibrary.createBlackAndWhiteStage = function() {
  717. return new PostProcessStage({
  718. name : 'czm_black_and_white',
  719. fragmentShader : BlackAndWhite,
  720. uniforms : {
  721. gradations : 5.0
  722. }
  723. });
  724. };
  725. /**
  726. * Creates a post-process stage that saturates the input texture.
  727. * <p>
  728. * This stage has one uniform value, <code>brightness</code>, which scales the saturation of each pixel.
  729. * </p>
  730. * @return {PostProcessStage} A post-process stage that saturates the input texture.
  731. */
  732. PostProcessStageLibrary.createBrightnessStage = function() {
  733. return new PostProcessStage({
  734. name : 'czm_brightness',
  735. fragmentShader : Brightness,
  736. uniforms : {
  737. brightness : 0.5
  738. }
  739. });
  740. };
  741. /**
  742. * Creates a post-process stage that adds a night vision effect to the input texture.
  743. * @return {PostProcessStage} A post-process stage that adds a night vision effect to the input texture.
  744. */
  745. PostProcessStageLibrary.createNightVisionStage = function() {
  746. return new PostProcessStage({
  747. name : 'czm_night_vision',
  748. fragmentShader : NightVision
  749. });
  750. };
  751. /**
  752. * Creates a post-process stage that replaces the input color texture with a black and white texture representing the fragment depth at each pixel.
  753. * @return {PostProcessStage} A post-process stage that replaces the input color texture with a black and white texture representing the fragment depth at each pixel.
  754. *
  755. * @private
  756. */
  757. PostProcessStageLibrary.createDepthViewStage = function() {
  758. return new PostProcessStage({
  759. name : 'czm_depth_view',
  760. fragmentShader : DepthView
  761. });
  762. };
  763. /**
  764. * Creates a post-process stage that applies an effect simulating light flaring a camera lens.
  765. * <p>
  766. * This stage has the following uniforms: <code>dirtTexture</code>, <code>starTexture</code>, <code>intensity</code>, <code>distortion</code>, <code>ghostDispersal</code>,
  767. * <code>haloWidth</code>, <code>dirtAmount</code>, and <code>earthRadius</code>.
  768. * <ul>
  769. * <li><code>dirtTexture</code> is a texture sampled to simulate dirt on the lens.</li>
  770. * <li><code>starTexture</code> is the texture sampled for the star pattern of the flare.</li>
  771. * <li><code>intensity</code> is a scalar multiplied by the result of the lens flare. The default value is <code>2.0</code>.</li>
  772. * <li><code>distortion</code> is a scalar value that affects the chromatic effect distortion. The default value is <code>10.0</code>.</li>
  773. * <li><code>ghostDispersal</code> is a scalar indicating how far the halo effect is from the center of the texture. The default value is <code>0.4</code>.</li>
  774. * <li><code>haloWidth</code> is a scalar representing the width of the halo from the ghost dispersal. The default value is <code>0.4</code>.</li>
  775. * <li><code>dirtAmount</code> is a scalar representing the amount of dirt on the lens. The default value is <code>0.4</code>.</li>
  776. * <li><code>earthRadius</code> is the maximum radius of the earth. The default value is <code>Ellipsoid.WGS84.maximumRadius</code>.</li>
  777. * </ul>
  778. * </p>
  779. * @return {PostProcessStage} A post-process stage for applying a lens flare effect.
  780. */
  781. PostProcessStageLibrary.createLensFlareStage = function() {
  782. return new PostProcessStage({
  783. name : 'czm_lens_flare',
  784. fragmentShader : LensFlare,
  785. uniforms : {
  786. dirtTexture : buildModuleUrl('Assets/Textures/LensFlare/DirtMask.jpg'),
  787. starTexture : buildModuleUrl('Assets/Textures/LensFlare/StarBurst.jpg'),
  788. intensity : 2.0,
  789. distortion : 10.0,
  790. ghostDispersal : 0.4,
  791. haloWidth : 0.4,
  792. dirtAmount : 0.4,
  793. earthRadius : Ellipsoid.WGS84.maximumRadius
  794. }
  795. });
  796. };
  797. export default PostProcessStageLibrary;