Scene.js 137 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493
  1. import BoundingRectangle from "../Core/BoundingRectangle.js";
  2. import BoundingSphere from "../Core/BoundingSphere.js";
  3. import BoxGeometry from "../Core/BoxGeometry.js";
  4. import Cartesian3 from "../Core/Cartesian3.js";
  5. import Cartographic from "../Core/Cartographic.js";
  6. import clone from "../Core/clone.js";
  7. import Color from "../Core/Color.js";
  8. import ColorGeometryInstanceAttribute from "../Core/ColorGeometryInstanceAttribute.js";
  9. import createGuid from "../Core/createGuid.js";
  10. import CullingVolume from "../Core/CullingVolume.js";
  11. import defaultValue from "../Core/defaultValue.js";
  12. import defined from "../Core/defined.js";
  13. import destroyObject from "../Core/destroyObject.js";
  14. import DeveloperError from "../Core/DeveloperError.js";
  15. import EllipsoidGeometry from "../Core/EllipsoidGeometry.js";
  16. import Event from "../Core/Event.js";
  17. import GeographicProjection from "../Core/GeographicProjection.js";
  18. import GeometryInstance from "../Core/GeometryInstance.js";
  19. import GeometryPipeline from "../Core/GeometryPipeline.js";
  20. import Intersect from "../Core/Intersect.js";
  21. import JulianDate from "../Core/JulianDate.js";
  22. import CesiumMath from "../Core/Math.js";
  23. import Matrix4 from "../Core/Matrix4.js";
  24. import mergeSort from "../Core/mergeSort.js";
  25. import Occluder from "../Core/Occluder.js";
  26. import OrthographicFrustum from "../Core/OrthographicFrustum.js";
  27. import OrthographicOffCenterFrustum from "../Core/OrthographicOffCenterFrustum.js";
  28. import PerspectiveFrustum from "../Core/PerspectiveFrustum.js";
  29. import PerspectiveOffCenterFrustum from "../Core/PerspectiveOffCenterFrustum.js";
  30. import RequestScheduler from "../Core/RequestScheduler.js";
  31. import TaskProcessor from "../Core/TaskProcessor.js";
  32. import Transforms from "../Core/Transforms.js";
  33. import ClearCommand from "../Renderer/ClearCommand.js";
  34. import ComputeEngine from "../Renderer/ComputeEngine.js";
  35. import Context from "../Renderer/Context.js";
  36. import ContextLimits from "../Renderer/ContextLimits.js";
  37. import Pass from "../Renderer/Pass.js";
  38. import RenderState from "../Renderer/RenderState.js";
  39. import BrdfLutGenerator from "./BrdfLutGenerator.js";
  40. import Camera from "./Camera.js";
  41. import Cesium3DTilePass from "./Cesium3DTilePass.js";
  42. import Cesium3DTilePassState from "./Cesium3DTilePassState.js";
  43. import CreditDisplay from "./CreditDisplay.js";
  44. import DebugCameraPrimitive from "./DebugCameraPrimitive.js";
  45. import DepthPlane from "./DepthPlane.js";
  46. import DerivedCommand from "./DerivedCommand.js";
  47. import DeviceOrientationCameraController from "./DeviceOrientationCameraController.js";
  48. import Fog from "./Fog.js";
  49. import FrameState from "./FrameState.js";
  50. import GlobeDepth from "./GlobeDepth.js";
  51. import GlobeTranslucencyState from "./GlobeTranslucencyState.js";
  52. import InvertClassification from "./InvertClassification.js";
  53. import JobScheduler from "./JobScheduler.js";
  54. import MapMode2D from "./MapMode2D.js";
  55. import OctahedralProjectedCubeMap from "./OctahedralProjectedCubeMap.js";
  56. import PerformanceDisplay from "./PerformanceDisplay.js";
  57. import PerInstanceColorAppearance from "./PerInstanceColorAppearance.js";
  58. import Picking from "./Picking.js";
  59. import PostProcessStageCollection from "./PostProcessStageCollection.js";
  60. import Primitive from "./Primitive.js";
  61. import PrimitiveCollection from "./PrimitiveCollection.js";
  62. import SceneMode from "./SceneMode.js";
  63. import SceneTransforms from "./SceneTransforms.js";
  64. import SceneTransitioner from "./SceneTransitioner.js";
  65. import ScreenSpaceCameraController from "./ScreenSpaceCameraController.js";
  66. import ShadowMap from "./ShadowMap.js";
  67. import StencilConstants from "./StencilConstants.js";
  68. import SunLight from "./SunLight.js";
  69. import SunPostProcess from "./SunPostProcess.js";
  70. import TweenCollection from "./TweenCollection.js";
  71. import View from "./View.js";
  72. import DebugInspector from "./DebugInspector.js";
  73. var requestRenderAfterFrame = function (scene) {
  74. return function () {
  75. scene.frameState.afterRender.push(function () {
  76. scene.requestRender();
  77. });
  78. };
  79. };
  80. /**
  81. * The container for all 3D graphical objects and state in a Cesium virtual scene. Generally,
  82. * a scene is not created directly; instead, it is implicitly created by {@link CesiumWidget}.
  83. * <p>
  84. * <em><code>contextOptions</code> parameter details:</em>
  85. * </p>
  86. * <p>
  87. * The default values are:
  88. * <code>
  89. * {
  90. * webgl : {
  91. * alpha : false,
  92. * depth : true,
  93. * stencil : false,
  94. * antialias : true,
  95. * powerPreference: 'high-performance',
  96. * premultipliedAlpha : true,
  97. * preserveDrawingBuffer : false,
  98. * failIfMajorPerformanceCaveat : false
  99. * },
  100. * allowTextureFilterAnisotropic : true
  101. * }
  102. * </code>
  103. * </p>
  104. * <p>
  105. * The <code>webgl</code> property corresponds to the {@link http://www.khronos.org/registry/webgl/specs/latest/#5.2|WebGLContextAttributes}
  106. * object used to create the WebGL context.
  107. * </p>
  108. * <p>
  109. * <code>webgl.alpha</code> defaults to false, which can improve performance compared to the standard WebGL default
  110. * of true. If an application needs to composite Cesium above other HTML elements using alpha-blending, set
  111. * <code>webgl.alpha</code> to true.
  112. * </p>
  113. * <p>
  114. * The other <code>webgl</code> properties match the WebGL defaults for {@link http://www.khronos.org/registry/webgl/specs/latest/#5.2|WebGLContextAttributes}.
  115. * </p>
  116. * <p>
  117. * <code>allowTextureFilterAnisotropic</code> defaults to true, which enables anisotropic texture filtering when the
  118. * WebGL extension is supported. Setting this to false will improve performance, but hurt visual quality, especially for horizon views.
  119. * </p>
  120. *
  121. * @alias Scene
  122. * @constructor
  123. *
  124. * @param {Object} [options] Object with the following properties:
  125. * @param {HTMLCanvasElement} options.canvas The HTML canvas element to create the scene for.
  126. * @param {Object} [options.contextOptions] Context and WebGL creation properties. See details above.
  127. * @param {Element} [options.creditContainer] The HTML element in which the credits will be displayed.
  128. * @param {Element} [options.creditViewport] The HTML element in which to display the credit popup. If not specified, the viewport will be a added as a sibling of the canvas.
  129. * @param {MapProjection} [options.mapProjection=new GeographicProjection()] The map projection to use in 2D and Columbus View modes.
  130. * @param {Boolean} [options.orderIndependentTranslucency=true] If true and the configuration supports it, use order independent translucency.
  131. * @param {Boolean} [options.scene3DOnly=false] If true, optimizes memory use and performance for 3D mode but disables the ability to use 2D or Columbus View.
  132. * @param {Number} [options.terrainExaggeration=1.0] A scalar used to exaggerate the terrain. Note that terrain exaggeration will not modify any other primitive as they are positioned relative to the ellipsoid.
  133. * @param {Boolean} [options.shadows=false] Determines if shadows are cast by light sources.
  134. * @param {MapMode2D} [options.mapMode2D=MapMode2D.INFINITE_SCROLL] Determines if the 2D map is rotatable or can be scrolled infinitely in the horizontal direction.
  135. * @param {Boolean} [options.requestRenderMode=false] If true, rendering a frame will only occur when needed as determined by changes within the scene. Enabling improves performance of the application, but requires using {@link Scene#requestRender} to render a new frame explicitly in this mode. This will be necessary in many cases after making changes to the scene in other parts of the API. See {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}.
  136. * @param {Number} [options.maximumRenderTimeChange=0.0] If requestRenderMode is true, this value defines the maximum change in simulation time allowed before a render is requested. See {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}.
  137. *
  138. * @see CesiumWidget
  139. * @see {@link http://www.khronos.org/registry/webgl/specs/latest/#5.2|WebGLContextAttributes}
  140. *
  141. * @exception {DeveloperError} options and options.canvas are required.
  142. *
  143. * @example
  144. * // Create scene without anisotropic texture filtering
  145. * var scene = new Cesium.Scene({
  146. * canvas : canvas,
  147. * contextOptions : {
  148. * allowTextureFilterAnisotropic : false
  149. * }
  150. * });
  151. */
  152. function Scene(options) {
  153. options = defaultValue(options, defaultValue.EMPTY_OBJECT);
  154. var canvas = options.canvas;
  155. var creditContainer = options.creditContainer;
  156. var creditViewport = options.creditViewport;
  157. var contextOptions = clone(options.contextOptions);
  158. if (!defined(contextOptions)) {
  159. contextOptions = {};
  160. }
  161. if (!defined(contextOptions.webgl)) {
  162. contextOptions.webgl = {};
  163. }
  164. contextOptions.webgl.powerPreference = defaultValue(
  165. contextOptions.webgl.powerPreference,
  166. "high-performance"
  167. );
  168. //>>includeStart('debug', pragmas.debug);
  169. if (!defined(canvas)) {
  170. throw new DeveloperError("options and options.canvas are required.");
  171. }
  172. //>>includeEnd('debug');
  173. var hasCreditContainer = defined(creditContainer);
  174. var context = new Context(canvas, contextOptions);
  175. if (!hasCreditContainer) {
  176. creditContainer = document.createElement("div");
  177. creditContainer.style.position = "absolute";
  178. creditContainer.style.bottom = "0";
  179. creditContainer.style["text-shadow"] = "0 0 2px #000000";
  180. creditContainer.style.color = "#ffffff";
  181. creditContainer.style["font-size"] = "10px";
  182. creditContainer.style["padding-right"] = "5px";
  183. canvas.parentNode.appendChild(creditContainer);
  184. }
  185. if (!defined(creditViewport)) {
  186. creditViewport = canvas.parentNode;
  187. }
  188. this._id = createGuid();
  189. this._jobScheduler = new JobScheduler();
  190. this._frameState = new FrameState(
  191. context,
  192. new CreditDisplay(creditContainer, " • ", creditViewport),
  193. this._jobScheduler
  194. );
  195. this._frameState.scene3DOnly = defaultValue(options.scene3DOnly, false);
  196. this._removeCreditContainer = !hasCreditContainer;
  197. this._creditContainer = creditContainer;
  198. this._canvas = canvas;
  199. this._context = context;
  200. this._computeEngine = new ComputeEngine(context);
  201. this._globe = undefined;
  202. this._globeTranslucencyState = new GlobeTranslucencyState();
  203. this._primitives = new PrimitiveCollection();
  204. this._groundPrimitives = new PrimitiveCollection();
  205. this._globeHeight = undefined;
  206. this._cameraUnderground = false;
  207. this._logDepthBuffer = context.fragmentDepth;
  208. this._logDepthBufferDirty = true;
  209. this._tweens = new TweenCollection();
  210. this._shaderFrameCount = 0;
  211. this._sunPostProcess = undefined;
  212. this._computeCommandList = [];
  213. this._overlayCommandList = [];
  214. this._useOIT = defaultValue(options.orderIndependentTranslucency, true);
  215. this._executeOITFunction = undefined;
  216. this._depthPlane = new DepthPlane();
  217. this._clearColorCommand = new ClearCommand({
  218. color: new Color(),
  219. stencil: 0,
  220. owner: this,
  221. });
  222. this._depthClearCommand = new ClearCommand({
  223. depth: 1.0,
  224. owner: this,
  225. });
  226. this._stencilClearCommand = new ClearCommand({
  227. stencil: 0,
  228. });
  229. this._classificationStencilClearCommand = new ClearCommand({
  230. stencil: 0,
  231. renderState: RenderState.fromCache({
  232. stencilMask: StencilConstants.CLASSIFICATION_MASK,
  233. }),
  234. });
  235. this._depthOnlyRenderStateCache = {};
  236. this._transitioner = new SceneTransitioner(this);
  237. this._preUpdate = new Event();
  238. this._postUpdate = new Event();
  239. this._renderError = new Event();
  240. this._preRender = new Event();
  241. this._postRender = new Event();
  242. this._minimumDisableDepthTestDistance = 0.0;
  243. this._debugInspector = new DebugInspector();
  244. /**
  245. * Exceptions occurring in <code>render</code> are always caught in order to raise the
  246. * <code>renderError</code> event. If this property is true, the error is rethrown
  247. * after the event is raised. If this property is false, the <code>render</code> function
  248. * returns normally after raising the event.
  249. *
  250. * @type {Boolean}
  251. * @default false
  252. */
  253. this.rethrowRenderErrors = false;
  254. /**
  255. * Determines whether or not to instantly complete the
  256. * scene transition animation on user input.
  257. *
  258. * @type {Boolean}
  259. * @default true
  260. */
  261. this.completeMorphOnUserInput = true;
  262. /**
  263. * The event fired at the beginning of a scene transition.
  264. * @type {Event}
  265. * @default Event()
  266. */
  267. this.morphStart = new Event();
  268. /**
  269. * The event fired at the completion of a scene transition.
  270. * @type {Event}
  271. * @default Event()
  272. */
  273. this.morphComplete = new Event();
  274. /**
  275. * The {@link SkyBox} used to draw the stars.
  276. *
  277. * @type {SkyBox}
  278. * @default undefined
  279. *
  280. * @see Scene#backgroundColor
  281. */
  282. this.skyBox = undefined;
  283. /**
  284. * The sky atmosphere drawn around the globe.
  285. *
  286. * @type {SkyAtmosphere}
  287. * @default undefined
  288. */
  289. this.skyAtmosphere = undefined;
  290. /**
  291. * The {@link Sun}.
  292. *
  293. * @type {Sun}
  294. * @default undefined
  295. */
  296. this.sun = undefined;
  297. /**
  298. * Uses a bloom filter on the sun when enabled.
  299. *
  300. * @type {Boolean}
  301. * @default true
  302. */
  303. this.sunBloom = true;
  304. this._sunBloom = undefined;
  305. /**
  306. * The {@link Moon}
  307. *
  308. * @type Moon
  309. * @default undefined
  310. */
  311. this.moon = undefined;
  312. /**
  313. * The background color, which is only visible if there is no sky box, i.e., {@link Scene#skyBox} is undefined.
  314. *
  315. * @type {Color}
  316. * @default {@link Color.BLACK}
  317. *
  318. * @see Scene#skyBox
  319. */
  320. this.backgroundColor = Color.clone(Color.BLACK);
  321. this._mode = SceneMode.SCENE3D;
  322. this._mapProjection = defined(options.mapProjection)
  323. ? options.mapProjection
  324. : new GeographicProjection();
  325. /**
  326. * The current morph transition time between 2D/Columbus View and 3D,
  327. * with 0.0 being 2D or Columbus View and 1.0 being 3D.
  328. *
  329. * @type {Number}
  330. * @default 1.0
  331. */
  332. this.morphTime = 1.0;
  333. /**
  334. * The far-to-near ratio of the multi-frustum when using a normal depth buffer.
  335. * <p>
  336. * This value is used to create the near and far values for each frustum of the multi-frustum. It is only used
  337. * when {@link Scene#logarithmicDepthBuffer} is <code>false</code>. When <code>logarithmicDepthBuffer</code> is
  338. * <code>true</code>, use {@link Scene#logarithmicDepthFarToNearRatio}.
  339. * </p>
  340. *
  341. * @type {Number}
  342. * @default 1000.0
  343. */
  344. this.farToNearRatio = 1000.0;
  345. /**
  346. * The far-to-near ratio of the multi-frustum when using a logarithmic depth buffer.
  347. * <p>
  348. * This value is used to create the near and far values for each frustum of the multi-frustum. It is only used
  349. * when {@link Scene#logarithmicDepthBuffer} is <code>true</code>. When <code>logarithmicDepthBuffer</code> is
  350. * <code>false</code>, use {@link Scene#farToNearRatio}.
  351. * </p>
  352. *
  353. * @type {Number}
  354. * @default 1e9
  355. */
  356. this.logarithmicDepthFarToNearRatio = 1e9;
  357. /**
  358. * Determines the uniform depth size in meters of each frustum of the multifrustum in 2D. If a primitive or model close
  359. * to the surface shows z-fighting, decreasing this will eliminate the artifact, but decrease performance. On the
  360. * other hand, increasing this will increase performance but may cause z-fighting among primitives close to the surface.
  361. *
  362. * @type {Number}
  363. * @default 1.75e6
  364. */
  365. this.nearToFarDistance2D = 1.75e6;
  366. /**
  367. * This property is for debugging only; it is not for production use.
  368. * <p>
  369. * A function that determines what commands are executed. As shown in the examples below,
  370. * the function receives the command's <code>owner</code> as an argument, and returns a boolean indicating if the
  371. * command should be executed.
  372. * </p>
  373. * <p>
  374. * The default is <code>undefined</code>, indicating that all commands are executed.
  375. * </p>
  376. *
  377. * @type Function
  378. *
  379. * @default undefined
  380. *
  381. * @example
  382. * // Do not execute any commands.
  383. * scene.debugCommandFilter = function(command) {
  384. * return false;
  385. * };
  386. *
  387. * // Execute only the billboard's commands. That is, only draw the billboard.
  388. * var billboards = new Cesium.BillboardCollection();
  389. * scene.debugCommandFilter = function(command) {
  390. * return command.owner === billboards;
  391. * };
  392. */
  393. this.debugCommandFilter = undefined;
  394. /**
  395. * This property is for debugging only; it is not for production use.
  396. * <p>
  397. * When <code>true</code>, commands are randomly shaded. This is useful
  398. * for performance analysis to see what parts of a scene or model are
  399. * command-dense and could benefit from batching.
  400. * </p>
  401. *
  402. * @type Boolean
  403. *
  404. * @default false
  405. */
  406. this.debugShowCommands = false;
  407. /**
  408. * This property is for debugging only; it is not for production use.
  409. * <p>
  410. * When <code>true</code>, commands are shaded based on the frustums they
  411. * overlap. Commands in the closest frustum are tinted red, commands in
  412. * the next closest are green, and commands in the farthest frustum are
  413. * blue. If a command overlaps more than one frustum, the color components
  414. * are combined, e.g., a command overlapping the first two frustums is tinted
  415. * yellow.
  416. * </p>
  417. *
  418. * @type Boolean
  419. *
  420. * @default false
  421. */
  422. this.debugShowFrustums = false;
  423. /**
  424. * This property is for debugging only; it is not for production use.
  425. * <p>
  426. * Displays frames per second and time between frames.
  427. * </p>
  428. *
  429. * @type Boolean
  430. *
  431. * @default false
  432. */
  433. this.debugShowFramesPerSecond = false;
  434. /**
  435. * This property is for debugging only; it is not for production use.
  436. * <p>
  437. * Displays depth information for the indicated frustum.
  438. * </p>
  439. *
  440. * @type Boolean
  441. *
  442. * @default false
  443. */
  444. this.debugShowGlobeDepth = false;
  445. /**
  446. * This property is for debugging only; it is not for production use.
  447. * <p>
  448. * Indicates which frustum will have depth information displayed.
  449. * </p>
  450. *
  451. * @type Number
  452. *
  453. * @default 1
  454. */
  455. this.debugShowDepthFrustum = 1;
  456. /**
  457. * This property is for debugging only; it is not for production use.
  458. * <p>
  459. * When <code>true</code>, draws outlines to show the boundaries of the camera frustums
  460. * </p>
  461. *
  462. * @type Boolean
  463. *
  464. * @default false
  465. */
  466. this.debugShowFrustumPlanes = false;
  467. this._debugShowFrustumPlanes = false;
  468. this._debugFrustumPlanes = undefined;
  469. /**
  470. * When <code>true</code>, enables picking using the depth buffer.
  471. *
  472. * @type Boolean
  473. * @default true
  474. */
  475. this.useDepthPicking = true;
  476. /**
  477. * When <code>true</code>, enables picking translucent geometry using the depth buffer. Note that {@link Scene#useDepthPicking} must also be true for enabling this to work.
  478. *
  479. * <p>
  480. * Render must be called between picks.
  481. * <br>There is a decrease in performance when enabled. There are extra draw calls to write depth for
  482. * translucent geometry.
  483. * </p>
  484. *
  485. * @example
  486. * // picking the position of a translucent primitive
  487. * viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
  488. * var pickedFeature = viewer.scene.pick(movement.position);
  489. * if (!Cesium.defined(pickedFeature)) {
  490. * // nothing picked
  491. * return;
  492. * }
  493. * viewer.scene.render();
  494. * var worldPosition = viewer.scene.pickPosition(movement.position);
  495. * }, Cesium.ScreenSpaceEventType.LEFT_CLICK);
  496. *
  497. * @type {Boolean}
  498. * @default false
  499. */
  500. this.pickTranslucentDepth = false;
  501. /**
  502. * The time in milliseconds to wait before checking if the camera has not moved and fire the cameraMoveEnd event.
  503. * @type {Number}
  504. * @default 500.0
  505. * @private
  506. */
  507. this.cameraEventWaitTime = 500.0;
  508. /**
  509. * Blends the atmosphere to geometry far from the camera for horizon views. Allows for additional
  510. * performance improvements by rendering less geometry and dispatching less terrain requests.
  511. * @type {Fog}
  512. */
  513. this.fog = new Fog();
  514. this._shadowMapCamera = new Camera(this);
  515. /**
  516. * The shadow map for the scene's light source. When enabled, models, primitives, and the globe may cast and receive shadows.
  517. * @type {ShadowMap}
  518. */
  519. this.shadowMap = new ShadowMap({
  520. context: context,
  521. lightCamera: this._shadowMapCamera,
  522. enabled: defaultValue(options.shadows, false),
  523. });
  524. /**
  525. * When <code>false</code>, 3D Tiles will render normally. When <code>true</code>, classified 3D Tile geometry will render normally and
  526. * unclassified 3D Tile geometry will render with the color multiplied by {@link Scene#invertClassificationColor}.
  527. * @type {Boolean}
  528. * @default false
  529. */
  530. this.invertClassification = false;
  531. /**
  532. * The highlight color of unclassified 3D Tile geometry when {@link Scene#invertClassification} is <code>true</code>.
  533. * <p>When the color's alpha is less than 1.0, the unclassified portions of the 3D Tiles will not blend correctly with the classified positions of the 3D Tiles.</p>
  534. * <p>Also, when the color's alpha is less than 1.0, the WEBGL_depth_texture and EXT_frag_depth WebGL extensions must be supported.</p>
  535. * @type {Color}
  536. * @default Color.WHITE
  537. */
  538. this.invertClassificationColor = Color.clone(Color.WHITE);
  539. this._actualInvertClassificationColor = Color.clone(
  540. this._invertClassificationColor
  541. );
  542. this._invertClassification = new InvertClassification();
  543. /**
  544. * The focal length for use when with cardboard or WebVR.
  545. * @type {Number}
  546. */
  547. this.focalLength = undefined;
  548. /**
  549. * The eye separation distance in meters for use with cardboard or WebVR.
  550. * @type {Number}
  551. */
  552. this.eyeSeparation = undefined;
  553. /**
  554. * Post processing effects applied to the final render.
  555. * @type {PostProcessStageCollection}
  556. */
  557. this.postProcessStages = new PostProcessStageCollection();
  558. this._brdfLutGenerator = new BrdfLutGenerator();
  559. this._terrainExaggeration = defaultValue(options.terrainExaggeration, 1.0);
  560. this._performanceDisplay = undefined;
  561. this._debugVolume = undefined;
  562. this._screenSpaceCameraController = new ScreenSpaceCameraController(this);
  563. this._cameraUnderground = false;
  564. this._mapMode2D = defaultValue(options.mapMode2D, MapMode2D.INFINITE_SCROLL);
  565. // Keeps track of the state of a frame. FrameState is the state across
  566. // the primitives of the scene. This state is for internally keeping track
  567. // of celestial and environment effects that need to be updated/rendered in
  568. // a certain order as well as updating/tracking framebuffer usage.
  569. this._environmentState = {
  570. skyBoxCommand: undefined,
  571. skyAtmosphereCommand: undefined,
  572. sunDrawCommand: undefined,
  573. sunComputeCommand: undefined,
  574. moonCommand: undefined,
  575. isSunVisible: false,
  576. isMoonVisible: false,
  577. isReadyForAtmosphere: false,
  578. isSkyAtmosphereVisible: false,
  579. clearGlobeDepth: false,
  580. useDepthPlane: false,
  581. renderTranslucentDepthForPick: false,
  582. originalFramebuffer: undefined,
  583. useGlobeDepthFramebuffer: false,
  584. separatePrimitiveFramebuffer: false,
  585. useOIT: false,
  586. useInvertClassification: false,
  587. usePostProcess: false,
  588. usePostProcessSelected: false,
  589. useWebVR: false,
  590. };
  591. this._useWebVR = false;
  592. this._cameraVR = undefined;
  593. this._aspectRatioVR = undefined;
  594. /**
  595. * When <code>true</code>, rendering a frame will only occur when needed as determined by changes within the scene.
  596. * Enabling improves performance of the application, but requires using {@link Scene#requestRender}
  597. * to render a new frame explicitly in this mode. This will be necessary in many cases after making changes
  598. * to the scene in other parts of the API.
  599. *
  600. * @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
  601. * @see Scene#maximumRenderTimeChange
  602. * @see Scene#requestRender
  603. *
  604. * @type {Boolean}
  605. * @default false
  606. */
  607. this.requestRenderMode = defaultValue(options.requestRenderMode, false);
  608. this._renderRequested = true;
  609. /**
  610. * If {@link Scene#requestRenderMode} is <code>true</code>, this value defines the maximum change in
  611. * simulation time allowed before a render is requested. Lower values increase the number of frames rendered
  612. * and higher values decrease the number of frames rendered. If <code>undefined</code>, changes to
  613. * the simulation time will never request a render.
  614. * This value impacts the rate of rendering for changes in the scene like lighting, entity property updates,
  615. * and animations.
  616. *
  617. * @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
  618. * @see Scene#requestRenderMode
  619. *
  620. * @type {Number}
  621. * @default 0.0
  622. */
  623. this.maximumRenderTimeChange = defaultValue(
  624. options.maximumRenderTimeChange,
  625. 0.0
  626. );
  627. this._lastRenderTime = undefined;
  628. this._frameRateMonitor = undefined;
  629. this._removeRequestListenerCallback = RequestScheduler.requestCompletedEvent.addEventListener(
  630. requestRenderAfterFrame(this)
  631. );
  632. this._removeTaskProcessorListenerCallback = TaskProcessor.taskCompletedEvent.addEventListener(
  633. requestRenderAfterFrame(this)
  634. );
  635. this._removeGlobeCallbacks = [];
  636. var viewport = new BoundingRectangle(
  637. 0,
  638. 0,
  639. context.drawingBufferWidth,
  640. context.drawingBufferHeight
  641. );
  642. var camera = new Camera(this);
  643. if (this._logDepthBuffer) {
  644. camera.frustum.near = 0.1;
  645. camera.frustum.far = 10000000000.0;
  646. }
  647. /**
  648. * The camera view for the scene camera flight destination. Used for preloading flight destination tiles.
  649. * @type {Camera}
  650. * @private
  651. */
  652. this.preloadFlightCamera = new Camera(this);
  653. /**
  654. * The culling volume for the scene camera flight destination. Used for preloading flight destination tiles.
  655. * @type {CullingVolume}
  656. * @private
  657. */
  658. this.preloadFlightCullingVolume = undefined;
  659. this._picking = new Picking(this);
  660. this._defaultView = new View(this, camera, viewport);
  661. this._view = this._defaultView;
  662. this._hdr = undefined;
  663. this._hdrDirty = undefined;
  664. this.highDynamicRange = false;
  665. this.gamma = 2.2;
  666. /**
  667. * The spherical harmonic coefficients for image-based lighting of PBR models.
  668. * @type {Cartesian3[]}
  669. */
  670. this.sphericalHarmonicCoefficients = undefined;
  671. /**
  672. * The url to the KTX file containing the specular environment map and convoluted mipmaps for image-based lighting of PBR models.
  673. * @type {String}
  674. */
  675. this.specularEnvironmentMaps = undefined;
  676. this._specularEnvironmentMapAtlas = undefined;
  677. /**
  678. * The light source for shading. Defaults to a directional light from the Sun.
  679. * @type {Light}
  680. */
  681. this.light = new SunLight();
  682. // Give frameState, camera, and screen space camera controller initial state before rendering
  683. updateFrameNumber(this, 0.0, JulianDate.now());
  684. this.updateFrameState();
  685. this.initializeFrame();
  686. }
  687. function updateGlobeListeners(scene, globe) {
  688. for (var i = 0; i < scene._removeGlobeCallbacks.length; ++i) {
  689. scene._removeGlobeCallbacks[i]();
  690. }
  691. scene._removeGlobeCallbacks.length = 0;
  692. var removeGlobeCallbacks = [];
  693. if (defined(globe)) {
  694. removeGlobeCallbacks.push(
  695. globe.imageryLayersUpdatedEvent.addEventListener(
  696. requestRenderAfterFrame(scene)
  697. )
  698. );
  699. removeGlobeCallbacks.push(
  700. globe.terrainProviderChanged.addEventListener(
  701. requestRenderAfterFrame(scene)
  702. )
  703. );
  704. }
  705. scene._removeGlobeCallbacks = removeGlobeCallbacks;
  706. }
  707. Object.defineProperties(Scene.prototype, {
  708. /**
  709. * Gets the canvas element to which this scene is bound.
  710. * @memberof Scene.prototype
  711. *
  712. * @type {HTMLCanvasElement}
  713. * @readonly
  714. */
  715. canvas: {
  716. get: function () {
  717. return this._canvas;
  718. },
  719. },
  720. /**
  721. * The drawingBufferHeight of the underlying GL context.
  722. * @memberof Scene.prototype
  723. *
  724. * @type {Number}
  725. * @readonly
  726. *
  727. * @see {@link https://www.khronos.org/registry/webgl/specs/1.0/#DOM-WebGLRenderingContext-drawingBufferHeight|drawingBufferHeight}
  728. */
  729. drawingBufferHeight: {
  730. get: function () {
  731. return this._context.drawingBufferHeight;
  732. },
  733. },
  734. /**
  735. * The drawingBufferHeight of the underlying GL context.
  736. * @memberof Scene.prototype
  737. *
  738. * @type {Number}
  739. * @readonly
  740. *
  741. * @see {@link https://www.khronos.org/registry/webgl/specs/1.0/#DOM-WebGLRenderingContext-drawingBufferHeight|drawingBufferHeight}
  742. */
  743. drawingBufferWidth: {
  744. get: function () {
  745. return this._context.drawingBufferWidth;
  746. },
  747. },
  748. /**
  749. * The maximum aliased line width, in pixels, supported by this WebGL implementation. It will be at least one.
  750. * @memberof Scene.prototype
  751. *
  752. * @type {Number}
  753. * @readonly
  754. *
  755. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>ALIASED_LINE_WIDTH_RANGE</code>.
  756. */
  757. maximumAliasedLineWidth: {
  758. get: function () {
  759. return ContextLimits.maximumAliasedLineWidth;
  760. },
  761. },
  762. /**
  763. * The maximum length in pixels of one edge of a cube map, supported by this WebGL implementation. It will be at least 16.
  764. * @memberof Scene.prototype
  765. *
  766. * @type {Number}
  767. * @readonly
  768. *
  769. * @see {@link https://www.khronos.org/opengles/sdk/docs/man/xhtml/glGet.xml|glGet} with <code>GL_MAX_CUBE_MAP_TEXTURE_SIZE</code>.
  770. */
  771. maximumCubeMapSize: {
  772. get: function () {
  773. return ContextLimits.maximumCubeMapSize;
  774. },
  775. },
  776. /**
  777. * Returns <code>true</code> if the {@link Scene#pickPosition} function is supported.
  778. * @memberof Scene.prototype
  779. *
  780. * @type {Boolean}
  781. * @readonly
  782. *
  783. * @see Scene#pickPosition
  784. */
  785. pickPositionSupported: {
  786. get: function () {
  787. return this._context.depthTexture;
  788. },
  789. },
  790. /**
  791. * Returns <code>true</code> if the {@link Scene#sampleHeight} and {@link Scene#sampleHeightMostDetailed} functions are supported.
  792. * @memberof Scene.prototype
  793. *
  794. * @type {Boolean}
  795. * @readonly
  796. *
  797. * @see Scene#sampleHeight
  798. * @see Scene#sampleHeightMostDetailed
  799. */
  800. sampleHeightSupported: {
  801. get: function () {
  802. return this._context.depthTexture;
  803. },
  804. },
  805. /**
  806. * Returns <code>true</code> if the {@link Scene#clampToHeight} and {@link Scene#clampToHeightMostDetailed} functions are supported.
  807. * @memberof Scene.prototype
  808. *
  809. * @type {Boolean}
  810. * @readonly
  811. *
  812. * @see Scene#clampToHeight
  813. * @see Scene#clampToHeightMostDetailed
  814. */
  815. clampToHeightSupported: {
  816. get: function () {
  817. return this._context.depthTexture;
  818. },
  819. },
  820. /**
  821. * Returns <code>true</code> if the {@link Scene#invertClassification} is supported.
  822. * @memberof Scene.prototype
  823. *
  824. * @type {Boolean}
  825. * @readonly
  826. *
  827. * @see Scene#invertClassification
  828. */
  829. invertClassificationSupported: {
  830. get: function () {
  831. return this._context.depthTexture;
  832. },
  833. },
  834. /**
  835. * Returns <code>true</code> if specular environment maps are supported.
  836. * @memberof Scene.prototype
  837. *
  838. * @type {Boolean}
  839. * @readonly
  840. *
  841. * @see Scene#specularEnvironmentMaps
  842. */
  843. specularEnvironmentMapsSupported: {
  844. get: function () {
  845. return OctahedralProjectedCubeMap.isSupported(this._context);
  846. },
  847. },
  848. /**
  849. * Gets or sets the depth-test ellipsoid.
  850. * @memberof Scene.prototype
  851. *
  852. * @type {Globe}
  853. */
  854. globe: {
  855. get: function () {
  856. return this._globe;
  857. },
  858. set: function (globe) {
  859. this._globe = this._globe && this._globe.destroy();
  860. this._globe = globe;
  861. updateGlobeListeners(this, globe);
  862. },
  863. },
  864. /**
  865. * Gets the collection of primitives.
  866. * @memberof Scene.prototype
  867. *
  868. * @type {PrimitiveCollection}
  869. * @readonly
  870. */
  871. primitives: {
  872. get: function () {
  873. return this._primitives;
  874. },
  875. },
  876. /**
  877. * Gets the collection of ground primitives.
  878. * @memberof Scene.prototype
  879. *
  880. * @type {PrimitiveCollection}
  881. * @readonly
  882. */
  883. groundPrimitives: {
  884. get: function () {
  885. return this._groundPrimitives;
  886. },
  887. },
  888. /**
  889. * Gets or sets the camera.
  890. * @memberof Scene.prototype
  891. *
  892. * @type {Camera}
  893. * @readonly
  894. */
  895. camera: {
  896. get: function () {
  897. return this._view.camera;
  898. },
  899. set: function (camera) {
  900. // For internal use only. Documentation is still @readonly.
  901. this._view.camera = camera;
  902. },
  903. },
  904. /**
  905. * Gets or sets the view.
  906. * @memberof Scene.prototype
  907. *
  908. * @type {View}
  909. * @readonly
  910. *
  911. * @private
  912. */
  913. view: {
  914. get: function () {
  915. return this._view;
  916. },
  917. set: function (view) {
  918. // For internal use only. Documentation is still @readonly.
  919. this._view = view;
  920. },
  921. },
  922. /**
  923. * Gets the default view.
  924. * @memberof Scene.prototype
  925. *
  926. * @type {View}
  927. * @readonly
  928. *
  929. * @private
  930. */
  931. defaultView: {
  932. get: function () {
  933. return this._defaultView;
  934. },
  935. },
  936. /**
  937. * Gets picking functions and state
  938. * @memberof Scene.prototype
  939. *
  940. * @type {Picking}
  941. * @readonly
  942. *
  943. * @private
  944. */
  945. picking: {
  946. get: function () {
  947. return this._picking;
  948. },
  949. },
  950. /**
  951. * Gets the controller for camera input handling.
  952. * @memberof Scene.prototype
  953. *
  954. * @type {ScreenSpaceCameraController}
  955. * @readonly
  956. */
  957. screenSpaceCameraController: {
  958. get: function () {
  959. return this._screenSpaceCameraController;
  960. },
  961. },
  962. /**
  963. * Get the map projection to use in 2D and Columbus View modes.
  964. * @memberof Scene.prototype
  965. *
  966. * @type {MapProjection}
  967. * @readonly
  968. *
  969. * @default new GeographicProjection()
  970. */
  971. mapProjection: {
  972. get: function () {
  973. return this._mapProjection;
  974. },
  975. },
  976. /**
  977. * Gets the job scheduler
  978. * @memberof Scene.prototype
  979. * @type {JobScheduler}
  980. * @readonly
  981. *
  982. * @private
  983. */
  984. jobScheduler: {
  985. get: function () {
  986. return this._jobScheduler;
  987. },
  988. },
  989. /**
  990. * Gets state information about the current scene. If called outside of a primitive's <code>update</code>
  991. * function, the previous frame's state is returned.
  992. * @memberof Scene.prototype
  993. *
  994. * @type {FrameState}
  995. * @readonly
  996. *
  997. * @private
  998. */
  999. frameState: {
  1000. get: function () {
  1001. return this._frameState;
  1002. },
  1003. },
  1004. /**
  1005. * Gets the environment state.
  1006. * @memberof Scene.prototype
  1007. *
  1008. * @type {EnvironmentState}
  1009. * @readonly
  1010. *
  1011. * @private
  1012. */
  1013. environmentState: {
  1014. get: function () {
  1015. return this._environmentState;
  1016. },
  1017. },
  1018. /**
  1019. * Gets the collection of tweens taking place in the scene.
  1020. * @memberof Scene.prototype
  1021. *
  1022. * @type {TweenCollection}
  1023. * @readonly
  1024. *
  1025. * @private
  1026. */
  1027. tweens: {
  1028. get: function () {
  1029. return this._tweens;
  1030. },
  1031. },
  1032. /**
  1033. * Gets the collection of image layers that will be rendered on the globe.
  1034. * @memberof Scene.prototype
  1035. *
  1036. * @type {ImageryLayerCollection}
  1037. * @readonly
  1038. */
  1039. imageryLayers: {
  1040. get: function () {
  1041. if (!defined(this.globe)) {
  1042. return undefined;
  1043. }
  1044. return this.globe.imageryLayers;
  1045. },
  1046. },
  1047. /**
  1048. * The terrain provider providing surface geometry for the globe.
  1049. * @memberof Scene.prototype
  1050. *
  1051. * @type {TerrainProvider}
  1052. */
  1053. terrainProvider: {
  1054. get: function () {
  1055. if (!defined(this.globe)) {
  1056. return undefined;
  1057. }
  1058. return this.globe.terrainProvider;
  1059. },
  1060. set: function (terrainProvider) {
  1061. if (defined(this.globe)) {
  1062. this.globe.terrainProvider = terrainProvider;
  1063. }
  1064. },
  1065. },
  1066. /**
  1067. * Gets an event that's raised when the terrain provider is changed
  1068. * @memberof Scene.prototype
  1069. *
  1070. * @type {Event}
  1071. * @readonly
  1072. */
  1073. terrainProviderChanged: {
  1074. get: function () {
  1075. if (!defined(this.globe)) {
  1076. return undefined;
  1077. }
  1078. return this.globe.terrainProviderChanged;
  1079. },
  1080. },
  1081. /**
  1082. * Gets the event that will be raised before the scene is updated or rendered. Subscribers to the event
  1083. * receive the Scene instance as the first parameter and the current time as the second parameter.
  1084. * @memberof Scene.prototype
  1085. *
  1086. * @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
  1087. * @see Scene#postUpdate
  1088. * @see Scene#preRender
  1089. * @see Scene#postRender
  1090. *
  1091. * @type {Event}
  1092. * @readonly
  1093. */
  1094. preUpdate: {
  1095. get: function () {
  1096. return this._preUpdate;
  1097. },
  1098. },
  1099. /**
  1100. * Gets the event that will be raised immediately after the scene is updated and before the scene is rendered.
  1101. * Subscribers to the event receive the Scene instance as the first parameter and the current time as the second
  1102. * parameter.
  1103. * @memberof Scene.prototype
  1104. *
  1105. * @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
  1106. * @see Scene#preUpdate
  1107. * @see Scene#preRender
  1108. * @see Scene#postRender
  1109. *
  1110. * @type {Event}
  1111. * @readonly
  1112. */
  1113. postUpdate: {
  1114. get: function () {
  1115. return this._postUpdate;
  1116. },
  1117. },
  1118. /**
  1119. * Gets the event that will be raised when an error is thrown inside the <code>render</code> function.
  1120. * The Scene instance and the thrown error are the only two parameters passed to the event handler.
  1121. * By default, errors are not rethrown after this event is raised, but that can be changed by setting
  1122. * the <code>rethrowRenderErrors</code> property.
  1123. * @memberof Scene.prototype
  1124. *
  1125. * @type {Event}
  1126. * @readonly
  1127. */
  1128. renderError: {
  1129. get: function () {
  1130. return this._renderError;
  1131. },
  1132. },
  1133. /**
  1134. * Gets the event that will be raised after the scene is updated and immediately before the scene is rendered.
  1135. * Subscribers to the event receive the Scene instance as the first parameter and the current time as the second
  1136. * parameter.
  1137. * @memberof Scene.prototype
  1138. *
  1139. * @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
  1140. * @see Scene#preUpdate
  1141. * @see Scene#postUpdate
  1142. * @see Scene#postRender
  1143. *
  1144. * @type {Event}
  1145. * @readonly
  1146. */
  1147. preRender: {
  1148. get: function () {
  1149. return this._preRender;
  1150. },
  1151. },
  1152. /**
  1153. * Gets the event that will be raised immediately after the scene is rendered. Subscribers to the event
  1154. * receive the Scene instance as the first parameter and the current time as the second parameter.
  1155. * @memberof Scene.prototype
  1156. *
  1157. * @see {@link https://cesium.com/blog/2018/01/24/cesium-scene-rendering-performance/|Improving Performance with Explicit Rendering}
  1158. * @see Scene#preUpdate
  1159. * @see Scene#postUpdate
  1160. * @see Scene#postRender
  1161. *
  1162. * @type {Event}
  1163. * @readonly
  1164. */
  1165. postRender: {
  1166. get: function () {
  1167. return this._postRender;
  1168. },
  1169. },
  1170. /**
  1171. * Gets the simulation time when the scene was last rendered. Returns undefined if the scene has not yet been
  1172. * rendered.
  1173. * @memberof Scene.prototype
  1174. *
  1175. * @type {JulianDate}
  1176. * @readonly
  1177. */
  1178. lastRenderTime: {
  1179. get: function () {
  1180. return this._lastRenderTime;
  1181. },
  1182. },
  1183. /**
  1184. * @memberof Scene.prototype
  1185. * @private
  1186. * @readonly
  1187. */
  1188. context: {
  1189. get: function () {
  1190. return this._context;
  1191. },
  1192. },
  1193. /**
  1194. * This property is for debugging only; it is not for production use.
  1195. * <p>
  1196. * When {@link Scene.debugShowFrustums} is <code>true</code>, this contains
  1197. * properties with statistics about the number of command execute per frustum.
  1198. * <code>totalCommands</code> is the total number of commands executed, ignoring
  1199. * overlap. <code>commandsInFrustums</code> is an array with the number of times
  1200. * commands are executed redundantly, e.g., how many commands overlap two or
  1201. * three frustums.
  1202. * </p>
  1203. *
  1204. * @memberof Scene.prototype
  1205. *
  1206. * @type {Object}
  1207. * @readonly
  1208. *
  1209. * @default undefined
  1210. */
  1211. debugFrustumStatistics: {
  1212. get: function () {
  1213. return this._view.debugFrustumStatistics;
  1214. },
  1215. },
  1216. /**
  1217. * Gets whether or not the scene is optimized for 3D only viewing.
  1218. * @memberof Scene.prototype
  1219. * @type {Boolean}
  1220. * @readonly
  1221. */
  1222. scene3DOnly: {
  1223. get: function () {
  1224. return this._frameState.scene3DOnly;
  1225. },
  1226. },
  1227. /**
  1228. * Gets whether or not the scene has order independent translucency enabled.
  1229. * Note that this only reflects the original construction option, and there are
  1230. * other factors that could prevent OIT from functioning on a given system configuration.
  1231. * @memberof Scene.prototype
  1232. * @type {Boolean}
  1233. * @readonly
  1234. */
  1235. orderIndependentTranslucency: {
  1236. get: function () {
  1237. return this._useOIT;
  1238. },
  1239. },
  1240. /**
  1241. * Gets the unique identifier for this scene.
  1242. * @memberof Scene.prototype
  1243. * @type {String}
  1244. * @readonly
  1245. */
  1246. id: {
  1247. get: function () {
  1248. return this._id;
  1249. },
  1250. },
  1251. /**
  1252. * Gets or sets the current mode of the scene.
  1253. * @memberof Scene.prototype
  1254. * @type {SceneMode}
  1255. * @default {@link SceneMode.SCENE3D}
  1256. */
  1257. mode: {
  1258. get: function () {
  1259. return this._mode;
  1260. },
  1261. set: function (value) {
  1262. //>>includeStart('debug', pragmas.debug);
  1263. if (this.scene3DOnly && value !== SceneMode.SCENE3D) {
  1264. throw new DeveloperError(
  1265. "Only SceneMode.SCENE3D is valid when scene3DOnly is true."
  1266. );
  1267. }
  1268. //>>includeEnd('debug');
  1269. if (value === SceneMode.SCENE2D) {
  1270. this.morphTo2D(0);
  1271. } else if (value === SceneMode.SCENE3D) {
  1272. this.morphTo3D(0);
  1273. } else if (value === SceneMode.COLUMBUS_VIEW) {
  1274. this.morphToColumbusView(0);
  1275. //>>includeStart('debug', pragmas.debug);
  1276. } else {
  1277. throw new DeveloperError(
  1278. "value must be a valid SceneMode enumeration."
  1279. );
  1280. //>>includeEnd('debug');
  1281. }
  1282. this._mode = value;
  1283. },
  1284. },
  1285. /**
  1286. * Gets the number of frustums used in the last frame.
  1287. * @memberof Scene.prototype
  1288. * @type {FrustumCommands[]}
  1289. *
  1290. * @private
  1291. */
  1292. frustumCommandsList: {
  1293. get: function () {
  1294. return this._view.frustumCommandsList;
  1295. },
  1296. },
  1297. /**
  1298. * Gets the number of frustums used in the last frame.
  1299. * @memberof Scene.prototype
  1300. * @type {Number}
  1301. *
  1302. * @private
  1303. */
  1304. numberOfFrustums: {
  1305. get: function () {
  1306. return this._view.frustumCommandsList.length;
  1307. },
  1308. },
  1309. /**
  1310. * Gets the scalar used to exaggerate the terrain.
  1311. * @memberof Scene.prototype
  1312. * @type {Number}
  1313. * @readonly
  1314. */
  1315. terrainExaggeration: {
  1316. get: function () {
  1317. return this._terrainExaggeration;
  1318. },
  1319. },
  1320. /**
  1321. * When <code>true</code>, splits the scene into two viewports with steroscopic views for the left and right eyes.
  1322. * Used for cardboard and WebVR.
  1323. * @memberof Scene.prototype
  1324. * @type {Boolean}
  1325. * @default false
  1326. */
  1327. useWebVR: {
  1328. get: function () {
  1329. return this._useWebVR;
  1330. },
  1331. set: function (value) {
  1332. //>>includeStart('debug', pragmas.debug);
  1333. if (this.camera.frustum instanceof OrthographicFrustum) {
  1334. throw new DeveloperError(
  1335. "VR is unsupported with an orthographic projection."
  1336. );
  1337. }
  1338. //>>includeEnd('debug');
  1339. this._useWebVR = value;
  1340. if (this._useWebVR) {
  1341. this._frameState.creditDisplay.container.style.visibility = "hidden";
  1342. this._cameraVR = new Camera(this);
  1343. if (!defined(this._deviceOrientationCameraController)) {
  1344. this._deviceOrientationCameraController = new DeviceOrientationCameraController(
  1345. this
  1346. );
  1347. }
  1348. this._aspectRatioVR = this.camera.frustum.aspectRatio;
  1349. } else {
  1350. this._frameState.creditDisplay.container.style.visibility = "visible";
  1351. this._cameraVR = undefined;
  1352. this._deviceOrientationCameraController =
  1353. this._deviceOrientationCameraController &&
  1354. !this._deviceOrientationCameraController.isDestroyed() &&
  1355. this._deviceOrientationCameraController.destroy();
  1356. this.camera.frustum.aspectRatio = this._aspectRatioVR;
  1357. this.camera.frustum.xOffset = 0.0;
  1358. }
  1359. },
  1360. },
  1361. /**
  1362. * Determines if the 2D map is rotatable or can be scrolled infinitely in the horizontal direction.
  1363. * @memberof Scene.prototype
  1364. * @type {MapMode2D}
  1365. * @readonly
  1366. */
  1367. mapMode2D: {
  1368. get: function () {
  1369. return this._mapMode2D;
  1370. },
  1371. },
  1372. /**
  1373. * Gets or sets the position of the Imagery splitter within the viewport. Valid values are between 0.0 and 1.0.
  1374. * @memberof Scene.prototype
  1375. *
  1376. * @type {Number}
  1377. */
  1378. imagerySplitPosition: {
  1379. get: function () {
  1380. return this._frameState.imagerySplitPosition;
  1381. },
  1382. set: function (value) {
  1383. this._frameState.imagerySplitPosition = value;
  1384. },
  1385. },
  1386. /**
  1387. * The distance from the camera at which to disable the depth test of billboards, labels and points
  1388. * to, for example, prevent clipping against terrain. When set to zero, the depth test should always
  1389. * be applied. When less than zero, the depth test should never be applied. Setting the disableDepthTestDistance
  1390. * property of a billboard, label or point will override this value.
  1391. * @memberof Scene.prototype
  1392. * @type {Number}
  1393. * @default 0.0
  1394. */
  1395. minimumDisableDepthTestDistance: {
  1396. get: function () {
  1397. return this._minimumDisableDepthTestDistance;
  1398. },
  1399. set: function (value) {
  1400. //>>includeStart('debug', pragmas.debug);
  1401. if (!defined(value) || value < 0.0) {
  1402. throw new DeveloperError(
  1403. "minimumDisableDepthTestDistance must be greater than or equal to 0.0."
  1404. );
  1405. }
  1406. //>>includeEnd('debug');
  1407. this._minimumDisableDepthTestDistance = value;
  1408. },
  1409. },
  1410. /**
  1411. * Whether or not to use a logarithmic depth buffer. Enabling this option will allow for less frustums in the multi-frustum,
  1412. * increasing performance. This property relies on fragmentDepth being supported.
  1413. * @memberof Scene.prototype
  1414. * @type {Boolean}
  1415. */
  1416. logarithmicDepthBuffer: {
  1417. get: function () {
  1418. return this._logDepthBuffer;
  1419. },
  1420. set: function (value) {
  1421. value = this._context.fragmentDepth && value;
  1422. if (this._logDepthBuffer !== value) {
  1423. this._logDepthBuffer = value;
  1424. this._logDepthBufferDirty = true;
  1425. }
  1426. },
  1427. },
  1428. /**
  1429. * The value used for gamma correction. This is only used when rendering with high dynamic range.
  1430. * @memberof Scene.prototype
  1431. * @type {Number}
  1432. * @default 2.2
  1433. */
  1434. gamma: {
  1435. get: function () {
  1436. return this._context.uniformState.gamma;
  1437. },
  1438. set: function (value) {
  1439. this._context.uniformState.gamma = value;
  1440. },
  1441. },
  1442. /**
  1443. * Whether or not to use high dynamic range rendering.
  1444. * @memberof Scene.prototype
  1445. * @type {Boolean}
  1446. * @default true
  1447. */
  1448. highDynamicRange: {
  1449. get: function () {
  1450. return this._hdr;
  1451. },
  1452. set: function (value) {
  1453. var context = this._context;
  1454. var hdr =
  1455. value &&
  1456. context.depthTexture &&
  1457. (context.colorBufferFloat || context.colorBufferHalfFloat);
  1458. this._hdrDirty = hdr !== this._hdr;
  1459. this._hdr = hdr;
  1460. },
  1461. },
  1462. /**
  1463. * Whether or not high dynamic range rendering is supported.
  1464. * @memberof Scene.prototype
  1465. * @type {Boolean}
  1466. * @readonly
  1467. * @default true
  1468. */
  1469. highDynamicRangeSupported: {
  1470. get: function () {
  1471. var context = this._context;
  1472. return (
  1473. context.depthTexture &&
  1474. (context.colorBufferFloat || context.colorBufferHalfFloat)
  1475. );
  1476. },
  1477. },
  1478. /**
  1479. * Whether or not the camera is underneath the globe.
  1480. * @memberof Scene.prototype
  1481. * @type {Boolean}
  1482. * @readonly
  1483. * @default false
  1484. */
  1485. cameraUnderground: {
  1486. get: function () {
  1487. return this._cameraUnderground;
  1488. },
  1489. },
  1490. /**
  1491. * Ratio between a pixel and a density-independent pixel. Provides a standard unit of
  1492. * measure for real pixel measurements appropriate to a particular device.
  1493. *
  1494. * @memberof Scene.prototype
  1495. * @type {Number}
  1496. * @default 1.0
  1497. * @private
  1498. */
  1499. pixelRatio: {
  1500. get: function () {
  1501. return this._frameState.pixelRatio;
  1502. },
  1503. set: function (value) {
  1504. this._frameState.pixelRatio = value;
  1505. },
  1506. },
  1507. /**
  1508. * @private
  1509. */
  1510. opaqueFrustumNearOffset: {
  1511. get: function () {
  1512. return 0.9999;
  1513. },
  1514. },
  1515. /**
  1516. * @private
  1517. */
  1518. globeHeight: {
  1519. get: function () {
  1520. return this._globeHeight;
  1521. },
  1522. },
  1523. });
  1524. /**
  1525. * Determines if a compressed texture format is supported.
  1526. * @param {String} format The texture format. May be the name of the format or the WebGL extension name, e.g. s3tc or WEBGL_compressed_texture_s3tc.
  1527. * @return {boolean} Whether or not the format is supported.
  1528. */
  1529. Scene.prototype.getCompressedTextureFormatSupported = function (format) {
  1530. var context = this.context;
  1531. return (
  1532. ((format === "WEBGL_compressed_texture_s3tc" || format === "s3tc") &&
  1533. context.s3tc) ||
  1534. ((format === "WEBGL_compressed_texture_pvrtc" || format === "pvrtc") &&
  1535. context.pvrtc) ||
  1536. ((format === "WEBGL_compressed_texture_etc1" || format === "etc1") &&
  1537. context.etc1)
  1538. );
  1539. };
  1540. function updateDerivedCommands(scene, command, shadowsDirty) {
  1541. var frameState = scene._frameState;
  1542. var context = scene._context;
  1543. var oit = scene._view.oit;
  1544. var lightShadowMaps = frameState.shadowState.lightShadowMaps;
  1545. var lightShadowsEnabled = frameState.shadowState.lightShadowsEnabled;
  1546. var derivedCommands = command.derivedCommands;
  1547. if (defined(command.pickId)) {
  1548. derivedCommands.picking = DerivedCommand.createPickDerivedCommand(
  1549. scene,
  1550. command,
  1551. context,
  1552. derivedCommands.picking
  1553. );
  1554. }
  1555. if (!command.pickOnly) {
  1556. derivedCommands.depth = DerivedCommand.createDepthOnlyDerivedCommand(
  1557. scene,
  1558. command,
  1559. context,
  1560. derivedCommands.depth
  1561. );
  1562. }
  1563. derivedCommands.originalCommand = command;
  1564. if (scene._hdr) {
  1565. derivedCommands.hdr = DerivedCommand.createHdrCommand(
  1566. command,
  1567. context,
  1568. derivedCommands.hdr
  1569. );
  1570. command = derivedCommands.hdr.command;
  1571. derivedCommands = command.derivedCommands;
  1572. }
  1573. if (lightShadowsEnabled && command.receiveShadows) {
  1574. derivedCommands.shadows = ShadowMap.createReceiveDerivedCommand(
  1575. lightShadowMaps,
  1576. command,
  1577. shadowsDirty,
  1578. context,
  1579. derivedCommands.shadows
  1580. );
  1581. }
  1582. if (command.pass === Pass.TRANSLUCENT && defined(oit) && oit.isSupported()) {
  1583. if (lightShadowsEnabled && command.receiveShadows) {
  1584. derivedCommands.oit = defined(derivedCommands.oit)
  1585. ? derivedCommands.oit
  1586. : {};
  1587. derivedCommands.oit.shadows = oit.createDerivedCommands(
  1588. derivedCommands.shadows.receiveCommand,
  1589. context,
  1590. derivedCommands.oit.shadows
  1591. );
  1592. } else {
  1593. derivedCommands.oit = oit.createDerivedCommands(
  1594. command,
  1595. context,
  1596. derivedCommands.oit
  1597. );
  1598. }
  1599. }
  1600. }
  1601. /**
  1602. * @private
  1603. */
  1604. Scene.prototype.updateDerivedCommands = function (command) {
  1605. if (!defined(command.derivedCommands)) {
  1606. // Is not a DrawCommand
  1607. return;
  1608. }
  1609. var frameState = this._frameState;
  1610. var context = this._context;
  1611. // Update derived commands when any shadow maps become dirty
  1612. var shadowsDirty = false;
  1613. var lastDirtyTime = frameState.shadowState.lastDirtyTime;
  1614. if (command.lastDirtyTime !== lastDirtyTime) {
  1615. command.lastDirtyTime = lastDirtyTime;
  1616. command.dirty = true;
  1617. shadowsDirty = true;
  1618. }
  1619. var useLogDepth = frameState.useLogDepth;
  1620. var useHdr = this._hdr;
  1621. var derivedCommands = command.derivedCommands;
  1622. var hasLogDepthDerivedCommands = defined(derivedCommands.logDepth);
  1623. var hasHdrCommands = defined(derivedCommands.hdr);
  1624. var hasDerivedCommands = defined(derivedCommands.originalCommand);
  1625. var needsLogDepthDerivedCommands = useLogDepth && !hasLogDepthDerivedCommands;
  1626. var needsHdrCommands = useHdr && !hasHdrCommands;
  1627. var needsDerivedCommands = (!useLogDepth || !useHdr) && !hasDerivedCommands;
  1628. command.dirty =
  1629. command.dirty ||
  1630. needsLogDepthDerivedCommands ||
  1631. needsHdrCommands ||
  1632. needsDerivedCommands;
  1633. if (command.dirty) {
  1634. command.dirty = false;
  1635. var shadowMaps = frameState.shadowState.shadowMaps;
  1636. var shadowsEnabled = frameState.shadowState.shadowsEnabled;
  1637. if (shadowsEnabled && command.castShadows) {
  1638. derivedCommands.shadows = ShadowMap.createCastDerivedCommand(
  1639. shadowMaps,
  1640. command,
  1641. shadowsDirty,
  1642. context,
  1643. derivedCommands.shadows
  1644. );
  1645. }
  1646. if (hasLogDepthDerivedCommands || needsLogDepthDerivedCommands) {
  1647. derivedCommands.logDepth = DerivedCommand.createLogDepthCommand(
  1648. command,
  1649. context,
  1650. derivedCommands.logDepth
  1651. );
  1652. updateDerivedCommands(
  1653. this,
  1654. derivedCommands.logDepth.command,
  1655. shadowsDirty
  1656. );
  1657. }
  1658. if (hasDerivedCommands || needsDerivedCommands) {
  1659. updateDerivedCommands(this, command, shadowsDirty);
  1660. }
  1661. }
  1662. };
  1663. var renderTilesetPassState = new Cesium3DTilePassState({
  1664. pass: Cesium3DTilePass.RENDER,
  1665. });
  1666. var preloadTilesetPassState = new Cesium3DTilePassState({
  1667. pass: Cesium3DTilePass.PRELOAD,
  1668. });
  1669. var preloadFlightTilesetPassState = new Cesium3DTilePassState({
  1670. pass: Cesium3DTilePass.PRELOAD_FLIGHT,
  1671. });
  1672. var requestRenderModeDeferCheckPassState = new Cesium3DTilePassState({
  1673. pass: Cesium3DTilePass.REQUEST_RENDER_MODE_DEFER_CHECK,
  1674. });
  1675. var scratchOccluderBoundingSphere = new BoundingSphere();
  1676. var scratchOccluder;
  1677. function getOccluder(scene) {
  1678. // TODO: The occluder is the top-level globe. When we add
  1679. // support for multiple central bodies, this should be the closest one.
  1680. var globe = scene.globe;
  1681. if (
  1682. scene._mode === SceneMode.SCENE3D &&
  1683. defined(globe) &&
  1684. globe.show &&
  1685. !scene._cameraUnderground &&
  1686. !scene._globeTranslucencyState.translucent
  1687. ) {
  1688. var ellipsoid = globe.ellipsoid;
  1689. var minimumTerrainHeight = scene.frameState.minimumTerrainHeight;
  1690. scratchOccluderBoundingSphere.radius =
  1691. ellipsoid.minimumRadius + minimumTerrainHeight;
  1692. scratchOccluder = Occluder.fromBoundingSphere(
  1693. scratchOccluderBoundingSphere,
  1694. scene.camera.positionWC,
  1695. scratchOccluder
  1696. );
  1697. return scratchOccluder;
  1698. }
  1699. return undefined;
  1700. }
  1701. /**
  1702. * @private
  1703. */
  1704. Scene.prototype.clearPasses = function (passes) {
  1705. passes.render = false;
  1706. passes.pick = false;
  1707. passes.depth = false;
  1708. passes.postProcess = false;
  1709. passes.offscreen = false;
  1710. };
  1711. function updateFrameNumber(scene, frameNumber, time) {
  1712. var frameState = scene._frameState;
  1713. frameState.frameNumber = frameNumber;
  1714. frameState.time = JulianDate.clone(time, frameState.time);
  1715. }
  1716. /**
  1717. * @private
  1718. */
  1719. Scene.prototype.updateFrameState = function () {
  1720. var camera = this.camera;
  1721. var frameState = this._frameState;
  1722. frameState.commandList.length = 0;
  1723. frameState.shadowMaps.length = 0;
  1724. frameState.brdfLutGenerator = this._brdfLutGenerator;
  1725. frameState.environmentMap = this.skyBox && this.skyBox._cubeMap;
  1726. frameState.mode = this._mode;
  1727. frameState.morphTime = this.morphTime;
  1728. frameState.mapProjection = this.mapProjection;
  1729. frameState.camera = camera;
  1730. frameState.cullingVolume = camera.frustum.computeCullingVolume(
  1731. camera.positionWC,
  1732. camera.directionWC,
  1733. camera.upWC
  1734. );
  1735. frameState.occluder = getOccluder(this);
  1736. frameState.terrainExaggeration = this._terrainExaggeration;
  1737. frameState.minimumTerrainHeight = 0.0;
  1738. frameState.minimumDisableDepthTestDistance = this._minimumDisableDepthTestDistance;
  1739. frameState.invertClassification = this.invertClassification;
  1740. frameState.useLogDepth =
  1741. this._logDepthBuffer &&
  1742. !(
  1743. this.camera.frustum instanceof OrthographicFrustum ||
  1744. this.camera.frustum instanceof OrthographicOffCenterFrustum
  1745. );
  1746. frameState.light = this.light;
  1747. frameState.cameraUnderground = this._cameraUnderground;
  1748. frameState.globeTranslucencyState = this._globeTranslucencyState;
  1749. if (
  1750. defined(this._specularEnvironmentMapAtlas) &&
  1751. this._specularEnvironmentMapAtlas.ready
  1752. ) {
  1753. frameState.specularEnvironmentMaps = this._specularEnvironmentMapAtlas.texture;
  1754. frameState.specularEnvironmentMapsMaximumLOD = this._specularEnvironmentMapAtlas.maximumMipmapLevel;
  1755. } else {
  1756. frameState.specularEnvironmentMaps = undefined;
  1757. frameState.specularEnvironmentMapsMaximumLOD = undefined;
  1758. }
  1759. frameState.sphericalHarmonicCoefficients = this.sphericalHarmonicCoefficients;
  1760. this._actualInvertClassificationColor = Color.clone(
  1761. this.invertClassificationColor,
  1762. this._actualInvertClassificationColor
  1763. );
  1764. if (!InvertClassification.isTranslucencySupported(this._context)) {
  1765. this._actualInvertClassificationColor.alpha = 1.0;
  1766. }
  1767. frameState.invertClassificationColor = this._actualInvertClassificationColor;
  1768. if (defined(this.globe)) {
  1769. frameState.maximumScreenSpaceError = this.globe.maximumScreenSpaceError;
  1770. } else {
  1771. frameState.maximumScreenSpaceError = 2;
  1772. }
  1773. this.clearPasses(frameState.passes);
  1774. frameState.tilesetPassState = undefined;
  1775. };
  1776. /**
  1777. * @private
  1778. */
  1779. Scene.prototype.isVisible = function (command, cullingVolume, occluder) {
  1780. return (
  1781. defined(command) &&
  1782. (!defined(command.boundingVolume) ||
  1783. !command.cull ||
  1784. (cullingVolume.computeVisibility(command.boundingVolume) !==
  1785. Intersect.OUTSIDE &&
  1786. (!defined(occluder) ||
  1787. !command.occlude ||
  1788. !command.boundingVolume.isOccluded(occluder))))
  1789. );
  1790. };
  1791. var transformFrom2D = new Matrix4(
  1792. 0.0,
  1793. 0.0,
  1794. 1.0,
  1795. 0.0,
  1796. 1.0,
  1797. 0.0,
  1798. 0.0,
  1799. 0.0,
  1800. 0.0,
  1801. 1.0,
  1802. 0.0,
  1803. 0.0,
  1804. 0.0,
  1805. 0.0,
  1806. 0.0,
  1807. 1.0
  1808. );
  1809. transformFrom2D = Matrix4.inverseTransformation(
  1810. transformFrom2D,
  1811. transformFrom2D
  1812. );
  1813. function debugShowBoundingVolume(command, scene, passState, debugFramebuffer) {
  1814. // Debug code to draw bounding volume for command. Not optimized!
  1815. // Assumes bounding volume is a bounding sphere or box
  1816. var frameState = scene._frameState;
  1817. var context = frameState.context;
  1818. var boundingVolume = command.boundingVolume;
  1819. if (defined(scene._debugVolume)) {
  1820. scene._debugVolume.destroy();
  1821. }
  1822. var geometry;
  1823. var center = Cartesian3.clone(boundingVolume.center);
  1824. if (frameState.mode !== SceneMode.SCENE3D) {
  1825. center = Matrix4.multiplyByPoint(transformFrom2D, center, center);
  1826. var projection = frameState.mapProjection;
  1827. var centerCartographic = projection.unproject(center);
  1828. center = projection.ellipsoid.cartographicToCartesian(centerCartographic);
  1829. }
  1830. if (defined(boundingVolume.radius)) {
  1831. var radius = boundingVolume.radius;
  1832. geometry = GeometryPipeline.toWireframe(
  1833. EllipsoidGeometry.createGeometry(
  1834. new EllipsoidGeometry({
  1835. radii: new Cartesian3(radius, radius, radius),
  1836. vertexFormat: PerInstanceColorAppearance.FLAT_VERTEX_FORMAT,
  1837. })
  1838. )
  1839. );
  1840. scene._debugVolume = new Primitive({
  1841. geometryInstances: new GeometryInstance({
  1842. geometry: geometry,
  1843. modelMatrix: Matrix4.fromTranslation(center),
  1844. attributes: {
  1845. color: new ColorGeometryInstanceAttribute(1.0, 0.0, 0.0, 1.0),
  1846. },
  1847. }),
  1848. appearance: new PerInstanceColorAppearance({
  1849. flat: true,
  1850. translucent: false,
  1851. }),
  1852. asynchronous: false,
  1853. });
  1854. } else {
  1855. var halfAxes = boundingVolume.halfAxes;
  1856. geometry = GeometryPipeline.toWireframe(
  1857. BoxGeometry.createGeometry(
  1858. BoxGeometry.fromDimensions({
  1859. dimensions: new Cartesian3(2.0, 2.0, 2.0),
  1860. vertexFormat: PerInstanceColorAppearance.FLAT_VERTEX_FORMAT,
  1861. })
  1862. )
  1863. );
  1864. scene._debugVolume = new Primitive({
  1865. geometryInstances: new GeometryInstance({
  1866. geometry: geometry,
  1867. modelMatrix: Matrix4.fromRotationTranslation(
  1868. halfAxes,
  1869. center,
  1870. new Matrix4()
  1871. ),
  1872. attributes: {
  1873. color: new ColorGeometryInstanceAttribute(1.0, 0.0, 0.0, 1.0),
  1874. },
  1875. }),
  1876. appearance: new PerInstanceColorAppearance({
  1877. flat: true,
  1878. translucent: false,
  1879. }),
  1880. asynchronous: false,
  1881. });
  1882. }
  1883. var savedCommandList = frameState.commandList;
  1884. var commandList = (frameState.commandList = []);
  1885. scene._debugVolume.update(frameState);
  1886. command = commandList[0];
  1887. if (frameState.useLogDepth) {
  1888. var logDepth = DerivedCommand.createLogDepthCommand(command, context);
  1889. command = logDepth.command;
  1890. }
  1891. var framebuffer;
  1892. if (defined(debugFramebuffer)) {
  1893. framebuffer = passState.framebuffer;
  1894. passState.framebuffer = debugFramebuffer;
  1895. }
  1896. command.execute(context, passState);
  1897. if (defined(framebuffer)) {
  1898. passState.framebuffer = framebuffer;
  1899. }
  1900. frameState.commandList = savedCommandList;
  1901. }
  1902. function executeCommand(command, scene, context, passState, debugFramebuffer) {
  1903. var frameState = scene._frameState;
  1904. if (defined(scene.debugCommandFilter) && !scene.debugCommandFilter(command)) {
  1905. return;
  1906. }
  1907. if (command instanceof ClearCommand) {
  1908. command.execute(context, passState);
  1909. return;
  1910. }
  1911. if (command.debugShowBoundingVolume && defined(command.boundingVolume)) {
  1912. debugShowBoundingVolume(command, scene, passState, debugFramebuffer);
  1913. }
  1914. if (frameState.useLogDepth && defined(command.derivedCommands.logDepth)) {
  1915. command = command.derivedCommands.logDepth.command;
  1916. }
  1917. var passes = frameState.passes;
  1918. if (
  1919. !passes.pick &&
  1920. !passes.depth &&
  1921. scene._hdr &&
  1922. defined(command.derivedCommands) &&
  1923. defined(command.derivedCommands.hdr)
  1924. ) {
  1925. command = command.derivedCommands.hdr.command;
  1926. }
  1927. if (passes.pick || passes.depth) {
  1928. if (
  1929. passes.pick &&
  1930. !passes.depth &&
  1931. defined(command.derivedCommands.picking)
  1932. ) {
  1933. command = command.derivedCommands.picking.pickCommand;
  1934. command.execute(context, passState);
  1935. return;
  1936. } else if (defined(command.derivedCommands.depth)) {
  1937. command = command.derivedCommands.depth.depthOnlyCommand;
  1938. command.execute(context, passState);
  1939. return;
  1940. }
  1941. }
  1942. if (scene.debugShowCommands || scene.debugShowFrustums) {
  1943. scene._debugInspector.executeDebugShowFrustumsCommand(
  1944. scene,
  1945. command,
  1946. passState
  1947. );
  1948. return;
  1949. }
  1950. if (
  1951. frameState.shadowState.lightShadowsEnabled &&
  1952. command.receiveShadows &&
  1953. defined(command.derivedCommands.shadows)
  1954. ) {
  1955. // If the command receives shadows, execute the derived shadows command.
  1956. // Some commands, such as OIT derived commands, do not have derived shadow commands themselves
  1957. // and instead shadowing is built-in. In this case execute the command regularly below.
  1958. command.derivedCommands.shadows.receiveCommand.execute(context, passState);
  1959. } else {
  1960. command.execute(context, passState);
  1961. }
  1962. }
  1963. function executeIdCommand(command, scene, context, passState) {
  1964. var frameState = scene._frameState;
  1965. var derivedCommands = command.derivedCommands;
  1966. if (!defined(derivedCommands)) {
  1967. return;
  1968. }
  1969. if (frameState.useLogDepth && defined(derivedCommands.logDepth)) {
  1970. command = derivedCommands.logDepth.command;
  1971. }
  1972. derivedCommands = command.derivedCommands;
  1973. if (defined(derivedCommands.picking)) {
  1974. command = derivedCommands.picking.pickCommand;
  1975. command.execute(context, passState);
  1976. } else if (defined(derivedCommands.depth)) {
  1977. command = derivedCommands.depth.depthOnlyCommand;
  1978. command.execute(context, passState);
  1979. }
  1980. }
  1981. function backToFront(a, b, position) {
  1982. return (
  1983. b.boundingVolume.distanceSquaredTo(position) -
  1984. a.boundingVolume.distanceSquaredTo(position)
  1985. );
  1986. }
  1987. function frontToBack(a, b, position) {
  1988. // When distances are equal equal favor sorting b before a. This gives render priority to commands later in the list.
  1989. return (
  1990. a.boundingVolume.distanceSquaredTo(position) -
  1991. b.boundingVolume.distanceSquaredTo(position) +
  1992. CesiumMath.EPSILON12
  1993. );
  1994. }
  1995. function executeTranslucentCommandsBackToFront(
  1996. scene,
  1997. executeFunction,
  1998. passState,
  1999. commands,
  2000. invertClassification
  2001. ) {
  2002. var context = scene.context;
  2003. mergeSort(commands, backToFront, scene.camera.positionWC);
  2004. if (defined(invertClassification)) {
  2005. executeFunction(
  2006. invertClassification.unclassifiedCommand,
  2007. scene,
  2008. context,
  2009. passState
  2010. );
  2011. }
  2012. var length = commands.length;
  2013. for (var i = 0; i < length; ++i) {
  2014. executeFunction(commands[i], scene, context, passState);
  2015. }
  2016. }
  2017. function executeTranslucentCommandsFrontToBack(
  2018. scene,
  2019. executeFunction,
  2020. passState,
  2021. commands,
  2022. invertClassification
  2023. ) {
  2024. var context = scene.context;
  2025. mergeSort(commands, frontToBack, scene.camera.positionWC);
  2026. if (defined(invertClassification)) {
  2027. executeFunction(
  2028. invertClassification.unclassifiedCommand,
  2029. scene,
  2030. context,
  2031. passState
  2032. );
  2033. }
  2034. var length = commands.length;
  2035. for (var i = 0; i < length; ++i) {
  2036. executeFunction(commands[i], scene, context, passState);
  2037. }
  2038. }
  2039. function getDebugGlobeDepth(scene, index) {
  2040. var globeDepths = scene._view.debugGlobeDepths;
  2041. var globeDepth = globeDepths[index];
  2042. if (!defined(globeDepth) && scene.context.depthTexture) {
  2043. globeDepth = new GlobeDepth();
  2044. globeDepths[index] = globeDepth;
  2045. }
  2046. return globeDepth;
  2047. }
  2048. var scratchPerspectiveFrustum = new PerspectiveFrustum();
  2049. var scratchPerspectiveOffCenterFrustum = new PerspectiveOffCenterFrustum();
  2050. var scratchOrthographicFrustum = new OrthographicFrustum();
  2051. var scratchOrthographicOffCenterFrustum = new OrthographicOffCenterFrustum();
  2052. function executeCommands(scene, passState) {
  2053. var camera = scene.camera;
  2054. var context = scene.context;
  2055. var frameState = scene.frameState;
  2056. var us = context.uniformState;
  2057. us.updateCamera(camera);
  2058. // Create a working frustum from the original camera frustum.
  2059. var frustum;
  2060. if (defined(camera.frustum.fov)) {
  2061. frustum = camera.frustum.clone(scratchPerspectiveFrustum);
  2062. } else if (defined(camera.frustum.infiniteProjectionMatrix)) {
  2063. frustum = camera.frustum.clone(scratchPerspectiveOffCenterFrustum);
  2064. } else if (defined(camera.frustum.width)) {
  2065. frustum = camera.frustum.clone(scratchOrthographicFrustum);
  2066. } else {
  2067. frustum = camera.frustum.clone(scratchOrthographicOffCenterFrustum);
  2068. }
  2069. // Ideally, we would render the sky box and atmosphere last for
  2070. // early-z, but we would have to draw it in each frustum
  2071. frustum.near = camera.frustum.near;
  2072. frustum.far = camera.frustum.far;
  2073. us.updateFrustum(frustum);
  2074. us.updatePass(Pass.ENVIRONMENT);
  2075. var passes = frameState.passes;
  2076. var picking = passes.pick;
  2077. var environmentState = scene._environmentState;
  2078. var view = scene._view;
  2079. var renderTranslucentDepthForPick =
  2080. environmentState.renderTranslucentDepthForPick;
  2081. var useWebVR = environmentState.useWebVR;
  2082. // Do not render environment primitives during a pick pass since they do not generate picking commands.
  2083. if (!picking) {
  2084. var skyBoxCommand = environmentState.skyBoxCommand;
  2085. if (defined(skyBoxCommand)) {
  2086. executeCommand(skyBoxCommand, scene, context, passState);
  2087. }
  2088. if (environmentState.isSkyAtmosphereVisible) {
  2089. executeCommand(
  2090. environmentState.skyAtmosphereCommand,
  2091. scene,
  2092. context,
  2093. passState
  2094. );
  2095. }
  2096. if (environmentState.isSunVisible) {
  2097. environmentState.sunDrawCommand.execute(context, passState);
  2098. if (scene.sunBloom && !useWebVR) {
  2099. var framebuffer;
  2100. if (environmentState.useGlobeDepthFramebuffer) {
  2101. framebuffer = view.globeDepth.framebuffer;
  2102. } else if (environmentState.usePostProcess) {
  2103. framebuffer = view.sceneFramebuffer.getFramebuffer();
  2104. } else {
  2105. framebuffer = environmentState.originalFramebuffer;
  2106. }
  2107. scene._sunPostProcess.execute(context);
  2108. scene._sunPostProcess.copy(context, framebuffer);
  2109. passState.framebuffer = framebuffer;
  2110. }
  2111. }
  2112. // Moon can be seen through the atmosphere, since the sun is rendered after the atmosphere.
  2113. if (environmentState.isMoonVisible) {
  2114. environmentState.moonCommand.execute(context, passState);
  2115. }
  2116. }
  2117. // Determine how translucent surfaces will be handled.
  2118. var executeTranslucentCommands;
  2119. if (environmentState.useOIT) {
  2120. if (!defined(scene._executeOITFunction)) {
  2121. scene._executeOITFunction = function (
  2122. scene,
  2123. executeFunction,
  2124. passState,
  2125. commands,
  2126. invertClassification
  2127. ) {
  2128. view.oit.executeCommands(
  2129. scene,
  2130. executeFunction,
  2131. passState,
  2132. commands,
  2133. invertClassification
  2134. );
  2135. };
  2136. }
  2137. executeTranslucentCommands = scene._executeOITFunction;
  2138. } else if (passes.render) {
  2139. executeTranslucentCommands = executeTranslucentCommandsBackToFront;
  2140. } else {
  2141. executeTranslucentCommands = executeTranslucentCommandsFrontToBack;
  2142. }
  2143. var frustumCommandsList = view.frustumCommandsList;
  2144. var numFrustums = frustumCommandsList.length;
  2145. var clearGlobeDepth = environmentState.clearGlobeDepth;
  2146. var useDepthPlane = environmentState.useDepthPlane;
  2147. var globeTranslucencyState = scene._globeTranslucencyState;
  2148. var globeTranslucent = globeTranslucencyState.translucent;
  2149. var globeTranslucencyFramebuffer = scene._view.globeTranslucencyFramebuffer;
  2150. var separatePrimitiveFramebuffer = (environmentState.separatePrimitiveFramebuffer = false);
  2151. var clearDepth = scene._depthClearCommand;
  2152. var clearStencil = scene._stencilClearCommand;
  2153. var clearClassificationStencil = scene._classificationStencilClearCommand;
  2154. var depthPlane = scene._depthPlane;
  2155. var usePostProcessSelected = environmentState.usePostProcessSelected;
  2156. var height2D = camera.position.z;
  2157. // Execute commands in each frustum in back to front order
  2158. var j;
  2159. for (var i = 0; i < numFrustums; ++i) {
  2160. var index = numFrustums - i - 1;
  2161. var frustumCommands = frustumCommandsList[index];
  2162. if (scene.mode === SceneMode.SCENE2D) {
  2163. // To avoid z-fighting in 2D, move the camera to just before the frustum
  2164. // and scale the frustum depth to be in [1.0, nearToFarDistance2D].
  2165. camera.position.z = height2D - frustumCommands.near + 1.0;
  2166. frustum.far = Math.max(1.0, frustumCommands.far - frustumCommands.near);
  2167. frustum.near = 1.0;
  2168. us.update(frameState);
  2169. us.updateFrustum(frustum);
  2170. } else {
  2171. // Avoid tearing artifacts between adjacent frustums in the opaque passes
  2172. frustum.near =
  2173. index !== 0
  2174. ? frustumCommands.near * scene.opaqueFrustumNearOffset
  2175. : frustumCommands.near;
  2176. frustum.far = frustumCommands.far;
  2177. us.updateFrustum(frustum);
  2178. }
  2179. var globeDepth = scene.debugShowGlobeDepth
  2180. ? getDebugGlobeDepth(scene, index)
  2181. : view.globeDepth;
  2182. if (separatePrimitiveFramebuffer) {
  2183. // Render to globe framebuffer in GLOBE pass
  2184. passState.framebuffer = globeDepth.framebuffer;
  2185. }
  2186. var fb;
  2187. if (
  2188. scene.debugShowGlobeDepth &&
  2189. defined(globeDepth) &&
  2190. environmentState.useGlobeDepthFramebuffer
  2191. ) {
  2192. globeDepth.update(
  2193. context,
  2194. passState,
  2195. view.viewport,
  2196. scene._hdr,
  2197. clearGlobeDepth
  2198. );
  2199. globeDepth.clear(context, passState, scene._clearColorCommand.color);
  2200. fb = passState.framebuffer;
  2201. passState.framebuffer = globeDepth.framebuffer;
  2202. }
  2203. clearDepth.execute(context, passState);
  2204. if (context.stencilBuffer) {
  2205. clearStencil.execute(context, passState);
  2206. }
  2207. us.updatePass(Pass.GLOBE);
  2208. var commands = frustumCommands.commands[Pass.GLOBE];
  2209. var length = frustumCommands.indices[Pass.GLOBE];
  2210. if (globeTranslucent) {
  2211. globeTranslucencyState.executeGlobeCommands(
  2212. frustumCommands,
  2213. executeCommand,
  2214. globeTranslucencyFramebuffer,
  2215. scene,
  2216. passState
  2217. );
  2218. } else {
  2219. for (j = 0; j < length; ++j) {
  2220. executeCommand(commands[j], scene, context, passState);
  2221. }
  2222. }
  2223. if (defined(globeDepth) && environmentState.useGlobeDepthFramebuffer) {
  2224. globeDepth.executeCopyDepth(context, passState);
  2225. }
  2226. if (
  2227. scene.debugShowGlobeDepth &&
  2228. defined(globeDepth) &&
  2229. environmentState.useGlobeDepthFramebuffer
  2230. ) {
  2231. passState.framebuffer = fb;
  2232. }
  2233. // Draw terrain classification
  2234. if (!environmentState.renderTranslucentDepthForPick) {
  2235. us.updatePass(Pass.TERRAIN_CLASSIFICATION);
  2236. commands = frustumCommands.commands[Pass.TERRAIN_CLASSIFICATION];
  2237. length = frustumCommands.indices[Pass.TERRAIN_CLASSIFICATION];
  2238. if (globeTranslucent) {
  2239. globeTranslucencyState.executeGlobeClassificationCommands(
  2240. frustumCommands,
  2241. executeCommand,
  2242. globeTranslucencyFramebuffer,
  2243. scene,
  2244. passState
  2245. );
  2246. } else {
  2247. for (j = 0; j < length; ++j) {
  2248. executeCommand(commands[j], scene, context, passState);
  2249. }
  2250. }
  2251. }
  2252. if (clearGlobeDepth) {
  2253. clearDepth.execute(context, passState);
  2254. if (useDepthPlane) {
  2255. depthPlane.execute(context, passState);
  2256. }
  2257. }
  2258. if (separatePrimitiveFramebuffer) {
  2259. // Render to primitive framebuffer in all other passes
  2260. passState.framebuffer = globeDepth.primitiveFramebuffer;
  2261. }
  2262. if (
  2263. !environmentState.useInvertClassification ||
  2264. picking ||
  2265. environmentState.renderTranslucentDepthForPick
  2266. ) {
  2267. // Common/fastest path. Draw 3D Tiles and classification normally.
  2268. // Draw 3D Tiles
  2269. us.updatePass(Pass.CESIUM_3D_TILE);
  2270. commands = frustumCommands.commands[Pass.CESIUM_3D_TILE];
  2271. length = frustumCommands.indices[Pass.CESIUM_3D_TILE];
  2272. for (j = 0; j < length; ++j) {
  2273. executeCommand(commands[j], scene, context, passState);
  2274. }
  2275. if (length > 0) {
  2276. if (defined(globeDepth) && environmentState.useGlobeDepthFramebuffer) {
  2277. globeDepth.executeUpdateDepth(context, passState, clearGlobeDepth);
  2278. }
  2279. // Draw classifications. Modifies 3D Tiles color.
  2280. if (!environmentState.renderTranslucentDepthForPick) {
  2281. us.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION);
  2282. commands =
  2283. frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION];
  2284. length = frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION];
  2285. for (j = 0; j < length; ++j) {
  2286. executeCommand(commands[j], scene, context, passState);
  2287. }
  2288. }
  2289. }
  2290. } else {
  2291. // When the invert classification color is opaque:
  2292. // Main FBO (FBO1): Main_Color + Main_DepthStencil
  2293. // Invert classification FBO (FBO2) : Invert_Color + Main_DepthStencil
  2294. //
  2295. // 1. Clear FBO2 color to vec4(0.0) for each frustum
  2296. // 2. Draw 3D Tiles to FBO2
  2297. // 3. Draw classification to FBO2
  2298. // 4. Fullscreen pass to FBO1, draw Invert_Color when:
  2299. // * Main_DepthStencil has the stencil bit set > 0 (classified)
  2300. // 5. Fullscreen pass to FBO1, draw Invert_Color * czm_invertClassificationColor when:
  2301. // * Main_DepthStencil has stencil bit set to 0 (unclassified) and
  2302. // * Invert_Color !== vec4(0.0)
  2303. //
  2304. // When the invert classification color is translucent:
  2305. // Main FBO (FBO1): Main_Color + Main_DepthStencil
  2306. // Invert classification FBO (FBO2): Invert_Color + Invert_DepthStencil
  2307. // IsClassified FBO (FBO3): IsClassified_Color + Invert_DepthStencil
  2308. //
  2309. // 1. Clear FBO2 and FBO3 color to vec4(0.0), stencil to 0, and depth to 1.0
  2310. // 2. Draw 3D Tiles to FBO2
  2311. // 3. Draw classification to FBO2
  2312. // 4. Fullscreen pass to FBO3, draw any color when
  2313. // * Invert_DepthStencil has the stencil bit set > 0 (classified)
  2314. // 5. Fullscreen pass to FBO1, draw Invert_Color when:
  2315. // * Invert_Color !== vec4(0.0) and
  2316. // * IsClassified_Color !== vec4(0.0)
  2317. // 6. Fullscreen pass to FBO1, draw Invert_Color * czm_invertClassificationColor when:
  2318. // * Invert_Color !== vec4(0.0) and
  2319. // * IsClassified_Color === vec4(0.0)
  2320. //
  2321. // NOTE: Step six when translucent invert color occurs after the TRANSLUCENT pass
  2322. //
  2323. scene._invertClassification.clear(context, passState);
  2324. var opaqueClassificationFramebuffer = passState.framebuffer;
  2325. passState.framebuffer = scene._invertClassification._fbo;
  2326. // Draw normally
  2327. us.updatePass(Pass.CESIUM_3D_TILE);
  2328. commands = frustumCommands.commands[Pass.CESIUM_3D_TILE];
  2329. length = frustumCommands.indices[Pass.CESIUM_3D_TILE];
  2330. for (j = 0; j < length; ++j) {
  2331. executeCommand(commands[j], scene, context, passState);
  2332. }
  2333. if (defined(globeDepth) && environmentState.useGlobeDepthFramebuffer) {
  2334. globeDepth.executeUpdateDepth(context, passState, clearGlobeDepth);
  2335. }
  2336. // Set stencil
  2337. us.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW);
  2338. commands =
  2339. frustumCommands.commands[
  2340. Pass.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW
  2341. ];
  2342. length =
  2343. frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION_IGNORE_SHOW];
  2344. for (j = 0; j < length; ++j) {
  2345. executeCommand(commands[j], scene, context, passState);
  2346. }
  2347. passState.framebuffer = opaqueClassificationFramebuffer;
  2348. // Fullscreen pass to copy classified fragments
  2349. scene._invertClassification.executeClassified(context, passState);
  2350. if (frameState.invertClassificationColor.alpha === 1.0) {
  2351. // Fullscreen pass to copy unclassified fragments when alpha == 1.0
  2352. scene._invertClassification.executeUnclassified(context, passState);
  2353. }
  2354. // Clear stencil set by the classification for the next classification pass
  2355. if (length > 0 && context.stencilBuffer) {
  2356. clearClassificationStencil.execute(context, passState);
  2357. }
  2358. // Draw style over classification.
  2359. us.updatePass(Pass.CESIUM_3D_TILE_CLASSIFICATION);
  2360. commands = frustumCommands.commands[Pass.CESIUM_3D_TILE_CLASSIFICATION];
  2361. length = frustumCommands.indices[Pass.CESIUM_3D_TILE_CLASSIFICATION];
  2362. for (j = 0; j < length; ++j) {
  2363. executeCommand(commands[j], scene, context, passState);
  2364. }
  2365. }
  2366. if (length > 0 && context.stencilBuffer) {
  2367. clearStencil.execute(context, passState);
  2368. }
  2369. us.updatePass(Pass.OPAQUE);
  2370. commands = frustumCommands.commands[Pass.OPAQUE];
  2371. length = frustumCommands.indices[Pass.OPAQUE];
  2372. for (j = 0; j < length; ++j) {
  2373. executeCommand(commands[j], scene, context, passState);
  2374. }
  2375. if (index !== 0 && scene.mode !== SceneMode.SCENE2D) {
  2376. // Do not overlap frustums in the translucent pass to avoid blending artifacts
  2377. frustum.near = frustumCommands.near;
  2378. us.updateFrustum(frustum);
  2379. }
  2380. var invertClassification;
  2381. if (
  2382. !picking &&
  2383. environmentState.useInvertClassification &&
  2384. frameState.invertClassificationColor.alpha < 1.0
  2385. ) {
  2386. // Fullscreen pass to copy unclassified fragments when alpha < 1.0.
  2387. // Not executed when undefined.
  2388. invertClassification = scene._invertClassification;
  2389. }
  2390. us.updatePass(Pass.TRANSLUCENT);
  2391. commands = frustumCommands.commands[Pass.TRANSLUCENT];
  2392. commands.length = frustumCommands.indices[Pass.TRANSLUCENT];
  2393. executeTranslucentCommands(
  2394. scene,
  2395. executeCommand,
  2396. passState,
  2397. commands,
  2398. invertClassification
  2399. );
  2400. if (
  2401. context.depthTexture &&
  2402. scene.useDepthPicking &&
  2403. (environmentState.useGlobeDepthFramebuffer ||
  2404. renderTranslucentDepthForPick)
  2405. ) {
  2406. // PERFORMANCE_IDEA: Use MRT to avoid the extra copy.
  2407. var depthStencilTexture = renderTranslucentDepthForPick
  2408. ? passState.framebuffer.depthStencilTexture
  2409. : globeDepth.framebuffer.depthStencilTexture;
  2410. var pickDepth = scene._picking.getPickDepth(scene, index);
  2411. pickDepth.update(context, depthStencilTexture);
  2412. pickDepth.executeCopyDepth(context, passState);
  2413. }
  2414. if (separatePrimitiveFramebuffer) {
  2415. // Reset framebuffer
  2416. passState.framebuffer = globeDepth.framebuffer;
  2417. }
  2418. if (picking || !usePostProcessSelected) {
  2419. continue;
  2420. }
  2421. var originalFramebuffer = passState.framebuffer;
  2422. passState.framebuffer = view.sceneFramebuffer.getIdFramebuffer();
  2423. // reset frustum
  2424. frustum.near =
  2425. index !== 0
  2426. ? frustumCommands.near * scene.opaqueFrustumNearOffset
  2427. : frustumCommands.near;
  2428. frustum.far = frustumCommands.far;
  2429. us.updateFrustum(frustum);
  2430. us.updatePass(Pass.GLOBE);
  2431. commands = frustumCommands.commands[Pass.GLOBE];
  2432. length = frustumCommands.indices[Pass.GLOBE];
  2433. if (globeTranslucent) {
  2434. globeTranslucencyState.executeGlobeCommands(
  2435. frustumCommands,
  2436. executeIdCommand,
  2437. globeTranslucencyFramebuffer,
  2438. scene,
  2439. passState
  2440. );
  2441. } else {
  2442. for (j = 0; j < length; ++j) {
  2443. executeIdCommand(commands[j], scene, context, passState);
  2444. }
  2445. }
  2446. if (clearGlobeDepth) {
  2447. clearDepth.framebuffer = passState.framebuffer;
  2448. clearDepth.execute(context, passState);
  2449. clearDepth.framebuffer = undefined;
  2450. }
  2451. if (clearGlobeDepth && useDepthPlane) {
  2452. depthPlane.execute(context, passState);
  2453. }
  2454. us.updatePass(Pass.CESIUM_3D_TILE);
  2455. commands = frustumCommands.commands[Pass.CESIUM_3D_TILE];
  2456. length = frustumCommands.indices[Pass.CESIUM_3D_TILE];
  2457. for (j = 0; j < length; ++j) {
  2458. executeIdCommand(commands[j], scene, context, passState);
  2459. }
  2460. us.updatePass(Pass.OPAQUE);
  2461. commands = frustumCommands.commands[Pass.OPAQUE];
  2462. length = frustumCommands.indices[Pass.OPAQUE];
  2463. for (j = 0; j < length; ++j) {
  2464. executeIdCommand(commands[j], scene, context, passState);
  2465. }
  2466. us.updatePass(Pass.TRANSLUCENT);
  2467. commands = frustumCommands.commands[Pass.TRANSLUCENT];
  2468. length = frustumCommands.indices[Pass.TRANSLUCENT];
  2469. for (j = 0; j < length; ++j) {
  2470. executeIdCommand(commands[j], scene, context, passState);
  2471. }
  2472. passState.framebuffer = originalFramebuffer;
  2473. }
  2474. }
  2475. function executeComputeCommands(scene) {
  2476. var us = scene.context.uniformState;
  2477. us.updatePass(Pass.COMPUTE);
  2478. var sunComputeCommand = scene._environmentState.sunComputeCommand;
  2479. if (defined(sunComputeCommand)) {
  2480. sunComputeCommand.execute(scene._computeEngine);
  2481. }
  2482. var commandList = scene._computeCommandList;
  2483. var length = commandList.length;
  2484. for (var i = 0; i < length; ++i) {
  2485. commandList[i].execute(scene._computeEngine);
  2486. }
  2487. }
  2488. function executeOverlayCommands(scene, passState) {
  2489. var us = scene.context.uniformState;
  2490. us.updatePass(Pass.OVERLAY);
  2491. var context = scene.context;
  2492. var commandList = scene._overlayCommandList;
  2493. var length = commandList.length;
  2494. for (var i = 0; i < length; ++i) {
  2495. commandList[i].execute(context, passState);
  2496. }
  2497. }
  2498. function insertShadowCastCommands(scene, commandList, shadowMap) {
  2499. var shadowVolume = shadowMap.shadowMapCullingVolume;
  2500. var isPointLight = shadowMap.isPointLight;
  2501. var passes = shadowMap.passes;
  2502. var numberOfPasses = passes.length;
  2503. var length = commandList.length;
  2504. for (var i = 0; i < length; ++i) {
  2505. var command = commandList[i];
  2506. scene.updateDerivedCommands(command);
  2507. if (
  2508. command.castShadows &&
  2509. (command.pass === Pass.GLOBE ||
  2510. command.pass === Pass.CESIUM_3D_TILE ||
  2511. command.pass === Pass.OPAQUE ||
  2512. command.pass === Pass.TRANSLUCENT)
  2513. ) {
  2514. if (scene.isVisible(command, shadowVolume)) {
  2515. if (isPointLight) {
  2516. for (var k = 0; k < numberOfPasses; ++k) {
  2517. passes[k].commandList.push(command);
  2518. }
  2519. } else if (numberOfPasses === 1) {
  2520. passes[0].commandList.push(command);
  2521. } else {
  2522. var wasVisible = false;
  2523. // Loop over cascades from largest to smallest
  2524. for (var j = numberOfPasses - 1; j >= 0; --j) {
  2525. var cascadeVolume = passes[j].cullingVolume;
  2526. if (scene.isVisible(command, cascadeVolume)) {
  2527. passes[j].commandList.push(command);
  2528. wasVisible = true;
  2529. } else if (wasVisible) {
  2530. // If it was visible in the previous cascade but now isn't
  2531. // then there is no need to check any more cascades
  2532. break;
  2533. }
  2534. }
  2535. }
  2536. }
  2537. }
  2538. }
  2539. }
  2540. function executeShadowMapCastCommands(scene) {
  2541. var frameState = scene.frameState;
  2542. var shadowMaps = frameState.shadowState.shadowMaps;
  2543. var shadowMapLength = shadowMaps.length;
  2544. if (!frameState.shadowState.shadowsEnabled) {
  2545. return;
  2546. }
  2547. var context = scene.context;
  2548. var uniformState = context.uniformState;
  2549. for (var i = 0; i < shadowMapLength; ++i) {
  2550. var shadowMap = shadowMaps[i];
  2551. if (shadowMap.outOfView) {
  2552. continue;
  2553. }
  2554. // Reset the command lists
  2555. var j;
  2556. var passes = shadowMap.passes;
  2557. var numberOfPasses = passes.length;
  2558. for (j = 0; j < numberOfPasses; ++j) {
  2559. passes[j].commandList.length = 0;
  2560. }
  2561. // Insert the primitive/model commands into the command lists
  2562. var sceneCommands = scene.frameState.commandList;
  2563. insertShadowCastCommands(scene, sceneCommands, shadowMap);
  2564. for (j = 0; j < numberOfPasses; ++j) {
  2565. var pass = shadowMap.passes[j];
  2566. uniformState.updateCamera(pass.camera);
  2567. shadowMap.updatePass(context, j);
  2568. var numberOfCommands = pass.commandList.length;
  2569. for (var k = 0; k < numberOfCommands; ++k) {
  2570. var command = pass.commandList[k];
  2571. // Set the correct pass before rendering into the shadow map because some shaders
  2572. // conditionally render based on whether the pass is translucent or opaque.
  2573. uniformState.updatePass(command.pass);
  2574. executeCommand(
  2575. command.derivedCommands.shadows.castCommands[i],
  2576. scene,
  2577. context,
  2578. pass.passState
  2579. );
  2580. }
  2581. }
  2582. }
  2583. }
  2584. var scratchEyeTranslation = new Cartesian3();
  2585. /**
  2586. * @private
  2587. */
  2588. Scene.prototype.updateAndExecuteCommands = function (
  2589. passState,
  2590. backgroundColor
  2591. ) {
  2592. var frameState = this._frameState;
  2593. var mode = frameState.mode;
  2594. var useWebVR = this._environmentState.useWebVR;
  2595. if (useWebVR) {
  2596. executeWebVRCommands(this, passState, backgroundColor);
  2597. } else if (
  2598. mode !== SceneMode.SCENE2D ||
  2599. this._mapMode2D === MapMode2D.ROTATE
  2600. ) {
  2601. executeCommandsInViewport(true, this, passState, backgroundColor);
  2602. } else {
  2603. updateAndClearFramebuffers(this, passState, backgroundColor);
  2604. execute2DViewportCommands(this, passState);
  2605. }
  2606. };
  2607. function executeWebVRCommands(scene, passState, backgroundColor) {
  2608. var view = scene._view;
  2609. var camera = view.camera;
  2610. var environmentState = scene._environmentState;
  2611. var renderTranslucentDepthForPick =
  2612. environmentState.renderTranslucentDepthForPick;
  2613. updateAndClearFramebuffers(scene, passState, backgroundColor);
  2614. if (!renderTranslucentDepthForPick) {
  2615. updateAndRenderPrimitives(scene);
  2616. }
  2617. view.createPotentiallyVisibleSet(scene);
  2618. if (!renderTranslucentDepthForPick) {
  2619. executeComputeCommands(scene);
  2620. executeShadowMapCastCommands(scene);
  2621. }
  2622. // Based on Calculating Stereo pairs by Paul Bourke
  2623. // http://paulbourke.net/stereographics/stereorender/
  2624. var viewport = passState.viewport;
  2625. viewport.x = 0;
  2626. viewport.y = 0;
  2627. viewport.width = viewport.width * 0.5;
  2628. var savedCamera = Camera.clone(camera, scene._cameraVR);
  2629. savedCamera.frustum = camera.frustum;
  2630. var near = camera.frustum.near;
  2631. var fo = near * defaultValue(scene.focalLength, 5.0);
  2632. var eyeSeparation = defaultValue(scene.eyeSeparation, fo / 30.0);
  2633. var eyeTranslation = Cartesian3.multiplyByScalar(
  2634. savedCamera.right,
  2635. eyeSeparation * 0.5,
  2636. scratchEyeTranslation
  2637. );
  2638. camera.frustum.aspectRatio = viewport.width / viewport.height;
  2639. var offset = (0.5 * eyeSeparation * near) / fo;
  2640. Cartesian3.add(savedCamera.position, eyeTranslation, camera.position);
  2641. camera.frustum.xOffset = offset;
  2642. executeCommands(scene, passState);
  2643. viewport.x = viewport.width;
  2644. Cartesian3.subtract(savedCamera.position, eyeTranslation, camera.position);
  2645. camera.frustum.xOffset = -offset;
  2646. executeCommands(scene, passState);
  2647. Camera.clone(savedCamera, camera);
  2648. }
  2649. var scratch2DViewportCartographic = new Cartographic(
  2650. Math.PI,
  2651. CesiumMath.PI_OVER_TWO
  2652. );
  2653. var scratch2DViewportMaxCoord = new Cartesian3();
  2654. var scratch2DViewportSavedPosition = new Cartesian3();
  2655. var scratch2DViewportTransform = new Matrix4();
  2656. var scratch2DViewportCameraTransform = new Matrix4();
  2657. var scratch2DViewportEyePoint = new Cartesian3();
  2658. var scratch2DViewportWindowCoords = new Cartesian3();
  2659. var scratch2DViewport = new BoundingRectangle();
  2660. function execute2DViewportCommands(scene, passState) {
  2661. var context = scene.context;
  2662. var frameState = scene.frameState;
  2663. var camera = scene.camera;
  2664. var originalViewport = passState.viewport;
  2665. var viewport = BoundingRectangle.clone(originalViewport, scratch2DViewport);
  2666. passState.viewport = viewport;
  2667. var maxCartographic = scratch2DViewportCartographic;
  2668. var maxCoord = scratch2DViewportMaxCoord;
  2669. var projection = scene.mapProjection;
  2670. projection.project(maxCartographic, maxCoord);
  2671. var position = Cartesian3.clone(
  2672. camera.position,
  2673. scratch2DViewportSavedPosition
  2674. );
  2675. var transform = Matrix4.clone(
  2676. camera.transform,
  2677. scratch2DViewportCameraTransform
  2678. );
  2679. var frustum = camera.frustum.clone();
  2680. camera._setTransform(Matrix4.IDENTITY);
  2681. var viewportTransformation = Matrix4.computeViewportTransformation(
  2682. viewport,
  2683. 0.0,
  2684. 1.0,
  2685. scratch2DViewportTransform
  2686. );
  2687. var projectionMatrix = camera.frustum.projectionMatrix;
  2688. var x = camera.positionWC.y;
  2689. var eyePoint = Cartesian3.fromElements(
  2690. CesiumMath.sign(x) * maxCoord.x - x,
  2691. 0.0,
  2692. -camera.positionWC.x,
  2693. scratch2DViewportEyePoint
  2694. );
  2695. var windowCoordinates = Transforms.pointToGLWindowCoordinates(
  2696. projectionMatrix,
  2697. viewportTransformation,
  2698. eyePoint,
  2699. scratch2DViewportWindowCoords
  2700. );
  2701. windowCoordinates.x = Math.floor(windowCoordinates.x);
  2702. var viewportX = viewport.x;
  2703. var viewportWidth = viewport.width;
  2704. if (
  2705. x === 0.0 ||
  2706. windowCoordinates.x <= viewportX ||
  2707. windowCoordinates.x >= viewportX + viewportWidth
  2708. ) {
  2709. executeCommandsInViewport(true, scene, passState);
  2710. } else if (
  2711. Math.abs(viewportX + viewportWidth * 0.5 - windowCoordinates.x) < 1.0
  2712. ) {
  2713. viewport.width = windowCoordinates.x - viewport.x;
  2714. camera.position.x *= CesiumMath.sign(camera.position.x);
  2715. camera.frustum.right = 0.0;
  2716. frameState.cullingVolume = camera.frustum.computeCullingVolume(
  2717. camera.positionWC,
  2718. camera.directionWC,
  2719. camera.upWC
  2720. );
  2721. context.uniformState.update(frameState);
  2722. executeCommandsInViewport(true, scene, passState);
  2723. viewport.x = windowCoordinates.x;
  2724. camera.position.x = -camera.position.x;
  2725. camera.frustum.right = -camera.frustum.left;
  2726. camera.frustum.left = 0.0;
  2727. frameState.cullingVolume = camera.frustum.computeCullingVolume(
  2728. camera.positionWC,
  2729. camera.directionWC,
  2730. camera.upWC
  2731. );
  2732. context.uniformState.update(frameState);
  2733. executeCommandsInViewport(false, scene, passState);
  2734. } else if (windowCoordinates.x > viewportX + viewportWidth * 0.5) {
  2735. viewport.width = windowCoordinates.x - viewportX;
  2736. var right = camera.frustum.right;
  2737. camera.frustum.right = maxCoord.x - x;
  2738. frameState.cullingVolume = camera.frustum.computeCullingVolume(
  2739. camera.positionWC,
  2740. camera.directionWC,
  2741. camera.upWC
  2742. );
  2743. context.uniformState.update(frameState);
  2744. executeCommandsInViewport(true, scene, passState);
  2745. viewport.x = windowCoordinates.x;
  2746. viewport.width = viewportX + viewportWidth - windowCoordinates.x;
  2747. camera.position.x = -camera.position.x;
  2748. camera.frustum.left = -camera.frustum.right;
  2749. camera.frustum.right = right - camera.frustum.right * 2.0;
  2750. frameState.cullingVolume = camera.frustum.computeCullingVolume(
  2751. camera.positionWC,
  2752. camera.directionWC,
  2753. camera.upWC
  2754. );
  2755. context.uniformState.update(frameState);
  2756. executeCommandsInViewport(false, scene, passState);
  2757. } else {
  2758. viewport.x = windowCoordinates.x;
  2759. viewport.width = viewportX + viewportWidth - windowCoordinates.x;
  2760. var left = camera.frustum.left;
  2761. camera.frustum.left = -maxCoord.x - x;
  2762. frameState.cullingVolume = camera.frustum.computeCullingVolume(
  2763. camera.positionWC,
  2764. camera.directionWC,
  2765. camera.upWC
  2766. );
  2767. context.uniformState.update(frameState);
  2768. executeCommandsInViewport(true, scene, passState);
  2769. viewport.x = viewportX;
  2770. viewport.width = windowCoordinates.x - viewportX;
  2771. camera.position.x = -camera.position.x;
  2772. camera.frustum.right = -camera.frustum.left;
  2773. camera.frustum.left = left - camera.frustum.left * 2.0;
  2774. frameState.cullingVolume = camera.frustum.computeCullingVolume(
  2775. camera.positionWC,
  2776. camera.directionWC,
  2777. camera.upWC
  2778. );
  2779. context.uniformState.update(frameState);
  2780. executeCommandsInViewport(false, scene, passState);
  2781. }
  2782. camera._setTransform(transform);
  2783. Cartesian3.clone(position, camera.position);
  2784. camera.frustum = frustum.clone();
  2785. passState.viewport = originalViewport;
  2786. }
  2787. function executeCommandsInViewport(
  2788. firstViewport,
  2789. scene,
  2790. passState,
  2791. backgroundColor
  2792. ) {
  2793. var environmentState = scene._environmentState;
  2794. var view = scene._view;
  2795. var renderTranslucentDepthForPick =
  2796. environmentState.renderTranslucentDepthForPick;
  2797. if (!firstViewport && !renderTranslucentDepthForPick) {
  2798. scene.frameState.commandList.length = 0;
  2799. }
  2800. if (!renderTranslucentDepthForPick) {
  2801. updateAndRenderPrimitives(scene);
  2802. }
  2803. view.createPotentiallyVisibleSet(scene);
  2804. if (firstViewport) {
  2805. if (defined(backgroundColor)) {
  2806. updateAndClearFramebuffers(scene, passState, backgroundColor);
  2807. }
  2808. if (!renderTranslucentDepthForPick) {
  2809. executeComputeCommands(scene);
  2810. executeShadowMapCastCommands(scene);
  2811. }
  2812. }
  2813. executeCommands(scene, passState);
  2814. }
  2815. var scratchCullingVolume = new CullingVolume();
  2816. /**
  2817. * @private
  2818. */
  2819. Scene.prototype.updateEnvironment = function () {
  2820. var frameState = this._frameState;
  2821. var view = this._view;
  2822. // Update celestial and terrestrial environment effects.
  2823. var environmentState = this._environmentState;
  2824. var renderPass = frameState.passes.render;
  2825. var offscreenPass = frameState.passes.offscreen;
  2826. var skyAtmosphere = this.skyAtmosphere;
  2827. var globe = this.globe;
  2828. var globeTranslucencyState = this._globeTranslucencyState;
  2829. if (
  2830. !renderPass ||
  2831. (this._mode !== SceneMode.SCENE2D &&
  2832. view.camera.frustum instanceof OrthographicFrustum) ||
  2833. !globeTranslucencyState.environmentVisible
  2834. ) {
  2835. environmentState.skyAtmosphereCommand = undefined;
  2836. environmentState.skyBoxCommand = undefined;
  2837. environmentState.sunDrawCommand = undefined;
  2838. environmentState.sunComputeCommand = undefined;
  2839. environmentState.moonCommand = undefined;
  2840. } else {
  2841. if (defined(skyAtmosphere)) {
  2842. if (defined(globe)) {
  2843. skyAtmosphere.setDynamicAtmosphereColor(
  2844. globe.enableLighting && globe.dynamicAtmosphereLighting,
  2845. globe.dynamicAtmosphereLightingFromSun
  2846. );
  2847. environmentState.isReadyForAtmosphere =
  2848. environmentState.isReadyForAtmosphere ||
  2849. globe._surface._tilesToRender.length > 0;
  2850. }
  2851. environmentState.skyAtmosphereCommand = skyAtmosphere.update(
  2852. frameState,
  2853. globe
  2854. );
  2855. if (defined(environmentState.skyAtmosphereCommand)) {
  2856. this.updateDerivedCommands(environmentState.skyAtmosphereCommand);
  2857. }
  2858. } else {
  2859. environmentState.skyAtmosphereCommand = undefined;
  2860. }
  2861. environmentState.skyBoxCommand = defined(this.skyBox)
  2862. ? this.skyBox.update(frameState, this._hdr)
  2863. : undefined;
  2864. var sunCommands = defined(this.sun)
  2865. ? this.sun.update(frameState, view.passState, this._hdr)
  2866. : undefined;
  2867. environmentState.sunDrawCommand = defined(sunCommands)
  2868. ? sunCommands.drawCommand
  2869. : undefined;
  2870. environmentState.sunComputeCommand = defined(sunCommands)
  2871. ? sunCommands.computeCommand
  2872. : undefined;
  2873. environmentState.moonCommand = defined(this.moon)
  2874. ? this.moon.update(frameState)
  2875. : undefined;
  2876. }
  2877. var clearGlobeDepth = (environmentState.clearGlobeDepth =
  2878. defined(globe) &&
  2879. globe.show &&
  2880. (!globe.depthTestAgainstTerrain || this.mode === SceneMode.SCENE2D));
  2881. var useDepthPlane = (environmentState.useDepthPlane =
  2882. clearGlobeDepth &&
  2883. this.mode === SceneMode.SCENE3D &&
  2884. globeTranslucencyState.useDepthPlane);
  2885. if (useDepthPlane) {
  2886. // Update the depth plane that is rendered in 3D when the primitives are
  2887. // not depth tested against terrain so primitives on the backface
  2888. // of the globe are not picked.
  2889. this._depthPlane.update(frameState);
  2890. }
  2891. environmentState.renderTranslucentDepthForPick = false;
  2892. environmentState.useWebVR =
  2893. this._useWebVR && this.mode !== SceneMode.SCENE2D && !offscreenPass;
  2894. var occluder =
  2895. frameState.mode === SceneMode.SCENE3D &&
  2896. !globeTranslucencyState.sunVisibleThroughGlobe
  2897. ? frameState.occluder
  2898. : undefined;
  2899. var cullingVolume = frameState.cullingVolume;
  2900. // get user culling volume minus the far plane.
  2901. var planes = scratchCullingVolume.planes;
  2902. for (var k = 0; k < 5; ++k) {
  2903. planes[k] = cullingVolume.planes[k];
  2904. }
  2905. cullingVolume = scratchCullingVolume;
  2906. // Determine visibility of celestial and terrestrial environment effects.
  2907. environmentState.isSkyAtmosphereVisible =
  2908. defined(environmentState.skyAtmosphereCommand) &&
  2909. environmentState.isReadyForAtmosphere;
  2910. environmentState.isSunVisible = this.isVisible(
  2911. environmentState.sunDrawCommand,
  2912. cullingVolume,
  2913. occluder
  2914. );
  2915. environmentState.isMoonVisible = this.isVisible(
  2916. environmentState.moonCommand,
  2917. cullingVolume,
  2918. occluder
  2919. );
  2920. var envMaps = this.specularEnvironmentMaps;
  2921. var envMapAtlas = this._specularEnvironmentMapAtlas;
  2922. if (
  2923. defined(envMaps) &&
  2924. (!defined(envMapAtlas) || envMapAtlas.url !== envMaps)
  2925. ) {
  2926. envMapAtlas = envMapAtlas && envMapAtlas.destroy();
  2927. this._specularEnvironmentMapAtlas = new OctahedralProjectedCubeMap(envMaps);
  2928. } else if (!defined(envMaps) && defined(envMapAtlas)) {
  2929. envMapAtlas.destroy();
  2930. this._specularEnvironmentMapAtlas = undefined;
  2931. }
  2932. if (defined(this._specularEnvironmentMapAtlas)) {
  2933. this._specularEnvironmentMapAtlas.update(frameState);
  2934. }
  2935. };
  2936. function updateDebugFrustumPlanes(scene) {
  2937. var frameState = scene._frameState;
  2938. if (scene.debugShowFrustumPlanes !== scene._debugShowFrustumPlanes) {
  2939. if (scene.debugShowFrustumPlanes) {
  2940. scene._debugFrustumPlanes = new DebugCameraPrimitive({
  2941. camera: scene.camera,
  2942. updateOnChange: false,
  2943. frustumSplits: frameState.frustumSplits,
  2944. });
  2945. } else {
  2946. scene._debugFrustumPlanes =
  2947. scene._debugFrustumPlanes && scene._debugFrustumPlanes.destroy();
  2948. }
  2949. scene._debugShowFrustumPlanes = scene.debugShowFrustumPlanes;
  2950. }
  2951. if (defined(scene._debugFrustumPlanes)) {
  2952. scene._debugFrustumPlanes.update(frameState);
  2953. }
  2954. }
  2955. function updateShadowMaps(scene) {
  2956. var frameState = scene._frameState;
  2957. var shadowMaps = frameState.shadowMaps;
  2958. var length = shadowMaps.length;
  2959. var shadowsEnabled =
  2960. length > 0 && !frameState.passes.pick && scene.mode === SceneMode.SCENE3D;
  2961. if (shadowsEnabled !== frameState.shadowState.shadowsEnabled) {
  2962. // Update derived commands when shadowsEnabled changes
  2963. ++frameState.shadowState.lastDirtyTime;
  2964. frameState.shadowState.shadowsEnabled = shadowsEnabled;
  2965. }
  2966. frameState.shadowState.lightShadowsEnabled = false;
  2967. if (!shadowsEnabled) {
  2968. return;
  2969. }
  2970. // Check if the shadow maps are different than the shadow maps last frame.
  2971. // If so, the derived commands need to be updated.
  2972. for (var j = 0; j < length; ++j) {
  2973. if (shadowMaps[j] !== frameState.shadowState.shadowMaps[j]) {
  2974. ++frameState.shadowState.lastDirtyTime;
  2975. break;
  2976. }
  2977. }
  2978. frameState.shadowState.shadowMaps.length = 0;
  2979. frameState.shadowState.lightShadowMaps.length = 0;
  2980. for (var i = 0; i < length; ++i) {
  2981. var shadowMap = shadowMaps[i];
  2982. shadowMap.update(frameState);
  2983. frameState.shadowState.shadowMaps.push(shadowMap);
  2984. if (shadowMap.fromLightSource) {
  2985. frameState.shadowState.lightShadowMaps.push(shadowMap);
  2986. frameState.shadowState.lightShadowsEnabled = true;
  2987. }
  2988. if (shadowMap.dirty) {
  2989. ++frameState.shadowState.lastDirtyTime;
  2990. shadowMap.dirty = false;
  2991. }
  2992. }
  2993. }
  2994. function updateAndRenderPrimitives(scene) {
  2995. var frameState = scene._frameState;
  2996. scene._groundPrimitives.update(frameState);
  2997. scene._primitives.update(frameState);
  2998. updateDebugFrustumPlanes(scene);
  2999. updateShadowMaps(scene);
  3000. if (scene._globe) {
  3001. scene._globe.render(frameState);
  3002. }
  3003. }
  3004. function updateAndClearFramebuffers(scene, passState, clearColor) {
  3005. var context = scene._context;
  3006. var frameState = scene._frameState;
  3007. var environmentState = scene._environmentState;
  3008. var view = scene._view;
  3009. var passes = scene._frameState.passes;
  3010. var picking = passes.pick;
  3011. var useWebVR = environmentState.useWebVR;
  3012. // Preserve the reference to the original framebuffer.
  3013. environmentState.originalFramebuffer = passState.framebuffer;
  3014. // Manage sun bloom post-processing effect.
  3015. if (defined(scene.sun) && scene.sunBloom !== scene._sunBloom) {
  3016. if (scene.sunBloom && !useWebVR) {
  3017. scene._sunPostProcess = new SunPostProcess();
  3018. } else if (defined(scene._sunPostProcess)) {
  3019. scene._sunPostProcess = scene._sunPostProcess.destroy();
  3020. }
  3021. scene._sunBloom = scene.sunBloom;
  3022. } else if (!defined(scene.sun) && defined(scene._sunPostProcess)) {
  3023. scene._sunPostProcess = scene._sunPostProcess.destroy();
  3024. scene._sunBloom = false;
  3025. }
  3026. // Clear the pass state framebuffer.
  3027. var clear = scene._clearColorCommand;
  3028. Color.clone(clearColor, clear.color);
  3029. clear.execute(context, passState);
  3030. // Update globe depth rendering based on the current context and clear the globe depth framebuffer.
  3031. // Globe depth is copied for the pick pass to support picking batched geometries in GroundPrimitives.
  3032. var useGlobeDepthFramebuffer = (environmentState.useGlobeDepthFramebuffer = defined(
  3033. view.globeDepth
  3034. ));
  3035. if (useGlobeDepthFramebuffer) {
  3036. view.globeDepth.update(
  3037. context,
  3038. passState,
  3039. view.viewport,
  3040. scene._hdr,
  3041. environmentState.clearGlobeDepth
  3042. );
  3043. view.globeDepth.clear(context, passState, clearColor);
  3044. }
  3045. // If supported, configure OIT to use the globe depth framebuffer and clear the OIT framebuffer.
  3046. var oit = view.oit;
  3047. var useOIT = (environmentState.useOIT =
  3048. !picking && defined(oit) && oit.isSupported());
  3049. if (useOIT) {
  3050. oit.update(context, passState, view.globeDepth.framebuffer, scene._hdr);
  3051. oit.clear(context, passState, clearColor);
  3052. environmentState.useOIT = oit.isSupported();
  3053. }
  3054. var postProcess = scene.postProcessStages;
  3055. var usePostProcess = (environmentState.usePostProcess =
  3056. !picking &&
  3057. (scene._hdr ||
  3058. postProcess.length > 0 ||
  3059. postProcess.ambientOcclusion.enabled ||
  3060. postProcess.fxaa.enabled ||
  3061. postProcess.bloom.enabled));
  3062. environmentState.usePostProcessSelected = false;
  3063. if (usePostProcess) {
  3064. view.sceneFramebuffer.update(context, view.viewport, scene._hdr);
  3065. view.sceneFramebuffer.clear(context, passState, clearColor);
  3066. postProcess.update(context, frameState.useLogDepth, scene._hdr);
  3067. postProcess.clear(context);
  3068. usePostProcess = environmentState.usePostProcess = postProcess.ready;
  3069. environmentState.usePostProcessSelected =
  3070. usePostProcess && postProcess.hasSelected;
  3071. }
  3072. if (environmentState.isSunVisible && scene.sunBloom && !useWebVR) {
  3073. passState.framebuffer = scene._sunPostProcess.update(passState);
  3074. scene._sunPostProcess.clear(context, passState, clearColor);
  3075. } else if (useGlobeDepthFramebuffer) {
  3076. passState.framebuffer = view.globeDepth.framebuffer;
  3077. } else if (usePostProcess) {
  3078. passState.framebuffer = view.sceneFramebuffer.getFramebuffer();
  3079. }
  3080. if (defined(passState.framebuffer)) {
  3081. clear.execute(context, passState);
  3082. }
  3083. var useInvertClassification = (environmentState.useInvertClassification =
  3084. !picking && defined(passState.framebuffer) && scene.invertClassification);
  3085. if (useInvertClassification) {
  3086. var depthFramebuffer;
  3087. if (scene.frameState.invertClassificationColor.alpha === 1.0) {
  3088. if (environmentState.useGlobeDepthFramebuffer) {
  3089. depthFramebuffer = view.globeDepth.framebuffer;
  3090. }
  3091. }
  3092. if (defined(depthFramebuffer) || context.depthTexture) {
  3093. scene._invertClassification.previousFramebuffer = depthFramebuffer;
  3094. scene._invertClassification.update(context);
  3095. scene._invertClassification.clear(context, passState);
  3096. if (scene.frameState.invertClassificationColor.alpha < 1.0 && useOIT) {
  3097. var command = scene._invertClassification.unclassifiedCommand;
  3098. var derivedCommands = command.derivedCommands;
  3099. derivedCommands.oit = oit.createDerivedCommands(
  3100. command,
  3101. context,
  3102. derivedCommands.oit
  3103. );
  3104. }
  3105. } else {
  3106. environmentState.useInvertClassification = false;
  3107. }
  3108. }
  3109. if (scene._globeTranslucencyState.translucent) {
  3110. view.globeTranslucencyFramebuffer.updateAndClear(
  3111. scene._hdr,
  3112. view.viewport,
  3113. context,
  3114. passState
  3115. );
  3116. }
  3117. }
  3118. /**
  3119. * @private
  3120. */
  3121. Scene.prototype.resolveFramebuffers = function (passState) {
  3122. var context = this._context;
  3123. var frameState = this._frameState;
  3124. var environmentState = this._environmentState;
  3125. var view = this._view;
  3126. var globeDepth = view.globeDepth;
  3127. var useOIT = environmentState.useOIT;
  3128. var useGlobeDepthFramebuffer = environmentState.useGlobeDepthFramebuffer;
  3129. var usePostProcess = environmentState.usePostProcess;
  3130. var defaultFramebuffer = environmentState.originalFramebuffer;
  3131. var globeFramebuffer = useGlobeDepthFramebuffer
  3132. ? globeDepth.framebuffer
  3133. : undefined;
  3134. var sceneFramebuffer = view.sceneFramebuffer.getFramebuffer();
  3135. var idFramebuffer = view.sceneFramebuffer.getIdFramebuffer();
  3136. if (environmentState.separatePrimitiveFramebuffer) {
  3137. // Merge primitive framebuffer into globe framebuffer
  3138. globeDepth.executeMergeColor(context, passState);
  3139. }
  3140. if (useOIT) {
  3141. passState.framebuffer = usePostProcess
  3142. ? sceneFramebuffer
  3143. : defaultFramebuffer;
  3144. view.oit.execute(context, passState);
  3145. }
  3146. if (usePostProcess) {
  3147. var inputFramebuffer = sceneFramebuffer;
  3148. if (useGlobeDepthFramebuffer && !useOIT) {
  3149. inputFramebuffer = globeFramebuffer;
  3150. }
  3151. var postProcess = this.postProcessStages;
  3152. var colorTexture = inputFramebuffer.getColorTexture(0);
  3153. var idTexture = idFramebuffer.getColorTexture(0);
  3154. var depthTexture = defaultValue(globeFramebuffer, sceneFramebuffer)
  3155. .depthStencilTexture;
  3156. postProcess.execute(context, colorTexture, depthTexture, idTexture);
  3157. postProcess.copy(context, defaultFramebuffer);
  3158. }
  3159. if (!useOIT && !usePostProcess && useGlobeDepthFramebuffer) {
  3160. passState.framebuffer = defaultFramebuffer;
  3161. globeDepth.executeCopyColor(context, passState);
  3162. }
  3163. var useLogDepth = frameState.useLogDepth;
  3164. if (this.debugShowGlobeDepth && useGlobeDepthFramebuffer) {
  3165. var gd = getDebugGlobeDepth(this, this.debugShowDepthFrustum - 1);
  3166. gd.executeDebugGlobeDepth(context, passState, useLogDepth);
  3167. }
  3168. if (this.debugShowPickDepth && useGlobeDepthFramebuffer) {
  3169. var pd = this._picking.getPickDepth(this, this.debugShowDepthFrustum - 1);
  3170. pd.executeDebugPickDepth(context, passState, useLogDepth);
  3171. }
  3172. };
  3173. function callAfterRenderFunctions(scene) {
  3174. // Functions are queued up during primitive update and executed here in case
  3175. // the function modifies scene state that should remain constant over the frame.
  3176. var functions = scene._frameState.afterRender;
  3177. for (var i = 0, length = functions.length; i < length; ++i) {
  3178. functions[i]();
  3179. scene.requestRender();
  3180. }
  3181. functions.length = 0;
  3182. }
  3183. function getGlobeHeight(scene) {
  3184. var globe = scene._globe;
  3185. var camera = scene.camera;
  3186. var cartographic = camera.positionCartographic;
  3187. if (defined(globe) && globe.show && defined(cartographic)) {
  3188. return globe.getHeight(cartographic);
  3189. }
  3190. return undefined;
  3191. }
  3192. function isCameraUnderground(scene) {
  3193. var camera = scene.camera;
  3194. var mode = scene._mode;
  3195. var globe = scene.globe;
  3196. var cameraController = scene._screenSpaceCameraController;
  3197. var cartographic = camera.positionCartographic;
  3198. if (!defined(cartographic)) {
  3199. return false;
  3200. }
  3201. if (!cameraController.onMap() && cartographic.height < 0.0) {
  3202. // The camera can go off the map while in Columbus View.
  3203. // Make a best guess as to whether it's underground by checking if its height is less than zero.
  3204. return true;
  3205. }
  3206. if (
  3207. !defined(globe) ||
  3208. !globe.show ||
  3209. mode === SceneMode.SCENE2D ||
  3210. mode === SceneMode.MORPHING
  3211. ) {
  3212. return false;
  3213. }
  3214. var globeHeight = scene._globeHeight;
  3215. return defined(globeHeight) && cartographic.height < globeHeight;
  3216. }
  3217. /**
  3218. * @private
  3219. */
  3220. Scene.prototype.initializeFrame = function () {
  3221. // Destroy released shaders and textures once every 120 frames to avoid thrashing the cache
  3222. if (this._shaderFrameCount++ === 120) {
  3223. this._shaderFrameCount = 0;
  3224. this._context.shaderCache.destroyReleasedShaderPrograms();
  3225. this._context.textureCache.destroyReleasedTextures();
  3226. }
  3227. this._tweens.update();
  3228. this._globeHeight = getGlobeHeight(this);
  3229. this._cameraUnderground = isCameraUnderground(this);
  3230. this._globeTranslucencyState.update(this);
  3231. this._screenSpaceCameraController.update();
  3232. if (defined(this._deviceOrientationCameraController)) {
  3233. this._deviceOrientationCameraController.update();
  3234. }
  3235. this.camera.update(this._mode);
  3236. this.camera._updateCameraChanged();
  3237. };
  3238. function updateDebugShowFramesPerSecond(scene, renderedThisFrame) {
  3239. if (scene.debugShowFramesPerSecond) {
  3240. if (!defined(scene._performanceDisplay)) {
  3241. var performanceContainer = document.createElement("div");
  3242. performanceContainer.className =
  3243. "cesium-performanceDisplay-defaultContainer";
  3244. var container = scene._canvas.parentNode;
  3245. container.appendChild(performanceContainer);
  3246. var performanceDisplay = new PerformanceDisplay({
  3247. container: performanceContainer,
  3248. });
  3249. scene._performanceDisplay = performanceDisplay;
  3250. scene._performanceContainer = performanceContainer;
  3251. }
  3252. scene._performanceDisplay.throttled = scene.requestRenderMode;
  3253. scene._performanceDisplay.update(renderedThisFrame);
  3254. } else if (defined(scene._performanceDisplay)) {
  3255. scene._performanceDisplay =
  3256. scene._performanceDisplay && scene._performanceDisplay.destroy();
  3257. scene._performanceContainer.parentNode.removeChild(
  3258. scene._performanceContainer
  3259. );
  3260. }
  3261. }
  3262. function prePassesUpdate(scene) {
  3263. scene._jobScheduler.resetBudgets();
  3264. var frameState = scene._frameState;
  3265. var primitives = scene.primitives;
  3266. primitives.prePassesUpdate(frameState);
  3267. if (defined(scene.globe)) {
  3268. scene.globe.update(frameState);
  3269. }
  3270. scene._picking.update();
  3271. frameState.creditDisplay.update();
  3272. }
  3273. function postPassesUpdate(scene) {
  3274. var frameState = scene._frameState;
  3275. var primitives = scene.primitives;
  3276. primitives.postPassesUpdate(frameState);
  3277. RequestScheduler.update();
  3278. }
  3279. var scratchBackgroundColor = new Color();
  3280. function render(scene) {
  3281. var frameState = scene._frameState;
  3282. var context = scene.context;
  3283. var us = context.uniformState;
  3284. var view = scene._defaultView;
  3285. scene._view = view;
  3286. scene.updateFrameState();
  3287. frameState.passes.render = true;
  3288. frameState.passes.postProcess = scene.postProcessStages.hasSelected;
  3289. frameState.tilesetPassState = renderTilesetPassState;
  3290. var backgroundColor = defaultValue(scene.backgroundColor, Color.BLACK);
  3291. if (scene._hdr) {
  3292. backgroundColor = Color.clone(backgroundColor, scratchBackgroundColor);
  3293. backgroundColor.red = Math.pow(backgroundColor.red, scene.gamma);
  3294. backgroundColor.green = Math.pow(backgroundColor.green, scene.gamma);
  3295. backgroundColor.blue = Math.pow(backgroundColor.blue, scene.gamma);
  3296. }
  3297. frameState.backgroundColor = backgroundColor;
  3298. scene.fog.update(frameState);
  3299. us.update(frameState);
  3300. var shadowMap = scene.shadowMap;
  3301. if (defined(shadowMap) && shadowMap.enabled) {
  3302. if (!defined(scene.light) || scene.light instanceof SunLight) {
  3303. // Negate the sun direction so that it is from the Sun, not to the Sun
  3304. Cartesian3.negate(us.sunDirectionWC, scene._shadowMapCamera.direction);
  3305. } else {
  3306. Cartesian3.clone(scene.light.direction, scene._shadowMapCamera.direction);
  3307. }
  3308. frameState.shadowMaps.push(shadowMap);
  3309. }
  3310. scene._computeCommandList.length = 0;
  3311. scene._overlayCommandList.length = 0;
  3312. var viewport = view.viewport;
  3313. viewport.x = 0;
  3314. viewport.y = 0;
  3315. viewport.width = context.drawingBufferWidth;
  3316. viewport.height = context.drawingBufferHeight;
  3317. var passState = view.passState;
  3318. passState.framebuffer = undefined;
  3319. passState.blendingEnabled = undefined;
  3320. passState.scissorTest = undefined;
  3321. passState.viewport = BoundingRectangle.clone(viewport, passState.viewport);
  3322. if (defined(scene.globe)) {
  3323. scene.globe.beginFrame(frameState);
  3324. }
  3325. scene.updateEnvironment();
  3326. scene.updateAndExecuteCommands(passState, backgroundColor);
  3327. scene.resolveFramebuffers(passState);
  3328. passState.framebuffer = undefined;
  3329. executeOverlayCommands(scene, passState);
  3330. if (defined(scene.globe)) {
  3331. scene.globe.endFrame(frameState);
  3332. if (!scene.globe.tilesLoaded) {
  3333. scene._renderRequested = true;
  3334. }
  3335. }
  3336. context.endFrame();
  3337. }
  3338. function tryAndCatchError(scene, functionToExecute) {
  3339. try {
  3340. functionToExecute(scene);
  3341. } catch (error) {
  3342. scene._renderError.raiseEvent(scene, error);
  3343. if (scene.rethrowRenderErrors) {
  3344. throw error;
  3345. }
  3346. }
  3347. }
  3348. function updateMostDetailedRayPicks(scene) {
  3349. return scene._picking.updateMostDetailedRayPicks(scene);
  3350. }
  3351. /**
  3352. * Update and render the scene. It is usually not necessary to call this function
  3353. * directly because {@link CesiumWidget} or {@link Viewer} do it automatically.
  3354. * @param {JulianDate} [time] The simulation time at which to render.
  3355. */
  3356. Scene.prototype.render = function (time) {
  3357. /**
  3358. *
  3359. * Pre passes update. Execute any pass invariant code that should run before the passes here.
  3360. *
  3361. */
  3362. this._preUpdate.raiseEvent(this, time);
  3363. var frameState = this._frameState;
  3364. frameState.newFrame = false;
  3365. if (!defined(time)) {
  3366. time = JulianDate.now();
  3367. }
  3368. // Determine if shouldRender
  3369. var cameraChanged = this._view.checkForCameraUpdates(this);
  3370. var shouldRender =
  3371. !this.requestRenderMode ||
  3372. this._renderRequested ||
  3373. cameraChanged ||
  3374. this._logDepthBufferDirty ||
  3375. this._hdrDirty ||
  3376. this.mode === SceneMode.MORPHING;
  3377. if (
  3378. !shouldRender &&
  3379. defined(this.maximumRenderTimeChange) &&
  3380. defined(this._lastRenderTime)
  3381. ) {
  3382. var difference = Math.abs(
  3383. JulianDate.secondsDifference(this._lastRenderTime, time)
  3384. );
  3385. shouldRender = shouldRender || difference > this.maximumRenderTimeChange;
  3386. }
  3387. if (shouldRender) {
  3388. this._lastRenderTime = JulianDate.clone(time, this._lastRenderTime);
  3389. this._renderRequested = false;
  3390. this._logDepthBufferDirty = false;
  3391. this._hdrDirty = false;
  3392. var frameNumber = CesiumMath.incrementWrap(
  3393. frameState.frameNumber,
  3394. 15000000.0,
  3395. 1.0
  3396. );
  3397. updateFrameNumber(this, frameNumber, time);
  3398. frameState.newFrame = true;
  3399. }
  3400. tryAndCatchError(this, prePassesUpdate);
  3401. /**
  3402. *
  3403. * Passes update. Add any passes here
  3404. *
  3405. */
  3406. if (this.primitives.show) {
  3407. tryAndCatchError(this, updateMostDetailedRayPicks);
  3408. tryAndCatchError(this, updatePreloadPass);
  3409. tryAndCatchError(this, updatePreloadFlightPass);
  3410. if (!shouldRender) {
  3411. tryAndCatchError(this, updateRequestRenderModeDeferCheckPass);
  3412. }
  3413. }
  3414. this._postUpdate.raiseEvent(this, time);
  3415. if (shouldRender) {
  3416. this._preRender.raiseEvent(this, time);
  3417. frameState.creditDisplay.beginFrame();
  3418. tryAndCatchError(this, render);
  3419. }
  3420. /**
  3421. *
  3422. * Post passes update. Execute any pass invariant code that should run after the passes here.
  3423. *
  3424. */
  3425. updateDebugShowFramesPerSecond(this, shouldRender);
  3426. tryAndCatchError(this, postPassesUpdate);
  3427. // Often used to trigger events (so don't want in trycatch) that the user might be subscribed to. Things like the tile load events, ready promises, etc.
  3428. // We don't want those events to resolve during the render loop because the events might add new primitives
  3429. callAfterRenderFunctions(this);
  3430. if (shouldRender) {
  3431. this._postRender.raiseEvent(this, time);
  3432. frameState.creditDisplay.endFrame();
  3433. }
  3434. };
  3435. /**
  3436. * Update and render the scene. Always forces a new render frame regardless of whether a render was
  3437. * previously requested.
  3438. * @param {JulianDate} [time] The simulation time at which to render.
  3439. *
  3440. * @private
  3441. */
  3442. Scene.prototype.forceRender = function (time) {
  3443. this._renderRequested = true;
  3444. this.render(time);
  3445. };
  3446. /**
  3447. * Requests a new rendered frame when {@link Scene#requestRenderMode} is set to <code>true</code>.
  3448. * The render rate will not exceed the {@link CesiumWidget#targetFrameRate}.
  3449. *
  3450. * @see Scene#requestRenderMode
  3451. */
  3452. Scene.prototype.requestRender = function () {
  3453. this._renderRequested = true;
  3454. };
  3455. /**
  3456. * @private
  3457. */
  3458. Scene.prototype.clampLineWidth = function (width) {
  3459. return Math.max(
  3460. ContextLimits.minimumAliasedLineWidth,
  3461. Math.min(width, ContextLimits.maximumAliasedLineWidth)
  3462. );
  3463. };
  3464. /**
  3465. * Returns an object with a `primitive` property that contains the first (top) primitive in the scene
  3466. * at a particular window coordinate or undefined if nothing is at the location. Other properties may
  3467. * potentially be set depending on the type of primitive and may be used to further identify the picked object.
  3468. * <p>
  3469. * When a feature of a 3D Tiles tileset is picked, <code>pick</code> returns a {@link Cesium3DTileFeature} object.
  3470. * </p>
  3471. *
  3472. * @example
  3473. * // On mouse over, color the feature yellow.
  3474. * handler.setInputAction(function(movement) {
  3475. * var feature = scene.pick(movement.endPosition);
  3476. * if (feature instanceof Cesium.Cesium3DTileFeature) {
  3477. * feature.color = Cesium.Color.YELLOW;
  3478. * }
  3479. * }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  3480. *
  3481. * @param {Cartesian2} windowPosition Window coordinates to perform picking on.
  3482. * @param {Number} [width=3] Width of the pick rectangle.
  3483. * @param {Number} [height=3] Height of the pick rectangle.
  3484. * @returns {Object} Object containing the picked primitive.
  3485. */
  3486. Scene.prototype.pick = function (windowPosition, width, height) {
  3487. return this._picking.pick(this, windowPosition, width, height);
  3488. };
  3489. /**
  3490. * Returns the cartesian position reconstructed from the depth buffer and window position.
  3491. * The returned position is in world coordinates. Used internally by camera functions to
  3492. * prevent conversion to projected 2D coordinates and then back.
  3493. * <p>
  3494. * Set {@link Scene#pickTranslucentDepth} to <code>true</code> to include the depth of
  3495. * translucent primitives; otherwise, this essentially picks through translucent primitives.
  3496. * </p>
  3497. *
  3498. * @private
  3499. *
  3500. * @param {Cartesian2} windowPosition Window coordinates to perform picking on.
  3501. * @param {Cartesian3} [result] The object on which to restore the result.
  3502. * @returns {Cartesian3} The cartesian position in world coordinates.
  3503. *
  3504. * @exception {DeveloperError} Picking from the depth buffer is not supported. Check pickPositionSupported.
  3505. */
  3506. Scene.prototype.pickPositionWorldCoordinates = function (
  3507. windowPosition,
  3508. result
  3509. ) {
  3510. return this._picking.pickPositionWorldCoordinates(
  3511. this,
  3512. windowPosition,
  3513. result
  3514. );
  3515. };
  3516. /**
  3517. * Returns the cartesian position reconstructed from the depth buffer and window position.
  3518. * <p>
  3519. * The position reconstructed from the depth buffer in 2D may be slightly different from those
  3520. * reconstructed in 3D and Columbus view. This is caused by the difference in the distribution
  3521. * of depth values of perspective and orthographic projection.
  3522. * </p>
  3523. * <p>
  3524. * Set {@link Scene#pickTranslucentDepth} to <code>true</code> to include the depth of
  3525. * translucent primitives; otherwise, this essentially picks through translucent primitives.
  3526. * </p>
  3527. *
  3528. * @param {Cartesian2} windowPosition Window coordinates to perform picking on.
  3529. * @param {Cartesian3} [result] The object on which to restore the result.
  3530. * @returns {Cartesian3} The cartesian position.
  3531. *
  3532. * @exception {DeveloperError} Picking from the depth buffer is not supported. Check pickPositionSupported.
  3533. */
  3534. Scene.prototype.pickPosition = function (windowPosition, result) {
  3535. return this._picking.pickPosition(this, windowPosition, result);
  3536. };
  3537. /**
  3538. * Returns a list of objects, each containing a `primitive` property, for all primitives at
  3539. * a particular window coordinate position. Other properties may also be set depending on the
  3540. * type of primitive and may be used to further identify the picked object. The primitives in
  3541. * the list are ordered by their visual order in the scene (front to back).
  3542. *
  3543. * @param {Cartesian2} windowPosition Window coordinates to perform picking on.
  3544. * @param {Number} [limit] If supplied, stop drilling after collecting this many picks.
  3545. * @param {Number} [width=3] Width of the pick rectangle.
  3546. * @param {Number} [height=3] Height of the pick rectangle.
  3547. * @returns {Array.<*>} Array of objects, each containing 1 picked primitives.
  3548. *
  3549. * @exception {DeveloperError} windowPosition is undefined.
  3550. *
  3551. * @example
  3552. * var pickedObjects = scene.drillPick(new Cesium.Cartesian2(100.0, 200.0));
  3553. *
  3554. * @see Scene#pick
  3555. */
  3556. Scene.prototype.drillPick = function (windowPosition, limit, width, height) {
  3557. return this._picking.drillPick(this, windowPosition, limit, width, height);
  3558. };
  3559. function updatePreloadPass(scene) {
  3560. var frameState = scene._frameState;
  3561. preloadTilesetPassState.camera = frameState.camera;
  3562. preloadTilesetPassState.cullingVolume = frameState.cullingVolume;
  3563. var primitives = scene.primitives;
  3564. primitives.updateForPass(frameState, preloadTilesetPassState);
  3565. }
  3566. function updatePreloadFlightPass(scene) {
  3567. var frameState = scene._frameState;
  3568. var camera = frameState.camera;
  3569. if (!camera.canPreloadFlight()) {
  3570. return;
  3571. }
  3572. preloadFlightTilesetPassState.camera = scene.preloadFlightCamera;
  3573. preloadFlightTilesetPassState.cullingVolume =
  3574. scene.preloadFlightCullingVolume;
  3575. var primitives = scene.primitives;
  3576. primitives.updateForPass(frameState, preloadFlightTilesetPassState);
  3577. }
  3578. function updateRequestRenderModeDeferCheckPass(scene) {
  3579. // Check if any ignored requests are ready to go (to wake rendering up again)
  3580. scene.primitives.updateForPass(
  3581. scene._frameState,
  3582. requestRenderModeDeferCheckPassState
  3583. );
  3584. }
  3585. /**
  3586. * Returns an object containing the first object intersected by the ray and the position of intersection,
  3587. * or <code>undefined</code> if there were no intersections. The intersected object has a <code>primitive</code>
  3588. * property that contains the intersected primitive. Other properties may be set depending on the type of primitive
  3589. * and may be used to further identify the picked object. The ray must be given in world coordinates.
  3590. * <p>
  3591. * This function only picks globe tiles and 3D Tiles that are rendered in the current view. Picks all other
  3592. * primitives regardless of their visibility.
  3593. * </p>
  3594. *
  3595. * @private
  3596. *
  3597. * @param {Ray} ray The ray.
  3598. * @param {Object[]} [objectsToExclude] A list of primitives, entities, or 3D Tiles features to exclude from the ray intersection.
  3599. * @param {Number} [width=0.1] Width of the intersection volume in meters.
  3600. * @returns {Object} An object containing the object and position of the first intersection.
  3601. *
  3602. * @exception {DeveloperError} Ray intersections are only supported in 3D mode.
  3603. */
  3604. Scene.prototype.pickFromRay = function (ray, objectsToExclude, width) {
  3605. return this._picking.pickFromRay(this, ray, objectsToExclude, width);
  3606. };
  3607. /**
  3608. * Returns a list of objects, each containing the object intersected by the ray and the position of intersection.
  3609. * The intersected object has a <code>primitive</code> property that contains the intersected primitive. Other
  3610. * properties may also be set depending on the type of primitive and may be used to further identify the picked object.
  3611. * The primitives in the list are ordered by first intersection to last intersection. The ray must be given in
  3612. * world coordinates.
  3613. * <p>
  3614. * This function only picks globe tiles and 3D Tiles that are rendered in the current view. Picks all other
  3615. * primitives regardless of their visibility.
  3616. * </p>
  3617. *
  3618. * @private
  3619. *
  3620. * @param {Ray} ray The ray.
  3621. * @param {Number} [limit=Number.MAX_VALUE] If supplied, stop finding intersections after this many intersections.
  3622. * @param {Object[]} [objectsToExclude] A list of primitives, entities, or 3D Tiles features to exclude from the ray intersection.
  3623. * @param {Number} [width=0.1] Width of the intersection volume in meters.
  3624. * @returns {Object[]} List of objects containing the object and position of each intersection.
  3625. *
  3626. * @exception {DeveloperError} Ray intersections are only supported in 3D mode.
  3627. */
  3628. Scene.prototype.drillPickFromRay = function (
  3629. ray,
  3630. limit,
  3631. objectsToExclude,
  3632. width
  3633. ) {
  3634. return this._picking.drillPickFromRay(
  3635. this,
  3636. ray,
  3637. limit,
  3638. objectsToExclude,
  3639. width
  3640. );
  3641. };
  3642. /**
  3643. * Initiates an asynchronous {@link Scene#pickFromRay} request using the maximum level of detail for 3D Tilesets
  3644. * regardless of visibility.
  3645. *
  3646. * @private
  3647. *
  3648. * @param {Ray} ray The ray.
  3649. * @param {Object[]} [objectsToExclude] A list of primitives, entities, or 3D Tiles features to exclude from the ray intersection.
  3650. * @param {Number} [width=0.1] Width of the intersection volume in meters.
  3651. * @returns {Promise.<Object>} A promise that resolves to an object containing the object and position of the first intersection.
  3652. *
  3653. * @exception {DeveloperError} Ray intersections are only supported in 3D mode.
  3654. */
  3655. Scene.prototype.pickFromRayMostDetailed = function (
  3656. ray,
  3657. objectsToExclude,
  3658. width
  3659. ) {
  3660. return this._picking.pickFromRayMostDetailed(
  3661. this,
  3662. ray,
  3663. objectsToExclude,
  3664. width
  3665. );
  3666. };
  3667. /**
  3668. * Initiates an asynchronous {@link Scene#drillPickFromRay} request using the maximum level of detail for 3D Tilesets
  3669. * regardless of visibility.
  3670. *
  3671. * @private
  3672. *
  3673. * @param {Ray} ray The ray.
  3674. * @param {Number} [limit=Number.MAX_VALUE] If supplied, stop finding intersections after this many intersections.
  3675. * @param {Object[]} [objectsToExclude] A list of primitives, entities, or 3D Tiles features to exclude from the ray intersection.
  3676. * @param {Number} [width=0.1] Width of the intersection volume in meters.
  3677. * @returns {Promise.<Object[]>} A promise that resolves to a list of objects containing the object and position of each intersection.
  3678. *
  3679. * @exception {DeveloperError} Ray intersections are only supported in 3D mode.
  3680. */
  3681. Scene.prototype.drillPickFromRayMostDetailed = function (
  3682. ray,
  3683. limit,
  3684. objectsToExclude,
  3685. width
  3686. ) {
  3687. return this._picking.drillPickFromRayMostDetailed(
  3688. this,
  3689. ray,
  3690. limit,
  3691. objectsToExclude,
  3692. width
  3693. );
  3694. };
  3695. /**
  3696. * Returns the height of scene geometry at the given cartographic position or <code>undefined</code> if there was no
  3697. * scene geometry to sample height from. The height of the input position is ignored. May be used to clamp objects to
  3698. * the globe, 3D Tiles, or primitives in the scene.
  3699. * <p>
  3700. * This function only samples height from globe tiles and 3D Tiles that are rendered in the current view. Samples height
  3701. * from all other primitives regardless of their visibility.
  3702. * </p>
  3703. *
  3704. * @param {Cartographic} position The cartographic position to sample height from.
  3705. * @param {Object[]} [objectsToExclude] A list of primitives, entities, or 3D Tiles features to not sample height from.
  3706. * @param {Number} [width=0.1] Width of the intersection volume in meters.
  3707. * @returns {Number} The height. This may be <code>undefined</code> if there was no scene geometry to sample height from.
  3708. *
  3709. * @example
  3710. * var position = new Cesium.Cartographic(-1.31968, 0.698874);
  3711. * var height = viewer.scene.sampleHeight(position);
  3712. * console.log(height);
  3713. *
  3714. * @see Scene#clampToHeight
  3715. * @see Scene#clampToHeightMostDetailed
  3716. * @see Scene#sampleHeightMostDetailed
  3717. *
  3718. * @exception {DeveloperError} sampleHeight is only supported in 3D mode.
  3719. * @exception {DeveloperError} sampleHeight requires depth texture support. Check sampleHeightSupported.
  3720. */
  3721. Scene.prototype.sampleHeight = function (position, objectsToExclude, width) {
  3722. return this._picking.sampleHeight(this, position, objectsToExclude, width);
  3723. };
  3724. /**
  3725. * Clamps the given cartesian position to the scene geometry along the geodetic surface normal. Returns the
  3726. * clamped position or <code>undefined</code> if there was no scene geometry to clamp to. May be used to clamp
  3727. * objects to the globe, 3D Tiles, or primitives in the scene.
  3728. * <p>
  3729. * This function only clamps to globe tiles and 3D Tiles that are rendered in the current view. Clamps to
  3730. * all other primitives regardless of their visibility.
  3731. * </p>
  3732. *
  3733. * @param {Cartesian3} cartesian The cartesian position.
  3734. * @param {Object[]} [objectsToExclude] A list of primitives, entities, or 3D Tiles features to not clamp to.
  3735. * @param {Number} [width=0.1] Width of the intersection volume in meters.
  3736. * @param {Cartesian3} [result] An optional object to return the clamped position.
  3737. * @returns {Cartesian3} The modified result parameter or a new Cartesian3 instance if one was not provided. This may be <code>undefined</code> if there was no scene geometry to clamp to.
  3738. *
  3739. * @example
  3740. * // Clamp an entity to the underlying scene geometry
  3741. * var position = entity.position.getValue(Cesium.JulianDate.now());
  3742. * entity.position = viewer.scene.clampToHeight(position);
  3743. *
  3744. * @see Scene#sampleHeight
  3745. * @see Scene#sampleHeightMostDetailed
  3746. * @see Scene#clampToHeightMostDetailed
  3747. *
  3748. * @exception {DeveloperError} clampToHeight is only supported in 3D mode.
  3749. * @exception {DeveloperError} clampToHeight requires depth texture support. Check clampToHeightSupported.
  3750. */
  3751. Scene.prototype.clampToHeight = function (
  3752. cartesian,
  3753. objectsToExclude,
  3754. width,
  3755. result
  3756. ) {
  3757. return this._picking.clampToHeight(
  3758. this,
  3759. cartesian,
  3760. objectsToExclude,
  3761. width,
  3762. result
  3763. );
  3764. };
  3765. /**
  3766. * Initiates an asynchronous {@link Scene#sampleHeight} query for an array of {@link Cartographic} positions
  3767. * using the maximum level of detail for 3D Tilesets in the scene. The height of the input positions is ignored.
  3768. * Returns a promise that is resolved when the query completes. Each point height is modified in place.
  3769. * If a height cannot be determined because no geometry can be sampled at that location, or another error occurs,
  3770. * the height is set to undefined.
  3771. *
  3772. * @param {Cartographic[]} positions The cartographic positions to update with sampled heights.
  3773. * @param {Object[]} [objectsToExclude] A list of primitives, entities, or 3D Tiles features to not sample height from.
  3774. * @param {Number} [width=0.1] Width of the intersection volume in meters.
  3775. * @returns {Promise.<Cartographic[]>} A promise that resolves to the provided list of positions when the query has completed.
  3776. *
  3777. * @example
  3778. * var positions = [
  3779. * new Cesium.Cartographic(-1.31968, 0.69887),
  3780. * new Cesium.Cartographic(-1.10489, 0.83923)
  3781. * ];
  3782. * var promise = viewer.scene.sampleHeightMostDetailed(positions);
  3783. * promise.then(function(updatedPosition) {
  3784. * // positions[0].height and positions[1].height have been updated.
  3785. * // updatedPositions is just a reference to positions.
  3786. * }
  3787. *
  3788. * @see Scene#sampleHeight
  3789. *
  3790. * @exception {DeveloperError} sampleHeightMostDetailed is only supported in 3D mode.
  3791. * @exception {DeveloperError} sampleHeightMostDetailed requires depth texture support. Check sampleHeightSupported.
  3792. */
  3793. Scene.prototype.sampleHeightMostDetailed = function (
  3794. positions,
  3795. objectsToExclude,
  3796. width
  3797. ) {
  3798. return this._picking.sampleHeightMostDetailed(
  3799. this,
  3800. positions,
  3801. objectsToExclude,
  3802. width
  3803. );
  3804. };
  3805. /**
  3806. * Initiates an asynchronous {@link Scene#clampToHeight} query for an array of {@link Cartesian3} positions
  3807. * using the maximum level of detail for 3D Tilesets in the scene. Returns a promise that is resolved when
  3808. * the query completes. Each position is modified in place. If a position cannot be clamped because no geometry
  3809. * can be sampled at that location, or another error occurs, the element in the array is set to undefined.
  3810. *
  3811. * @param {Cartesian3[]} cartesians The cartesian positions to update with clamped positions.
  3812. * @param {Object[]} [objectsToExclude] A list of primitives, entities, or 3D Tiles features to not clamp to.
  3813. * @param {Number} [width=0.1] Width of the intersection volume in meters.
  3814. * @returns {Promise.<Cartesian3[]>} A promise that resolves to the provided list of positions when the query has completed.
  3815. *
  3816. * @example
  3817. * var cartesians = [
  3818. * entities[0].position.getValue(Cesium.JulianDate.now()),
  3819. * entities[1].position.getValue(Cesium.JulianDate.now())
  3820. * ];
  3821. * var promise = viewer.scene.clampToHeightMostDetailed(cartesians);
  3822. * promise.then(function(updatedCartesians) {
  3823. * entities[0].position = updatedCartesians[0];
  3824. * entities[1].position = updatedCartesians[1];
  3825. * }
  3826. *
  3827. * @see Scene#clampToHeight
  3828. *
  3829. * @exception {DeveloperError} clampToHeightMostDetailed is only supported in 3D mode.
  3830. * @exception {DeveloperError} clampToHeightMostDetailed requires depth texture support. Check clampToHeightSupported.
  3831. */
  3832. Scene.prototype.clampToHeightMostDetailed = function (
  3833. cartesians,
  3834. objectsToExclude,
  3835. width
  3836. ) {
  3837. return this._picking.clampToHeightMostDetailed(
  3838. this,
  3839. cartesians,
  3840. objectsToExclude,
  3841. width
  3842. );
  3843. };
  3844. /**
  3845. * Transforms a position in cartesian coordinates to canvas coordinates. This is commonly used to place an
  3846. * HTML element at the same screen position as an object in the scene.
  3847. *
  3848. * @param {Cartesian3} position The position in cartesian coordinates.
  3849. * @param {Cartesian2} [result] An optional object to return the input position transformed to canvas coordinates.
  3850. * @returns {Cartesian2} The modified result parameter or a new Cartesian2 instance if one was not provided. This may be <code>undefined</code> if the input position is near the center of the ellipsoid.
  3851. *
  3852. * @example
  3853. * // Output the canvas position of longitude/latitude (0, 0) every time the mouse moves.
  3854. * var scene = widget.scene;
  3855. * var ellipsoid = scene.globe.ellipsoid;
  3856. * var position = Cesium.Cartesian3.fromDegrees(0.0, 0.0);
  3857. * var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
  3858. * handler.setInputAction(function(movement) {
  3859. * console.log(scene.cartesianToCanvasCoordinates(position));
  3860. * }, Cesium.ScreenSpaceEventType.MOUSE_MOVE);
  3861. */
  3862. Scene.prototype.cartesianToCanvasCoordinates = function (position, result) {
  3863. return SceneTransforms.wgs84ToWindowCoordinates(this, position, result);
  3864. };
  3865. /**
  3866. * Instantly completes an active transition.
  3867. */
  3868. Scene.prototype.completeMorph = function () {
  3869. this._transitioner.completeMorph();
  3870. };
  3871. /**
  3872. * Asynchronously transitions the scene to 2D.
  3873. * @param {Number} [duration=2.0] The amount of time, in seconds, for transition animations to complete.
  3874. */
  3875. Scene.prototype.morphTo2D = function (duration) {
  3876. var ellipsoid;
  3877. var globe = this.globe;
  3878. if (defined(globe)) {
  3879. ellipsoid = globe.ellipsoid;
  3880. } else {
  3881. ellipsoid = this.mapProjection.ellipsoid;
  3882. }
  3883. duration = defaultValue(duration, 2.0);
  3884. this._transitioner.morphTo2D(duration, ellipsoid);
  3885. };
  3886. /**
  3887. * Asynchronously transitions the scene to Columbus View.
  3888. * @param {Number} [duration=2.0] The amount of time, in seconds, for transition animations to complete.
  3889. */
  3890. Scene.prototype.morphToColumbusView = function (duration) {
  3891. var ellipsoid;
  3892. var globe = this.globe;
  3893. if (defined(globe)) {
  3894. ellipsoid = globe.ellipsoid;
  3895. } else {
  3896. ellipsoid = this.mapProjection.ellipsoid;
  3897. }
  3898. duration = defaultValue(duration, 2.0);
  3899. this._transitioner.morphToColumbusView(duration, ellipsoid);
  3900. };
  3901. /**
  3902. * Asynchronously transitions the scene to 3D.
  3903. * @param {Number} [duration=2.0] The amount of time, in seconds, for transition animations to complete.
  3904. */
  3905. Scene.prototype.morphTo3D = function (duration) {
  3906. var ellipsoid;
  3907. var globe = this.globe;
  3908. if (defined(globe)) {
  3909. ellipsoid = globe.ellipsoid;
  3910. } else {
  3911. ellipsoid = this.mapProjection.ellipsoid;
  3912. }
  3913. duration = defaultValue(duration, 2.0);
  3914. this._transitioner.morphTo3D(duration, ellipsoid);
  3915. };
  3916. /**
  3917. * Returns true if this object was destroyed; otherwise, false.
  3918. * <br /><br />
  3919. * If this object was destroyed, it should not be used; calling any function other than
  3920. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception.
  3921. *
  3922. * @returns {Boolean} <code>true</code> if this object was destroyed; otherwise, <code>false</code>.
  3923. *
  3924. * @see Scene#destroy
  3925. */
  3926. Scene.prototype.isDestroyed = function () {
  3927. return false;
  3928. };
  3929. /**
  3930. * Destroys the WebGL resources held by this object. Destroying an object allows for deterministic
  3931. * release of WebGL resources, instead of relying on the garbage collector to destroy this object.
  3932. * <br /><br />
  3933. * Once an object is destroyed, it should not be used; calling any function other than
  3934. * <code>isDestroyed</code> will result in a {@link DeveloperError} exception. Therefore,
  3935. * assign the return value (<code>undefined</code>) to the object as done in the example.
  3936. *
  3937. * @exception {DeveloperError} This object was destroyed, i.e., destroy() was called.
  3938. *
  3939. *
  3940. * @example
  3941. * scene = scene && scene.destroy();
  3942. *
  3943. * @see Scene#isDestroyed
  3944. */
  3945. Scene.prototype.destroy = function () {
  3946. this._tweens.removeAll();
  3947. this._computeEngine = this._computeEngine && this._computeEngine.destroy();
  3948. this._screenSpaceCameraController =
  3949. this._screenSpaceCameraController &&
  3950. this._screenSpaceCameraController.destroy();
  3951. this._deviceOrientationCameraController =
  3952. this._deviceOrientationCameraController &&
  3953. !this._deviceOrientationCameraController.isDestroyed() &&
  3954. this._deviceOrientationCameraController.destroy();
  3955. this._primitives = this._primitives && this._primitives.destroy();
  3956. this._groundPrimitives =
  3957. this._groundPrimitives && this._groundPrimitives.destroy();
  3958. this._globe = this._globe && this._globe.destroy();
  3959. this.skyBox = this.skyBox && this.skyBox.destroy();
  3960. this.skyAtmosphere = this.skyAtmosphere && this.skyAtmosphere.destroy();
  3961. this._debugSphere = this._debugSphere && this._debugSphere.destroy();
  3962. this.sun = this.sun && this.sun.destroy();
  3963. this._sunPostProcess = this._sunPostProcess && this._sunPostProcess.destroy();
  3964. this._depthPlane = this._depthPlane && this._depthPlane.destroy();
  3965. this._transitioner = this._transitioner && this._transitioner.destroy();
  3966. this._debugFrustumPlanes =
  3967. this._debugFrustumPlanes && this._debugFrustumPlanes.destroy();
  3968. this._brdfLutGenerator =
  3969. this._brdfLutGenerator && this._brdfLutGenerator.destroy();
  3970. this._picking = this._picking && this._picking.destroy();
  3971. this._defaultView = this._defaultView && this._defaultView.destroy();
  3972. this._view = undefined;
  3973. if (this._removeCreditContainer) {
  3974. this._canvas.parentNode.removeChild(this._creditContainer);
  3975. }
  3976. this.postProcessStages =
  3977. this.postProcessStages && this.postProcessStages.destroy();
  3978. this._context = this._context && this._context.destroy();
  3979. this._frameState.creditDisplay =
  3980. this._frameState.creditDisplay && this._frameState.creditDisplay.destroy();
  3981. if (defined(this._performanceDisplay)) {
  3982. this._performanceDisplay =
  3983. this._performanceDisplay && this._performanceDisplay.destroy();
  3984. this._performanceContainer.parentNode.removeChild(
  3985. this._performanceContainer
  3986. );
  3987. }
  3988. this._removeRequestListenerCallback();
  3989. this._removeTaskProcessorListenerCallback();
  3990. for (var i = 0; i < this._removeGlobeCallbacks.length; ++i) {
  3991. this._removeGlobeCallbacks[i]();
  3992. }
  3993. this._removeGlobeCallbacks.length = 0;
  3994. return destroyObject(this);
  3995. };
  3996. export default Scene;