f3f54528bfcd10077eb00a2121ed5d1424412e76.js 66 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504
  1. System.register(["__unresolved_0", "cc", "cc/env", "__unresolved_1"], function (_export, _context) {
  2. "use strict";
  3. var _reporterNs, _cclegacy, __checkObsolete__, __checkObsoleteInNamespace__, assert, cclegacy, clamp, geometry, gfx, Layers, Material, pipeline, PipelineEventType, renderer, rendering, sys, Vec2, Vec3, Vec4, warn, DEBUG, EDITOR, makePipelineSettings, PipelineConfigs, CameraConfigs, ForwardLighting, BuiltinForwardPassBuilder, BuiltinBloomPassBuilder, BuiltinToneMappingPassBuilder, BuiltinFXAAPassBuilder, BuiltinFsrPassBuilder, BuiltinUiPassBuilder, _crd, AABB, Sphere, intersect, ClearFlagBit, Color, Format, FormatFeatureBit, LoadOp, StoreOp, TextureType, Viewport, scene, CameraUsage, CSMLevel, LightType, defaultSettings, sClearColorTransparentBlack, QueueHint, SceneFlags;
  4. function forwardNeedClearColor(camera) {
  5. return !!(camera.clearFlag & (ClearFlagBit.COLOR | ClearFlagBit.STENCIL << 1));
  6. }
  7. function getCsmMainLightViewport(light, w, h, level, vp, screenSpaceSignY) {
  8. if (light.shadowFixedArea || light.csmLevel === CSMLevel.LEVEL_1) {
  9. vp.left = 0;
  10. vp.top = 0;
  11. vp.width = Math.trunc(w);
  12. vp.height = Math.trunc(h);
  13. } else {
  14. vp.left = Math.trunc(level % 2 * 0.5 * w);
  15. if (screenSpaceSignY > 0) {
  16. vp.top = Math.trunc((1 - Math.floor(level / 2)) * 0.5 * h);
  17. } else {
  18. vp.top = Math.trunc(Math.floor(level / 2) * 0.5 * h);
  19. }
  20. vp.width = Math.trunc(0.5 * w);
  21. vp.height = Math.trunc(0.5 * h);
  22. }
  23. vp.left = Math.max(0, vp.left);
  24. vp.top = Math.max(0, vp.top);
  25. vp.width = Math.max(1, vp.width);
  26. vp.height = Math.max(1, vp.height);
  27. }
  28. function setupPipelineConfigs(ppl, configs) {
  29. const sampleFeature = FormatFeatureBit.SAMPLED_TEXTURE | FormatFeatureBit.LINEAR_FILTER;
  30. const device = ppl.device; // Platform
  31. configs.isWeb = !sys.isNative;
  32. configs.isWebGL1 = device.gfxAPI === gfx.API.WEBGL;
  33. configs.isWebGPU = device.gfxAPI === gfx.API.WEBGPU;
  34. configs.isMobile = sys.isMobile; // Rendering
  35. configs.isHDR = ppl.pipelineSceneData.isHDR; // Has tone mapping
  36. configs.useFloatOutput = ppl.getMacroBool('CC_USE_FLOAT_OUTPUT');
  37. configs.toneMappingType = ppl.pipelineSceneData.postSettings.toneMappingType; // Shadow
  38. const shadowInfo = ppl.pipelineSceneData.shadows;
  39. configs.shadowEnabled = shadowInfo.enabled;
  40. configs.shadowMapFormat = pipeline.supportsR32FloatTexture(ppl.device) ? Format.R32F : Format.RGBA8;
  41. configs.shadowMapSize.set(shadowInfo.size);
  42. configs.usePlanarShadow = shadowInfo.enabled && shadowInfo.type === renderer.scene.ShadowType.Planar; // Device
  43. configs.screenSpaceSignY = ppl.device.capabilities.screenSpaceSignY;
  44. configs.supportDepthSample = (ppl.device.getFormatFeatures(Format.DEPTH_STENCIL) & sampleFeature) === sampleFeature; // Constants
  45. const screenSpaceSignY = device.capabilities.screenSpaceSignY;
  46. configs.platform.x = configs.isMobile ? 1.0 : 0.0;
  47. configs.platform.w = screenSpaceSignY * 0.5 + 0.5 << 1 | device.capabilities.clipSpaceSignY * 0.5 + 0.5;
  48. }
  49. function sortPipelinePassBuildersByConfigOrder(passBuilders) {
  50. passBuilders.sort((a, b) => {
  51. return a.getConfigOrder() - b.getConfigOrder();
  52. });
  53. }
  54. function sortPipelinePassBuildersByRenderOrder(passBuilders) {
  55. passBuilders.sort((a, b) => {
  56. return a.getRenderOrder() - b.getRenderOrder();
  57. });
  58. }
  59. function addCopyToScreenPass(ppl, pplConfigs, cameraConfigs, input) {
  60. assert(!!cameraConfigs.copyAndTonemapMaterial);
  61. const pass = ppl.addRenderPass(cameraConfigs.nativeWidth, cameraConfigs.nativeHeight, 'cc-tone-mapping');
  62. pass.addRenderTarget(cameraConfigs.colorName, LoadOp.CLEAR, StoreOp.STORE, sClearColorTransparentBlack);
  63. pass.addTexture(input, 'inputTexture');
  64. pass.setVec4('g_platform', pplConfigs.platform);
  65. pass.addQueue(rendering.QueueHint.OPAQUE).addFullscreenQuad(cameraConfigs.copyAndTonemapMaterial, 1);
  66. return pass;
  67. }
  68. function getPingPongRenderTarget(prevName, prefix, id) {
  69. if (prevName.startsWith(prefix)) {
  70. return `${prefix}${1 - Number(prevName.charAt(prefix.length))}_${id}`;
  71. } else {
  72. return `${prefix}0_${id}`;
  73. }
  74. }
  75. function _reportPossibleCrUseOfmakePipelineSettings(extras) {
  76. _reporterNs.report("makePipelineSettings", "./builtin-pipeline-types", _context.meta, extras);
  77. }
  78. function _reportPossibleCrUseOfPipelineSettings(extras) {
  79. _reporterNs.report("PipelineSettings", "./builtin-pipeline-types", _context.meta, extras);
  80. }
  81. _export({
  82. PipelineConfigs: void 0,
  83. CameraConfigs: void 0,
  84. getPingPongRenderTarget: getPingPongRenderTarget,
  85. BuiltinForwardPassBuilder: void 0,
  86. BuiltinBloomPassBuilder: void 0,
  87. BuiltinToneMappingPassBuilder: void 0,
  88. BuiltinFXAAPassBuilder: void 0,
  89. BuiltinFsrPassBuilder: void 0,
  90. BuiltinUiPassBuilder: void 0
  91. });
  92. return {
  93. setters: [function (_unresolved_) {
  94. _reporterNs = _unresolved_;
  95. }, function (_cc) {
  96. _cclegacy = _cc.cclegacy;
  97. __checkObsolete__ = _cc.__checkObsolete__;
  98. __checkObsoleteInNamespace__ = _cc.__checkObsoleteInNamespace__;
  99. assert = _cc.assert;
  100. cclegacy = _cc.cclegacy;
  101. clamp = _cc.clamp;
  102. geometry = _cc.geometry;
  103. gfx = _cc.gfx;
  104. Layers = _cc.Layers;
  105. Material = _cc.Material;
  106. pipeline = _cc.pipeline;
  107. PipelineEventType = _cc.PipelineEventType;
  108. renderer = _cc.renderer;
  109. rendering = _cc.rendering;
  110. sys = _cc.sys;
  111. Vec2 = _cc.Vec2;
  112. Vec3 = _cc.Vec3;
  113. Vec4 = _cc.Vec4;
  114. warn = _cc.warn;
  115. }, function (_ccEnv) {
  116. DEBUG = _ccEnv.DEBUG;
  117. EDITOR = _ccEnv.EDITOR;
  118. }, function (_unresolved_2) {
  119. makePipelineSettings = _unresolved_2.makePipelineSettings;
  120. }],
  121. execute: function () {
  122. _crd = true;
  123. _cclegacy._RF.push({}, "ff9b0GZzgRM/obMbHGfCNbk", "builtin-pipeline", undefined);
  124. /*
  125. Copyright (c) 2021-2024 Xiamen Yaji Software Co., Ltd.
  126. https://www.cocos.com/
  127. Permission is hereby granted, free of charge, to any person obtaining a copy
  128. of this software and associated documentation files (the "Software"), to deal
  129. in the Software without restriction, including without limitation the rights to
  130. use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
  131. of the Software, and to permit persons to whom the Software is furnished to do so,
  132. subject to the following conditions:
  133. The above copyright notice and this permission notice shall be included in
  134. all copies or substantial portions of the Software.
  135. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  136. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  137. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  138. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  139. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  140. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  141. THE SOFTWARE.
  142. */
  143. __checkObsolete__(['assert', 'cclegacy', 'clamp', 'geometry', 'gfx', 'Layers', 'Material', 'pipeline', 'PipelineEventProcessor', 'PipelineEventType', 'ReflectionProbeManager', 'renderer', 'rendering', 'sys', 'Vec2', 'Vec3', 'Vec4', 'warn']);
  144. ({
  145. AABB,
  146. Sphere,
  147. intersect
  148. } = geometry);
  149. ({
  150. ClearFlagBit,
  151. Color,
  152. Format,
  153. FormatFeatureBit,
  154. LoadOp,
  155. StoreOp,
  156. TextureType,
  157. Viewport
  158. } = gfx);
  159. ({
  160. scene
  161. } = renderer);
  162. ({
  163. CameraUsage,
  164. CSMLevel,
  165. LightType
  166. } = scene);
  167. _export("PipelineConfigs", PipelineConfigs = class PipelineConfigs {
  168. constructor() {
  169. this.isWeb = false;
  170. this.isWebGL1 = false;
  171. this.isWebGPU = false;
  172. this.isMobile = false;
  173. this.isHDR = false;
  174. this.useFloatOutput = false;
  175. this.toneMappingType = 0;
  176. // 0: ACES, 1: None
  177. this.shadowEnabled = false;
  178. this.shadowMapFormat = Format.R32F;
  179. this.shadowMapSize = new Vec2(1, 1);
  180. this.usePlanarShadow = false;
  181. this.screenSpaceSignY = 1;
  182. this.supportDepthSample = false;
  183. this.mobileMaxSpotLightShadowMaps = 1;
  184. this.platform = new Vec4(0, 0, 0, 0);
  185. }
  186. });
  187. defaultSettings = (_crd && makePipelineSettings === void 0 ? (_reportPossibleCrUseOfmakePipelineSettings({
  188. error: Error()
  189. }), makePipelineSettings) : makePipelineSettings)();
  190. _export("CameraConfigs", CameraConfigs = class CameraConfigs {
  191. constructor() {
  192. this.settings = defaultSettings;
  193. // Window
  194. this.isMainGameWindow = false;
  195. this.renderWindowId = 0;
  196. // Camera
  197. this.colorName = '';
  198. this.depthStencilName = '';
  199. // Pipeline
  200. this.enableFullPipeline = false;
  201. this.enableProfiler = false;
  202. this.remainingPasses = 0;
  203. // Shading Scale
  204. this.enableShadingScale = false;
  205. this.shadingScale = 1.0;
  206. this.nativeWidth = 1;
  207. this.nativeHeight = 1;
  208. this.width = 1;
  209. // Scaled width
  210. this.height = 1;
  211. // Scaled height
  212. // Radiance
  213. this.enableHDR = false;
  214. this.radianceFormat = gfx.Format.RGBA8;
  215. // Tone Mapping
  216. this.copyAndTonemapMaterial = null;
  217. // Depth
  218. /** @en mutable */
  219. this.enableStoreSceneDepth = false;
  220. }
  221. });
  222. sClearColorTransparentBlack = new Color(0, 0, 0, 0);
  223. ForwardLighting = class ForwardLighting {
  224. constructor() {
  225. // Active lights
  226. this.lights = [];
  227. // Active spot lights with shadows (Mutually exclusive with `lights`)
  228. this.shadowEnabledSpotLights = [];
  229. // Internal cached resources
  230. this._sphere = Sphere.create(0, 0, 0, 1);
  231. this._boundingBox = new AABB();
  232. this._rangedDirLightBoundingBox = new AABB(0.0, 0.0, 0.0, 0.5, 0.5, 0.5);
  233. }
  234. // ----------------------------------------------------------------
  235. // Interface
  236. // ----------------------------------------------------------------
  237. cullLights(scene, frustum, cameraPos) {
  238. // TODO(zhouzhenglong): Make light culling native
  239. this.lights.length = 0;
  240. this.shadowEnabledSpotLights.length = 0; // spot lights
  241. for (const light of scene.spotLights) {
  242. if (light.baked) {
  243. continue;
  244. }
  245. Sphere.set(this._sphere, light.position.x, light.position.y, light.position.z, light.range);
  246. if (intersect.sphereFrustum(this._sphere, frustum)) {
  247. if (light.shadowEnabled) {
  248. this.shadowEnabledSpotLights.push(light);
  249. } else {
  250. this.lights.push(light);
  251. }
  252. }
  253. } // sphere lights
  254. for (const light of scene.sphereLights) {
  255. if (light.baked) {
  256. continue;
  257. }
  258. Sphere.set(this._sphere, light.position.x, light.position.y, light.position.z, light.range);
  259. if (intersect.sphereFrustum(this._sphere, frustum)) {
  260. this.lights.push(light);
  261. }
  262. } // point lights
  263. for (const light of scene.pointLights) {
  264. if (light.baked) {
  265. continue;
  266. }
  267. Sphere.set(this._sphere, light.position.x, light.position.y, light.position.z, light.range);
  268. if (intersect.sphereFrustum(this._sphere, frustum)) {
  269. this.lights.push(light);
  270. }
  271. } // ranged dir lights
  272. for (const light of scene.rangedDirLights) {
  273. AABB.transform(this._boundingBox, this._rangedDirLightBoundingBox, light.node.getWorldMatrix());
  274. if (intersect.aabbFrustum(this._boundingBox, frustum)) {
  275. this.lights.push(light);
  276. }
  277. }
  278. if (cameraPos) {
  279. this.shadowEnabledSpotLights.sort((lhs, rhs) => Vec3.squaredDistance(cameraPos, lhs.position) - Vec3.squaredDistance(cameraPos, rhs.position));
  280. }
  281. }
  282. _addLightQueues(camera, pass) {
  283. for (const light of this.lights) {
  284. const queue = pass.addQueue(rendering.QueueHint.BLEND, 'forward-add');
  285. switch (light.type) {
  286. case LightType.SPHERE:
  287. queue.name = 'sphere-light';
  288. break;
  289. case LightType.SPOT:
  290. queue.name = 'spot-light';
  291. break;
  292. case LightType.POINT:
  293. queue.name = 'point-light';
  294. break;
  295. case LightType.RANGED_DIRECTIONAL:
  296. queue.name = 'ranged-directional-light';
  297. break;
  298. default:
  299. queue.name = 'unknown-light';
  300. }
  301. queue.addScene(camera, rendering.SceneFlags.BLEND, light);
  302. }
  303. }
  304. addSpotlightShadowPasses(ppl, camera, maxNumShadowMaps) {
  305. let i = 0;
  306. for (const light of this.shadowEnabledSpotLights) {
  307. const shadowMapSize = ppl.pipelineSceneData.shadows.size;
  308. const shadowPass = ppl.addRenderPass(shadowMapSize.x, shadowMapSize.y, 'default');
  309. shadowPass.name = `SpotLightShadowPass${i}`;
  310. shadowPass.addRenderTarget(`SpotShadowMap${i}`, LoadOp.CLEAR, StoreOp.STORE, new Color(1, 1, 1, 1));
  311. shadowPass.addDepthStencil(`SpotShadowDepth${i}`, LoadOp.CLEAR, StoreOp.DISCARD);
  312. shadowPass.addQueue(rendering.QueueHint.NONE, 'shadow-caster').addScene(camera, rendering.SceneFlags.OPAQUE | rendering.SceneFlags.MASK | rendering.SceneFlags.SHADOW_CASTER).useLightFrustum(light);
  313. ++i;
  314. if (i >= maxNumShadowMaps) {
  315. break;
  316. }
  317. }
  318. }
  319. addLightQueues(pass, camera, maxNumShadowMaps) {
  320. this._addLightQueues(camera, pass);
  321. let i = 0;
  322. for (const light of this.shadowEnabledSpotLights) {
  323. // Add spot-light pass
  324. // Save last RenderPass to the `pass` variable
  325. // TODO(zhouzhenglong): Fix per queue addTexture
  326. pass.addTexture(`SpotShadowMap${i}`, 'cc_spotShadowMap');
  327. const queue = pass.addQueue(rendering.QueueHint.BLEND, 'forward-add');
  328. queue.addScene(camera, rendering.SceneFlags.BLEND, light);
  329. ++i;
  330. if (i >= maxNumShadowMaps) {
  331. break;
  332. }
  333. }
  334. } // Notice: ForwardLighting cannot handle a lot of lights.
  335. // If there are too many lights, the performance will be very poor.
  336. // If many lights are needed, please implement a forward+ or deferred rendering pipeline.
  337. addLightPasses(colorName, depthStencilName, depthStencilStoreOp, id, // window id
  338. width, height, camera, viewport, ppl, pass) {
  339. this._addLightQueues(camera, pass);
  340. let count = 0;
  341. const shadowMapSize = ppl.pipelineSceneData.shadows.size;
  342. for (const light of this.shadowEnabledSpotLights) {
  343. const shadowPass = ppl.addRenderPass(shadowMapSize.x, shadowMapSize.y, 'default');
  344. shadowPass.name = 'SpotlightShadowPass'; // Reuse csm shadow map
  345. shadowPass.addRenderTarget(`ShadowMap${id}`, LoadOp.CLEAR, StoreOp.STORE, new Color(1, 1, 1, 1));
  346. shadowPass.addDepthStencil(`ShadowDepth${id}`, LoadOp.CLEAR, StoreOp.DISCARD);
  347. shadowPass.addQueue(rendering.QueueHint.NONE, 'shadow-caster').addScene(camera, rendering.SceneFlags.OPAQUE | rendering.SceneFlags.MASK | rendering.SceneFlags.SHADOW_CASTER).useLightFrustum(light); // Add spot-light pass
  348. // Save last RenderPass to the `pass` variable
  349. ++count;
  350. const storeOp = count === this.shadowEnabledSpotLights.length ? depthStencilStoreOp : StoreOp.STORE;
  351. pass = ppl.addRenderPass(width, height, 'default');
  352. pass.name = 'SpotlightWithShadowMap';
  353. pass.setViewport(viewport);
  354. pass.addRenderTarget(colorName, LoadOp.LOAD);
  355. pass.addDepthStencil(depthStencilName, LoadOp.LOAD, storeOp);
  356. pass.addTexture(`ShadowMap${id}`, 'cc_spotShadowMap');
  357. const queue = pass.addQueue(rendering.QueueHint.BLEND, 'forward-add');
  358. queue.addScene(camera, rendering.SceneFlags.BLEND, light);
  359. }
  360. return pass;
  361. }
  362. isMultipleLightPassesNeeded() {
  363. return this.shadowEnabledSpotLights.length > 0;
  364. }
  365. };
  366. _export("BuiltinForwardPassBuilder", BuiltinForwardPassBuilder = class BuiltinForwardPassBuilder {
  367. constructor() {
  368. this.forwardLighting = new ForwardLighting();
  369. this._viewport = new Viewport();
  370. this._clearColor = new Color(0, 0, 0, 1);
  371. this._reflectionProbeClearColor = new Vec3(0, 0, 0);
  372. }
  373. getConfigOrder() {
  374. return BuiltinForwardPassBuilder.ConfigOrder;
  375. }
  376. getRenderOrder() {
  377. return BuiltinForwardPassBuilder.RenderOrder;
  378. }
  379. configCamera(camera, pipelineConfigs, cameraConfigs) {
  380. // Shadow
  381. cameraConfigs.enableMainLightShadowMap = pipelineConfigs.shadowEnabled && !pipelineConfigs.usePlanarShadow && !!camera.scene && !!camera.scene.mainLight && camera.scene.mainLight.shadowEnabled;
  382. cameraConfigs.enableMainLightPlanarShadowMap = pipelineConfigs.shadowEnabled && pipelineConfigs.usePlanarShadow && !!camera.scene && !!camera.scene.mainLight && camera.scene.mainLight.shadowEnabled; // Reflection Probe
  383. cameraConfigs.enablePlanarReflectionProbe = cameraConfigs.isMainGameWindow || camera.cameraUsage === CameraUsage.SCENE_VIEW; // MSAA
  384. cameraConfigs.enableMSAA = cameraConfigs.settings.msaa.enabled && !cameraConfigs.enableStoreSceneDepth // Cannot store MS depth, resolve depth is also not cross-platform
  385. && !pipelineConfigs.isWeb // TODO(zhouzhenglong): remove this constraint
  386. && !pipelineConfigs.isWebGL1; // Forward rendering (Depend on MSAA and TBR)
  387. cameraConfigs.enableSingleForwardPass = pipelineConfigs.isMobile || cameraConfigs.enableMSAA;
  388. ++cameraConfigs.remainingPasses;
  389. }
  390. windowResize(ppl, pplConfigs, cameraConfigs, window, camera, nativeWidth, nativeHeight) {
  391. const ResourceFlags = rendering.ResourceFlags;
  392. const ResourceResidency = rendering.ResourceResidency;
  393. const id = window.renderWindowId;
  394. const settings = cameraConfigs.settings;
  395. const width = cameraConfigs.enableShadingScale ? Math.max(Math.floor(nativeWidth * cameraConfigs.shadingScale), 1) : nativeWidth;
  396. const height = cameraConfigs.enableShadingScale ? Math.max(Math.floor(nativeHeight * cameraConfigs.shadingScale), 1) : nativeHeight; // MsaaRadiance
  397. if (cameraConfigs.enableMSAA) {
  398. // Notice: We never store multisample results.
  399. // These samples are always resolved and discarded at the end of the render pass.
  400. // So the ResourceResidency should be MEMORYLESS.
  401. if (cameraConfigs.enableHDR) {
  402. ppl.addTexture(`MsaaRadiance${id}`, TextureType.TEX2D, cameraConfigs.radianceFormat, width, height, 1, 1, 1, settings.msaa.sampleCount, ResourceFlags.COLOR_ATTACHMENT, ResourceResidency.MEMORYLESS);
  403. } else {
  404. ppl.addTexture(`MsaaRadiance${id}`, TextureType.TEX2D, Format.RGBA8, width, height, 1, 1, 1, settings.msaa.sampleCount, ResourceFlags.COLOR_ATTACHMENT, ResourceResidency.MEMORYLESS);
  405. }
  406. ppl.addTexture(`MsaaDepthStencil${id}`, TextureType.TEX2D, Format.DEPTH_STENCIL, width, height, 1, 1, 1, settings.msaa.sampleCount, ResourceFlags.DEPTH_STENCIL_ATTACHMENT, ResourceResidency.MEMORYLESS);
  407. } // Mainlight ShadowMap
  408. ppl.addRenderTarget(`ShadowMap${id}`, pplConfigs.shadowMapFormat, pplConfigs.shadowMapSize.x, pplConfigs.shadowMapSize.y);
  409. ppl.addDepthStencil(`ShadowDepth${id}`, Format.DEPTH_STENCIL, pplConfigs.shadowMapSize.x, pplConfigs.shadowMapSize.y); // Spot-light shadow maps
  410. if (cameraConfigs.enableSingleForwardPass) {
  411. const count = pplConfigs.mobileMaxSpotLightShadowMaps;
  412. for (let i = 0; i !== count; ++i) {
  413. ppl.addRenderTarget(`SpotShadowMap${i}`, pplConfigs.shadowMapFormat, pplConfigs.shadowMapSize.x, pplConfigs.shadowMapSize.y);
  414. ppl.addDepthStencil(`SpotShadowDepth${i}`, Format.DEPTH_STENCIL, pplConfigs.shadowMapSize.x, pplConfigs.shadowMapSize.y);
  415. }
  416. }
  417. }
  418. setup(ppl, pplConfigs, cameraConfigs, camera, context) {
  419. const id = camera.window.renderWindowId;
  420. const scene = camera.scene;
  421. const mainLight = scene.mainLight;
  422. --cameraConfigs.remainingPasses;
  423. assert(cameraConfigs.remainingPasses >= 0); // Forward Lighting (Light Culling)
  424. this.forwardLighting.cullLights(scene, camera.frustum); // Main Directional light CSM Shadow Map
  425. if (cameraConfigs.enableMainLightShadowMap) {
  426. assert(!!mainLight);
  427. this._addCascadedShadowMapPass(ppl, pplConfigs, id, mainLight, camera);
  428. } // Spot light shadow maps (Mobile or MSAA)
  429. if (cameraConfigs.enableSingleForwardPass) {
  430. // Currently, only support 1 spot light with shadow map on mobile platform.
  431. // TODO(zhouzhenglong): Relex this limitation.
  432. this.forwardLighting.addSpotlightShadowPasses(ppl, camera, pplConfigs.mobileMaxSpotLightShadowMaps);
  433. }
  434. this._tryAddReflectionProbePasses(ppl, cameraConfigs, id, mainLight, camera.scene);
  435. if (cameraConfigs.remainingPasses > 0 || cameraConfigs.enableShadingScale) {
  436. context.colorName = cameraConfigs.enableShadingScale ? `ScaledRadiance0_${id}` : `Radiance0_${id}`;
  437. context.depthStencilName = cameraConfigs.enableShadingScale ? `ScaledSceneDepth_${id}` : `SceneDepth_${id}`;
  438. } else {
  439. context.colorName = cameraConfigs.colorName;
  440. context.depthStencilName = cameraConfigs.depthStencilName;
  441. }
  442. const pass = this._addForwardRadiancePasses(ppl, pplConfigs, cameraConfigs, id, camera, cameraConfigs.width, cameraConfigs.height, mainLight, context.colorName, context.depthStencilName, !cameraConfigs.enableMSAA, cameraConfigs.enableStoreSceneDepth ? StoreOp.STORE : StoreOp.DISCARD);
  443. if (!cameraConfigs.enableStoreSceneDepth) {
  444. context.depthStencilName = '';
  445. }
  446. if (cameraConfigs.remainingPasses === 0 && cameraConfigs.enableShadingScale) {
  447. return addCopyToScreenPass(ppl, pplConfigs, cameraConfigs, context.colorName);
  448. } else {
  449. return pass;
  450. }
  451. }
  452. _addCascadedShadowMapPass(ppl, pplConfigs, id, light, camera) {
  453. const QueueHint = rendering.QueueHint;
  454. const SceneFlags = rendering.SceneFlags; // ----------------------------------------------------------------
  455. // Dynamic states
  456. // ----------------------------------------------------------------
  457. const shadowSize = ppl.pipelineSceneData.shadows.size;
  458. const width = shadowSize.x;
  459. const height = shadowSize.y;
  460. const viewport = this._viewport;
  461. viewport.left = viewport.top = 0;
  462. viewport.width = width;
  463. viewport.height = height; // ----------------------------------------------------------------
  464. // CSM Shadow Map
  465. // ----------------------------------------------------------------
  466. const pass = ppl.addRenderPass(width, height, 'default');
  467. pass.name = 'CascadedShadowMap';
  468. pass.addRenderTarget(`ShadowMap${id}`, LoadOp.CLEAR, StoreOp.STORE, new Color(1, 1, 1, 1));
  469. pass.addDepthStencil(`ShadowDepth${id}`, LoadOp.CLEAR, StoreOp.DISCARD);
  470. const csmLevel = ppl.pipelineSceneData.csmSupported ? light.csmLevel : 1; // Add shadow map viewports
  471. for (let level = 0; level !== csmLevel; ++level) {
  472. getCsmMainLightViewport(light, width, height, level, this._viewport, pplConfigs.screenSpaceSignY);
  473. const queue = pass.addQueue(QueueHint.NONE, 'shadow-caster');
  474. if (!pplConfigs.isWebGPU) {
  475. // Temporary workaround for WebGPU
  476. queue.setViewport(this._viewport);
  477. }
  478. queue.addScene(camera, SceneFlags.OPAQUE | SceneFlags.MASK | SceneFlags.SHADOW_CASTER).useLightFrustum(light, level);
  479. }
  480. }
  481. _tryAddReflectionProbePasses(ppl, cameraConfigs, id, mainLight, scene) {
  482. const reflectionProbeManager = cclegacy.internal.reflectionProbeManager;
  483. if (!reflectionProbeManager) {
  484. return;
  485. }
  486. const ResourceResidency = rendering.ResourceResidency;
  487. const probes = reflectionProbeManager.getProbes();
  488. const maxProbeCount = 4;
  489. let probeID = 0;
  490. for (const probe of probes) {
  491. if (!probe.needRender) {
  492. continue;
  493. }
  494. const area = probe.renderArea();
  495. const width = Math.max(Math.floor(area.x), 1);
  496. const height = Math.max(Math.floor(area.y), 1);
  497. if (probe.probeType === renderer.scene.ProbeType.PLANAR) {
  498. if (!cameraConfigs.enablePlanarReflectionProbe) {
  499. continue;
  500. }
  501. const window = probe.realtimePlanarTexture.window;
  502. const colorName = `PlanarProbeRT${probeID}`;
  503. const depthStencilName = `PlanarProbeDS${probeID}`; // ProbeResource
  504. ppl.addRenderWindow(colorName, cameraConfigs.radianceFormat, width, height, window);
  505. ppl.addDepthStencil(depthStencilName, gfx.Format.DEPTH_STENCIL, width, height, ResourceResidency.MEMORYLESS); // Rendering
  506. const probePass = ppl.addRenderPass(width, height, 'default');
  507. probePass.name = `PlanarReflectionProbe${probeID}`;
  508. this._buildReflectionProbePass(probePass, cameraConfigs, id, probe.camera, colorName, depthStencilName, mainLight, scene);
  509. } else if (EDITOR) {
  510. for (let faceIdx = 0; faceIdx < probe.bakedCubeTextures.length; faceIdx++) {
  511. probe.updateCameraDir(faceIdx);
  512. const window = probe.bakedCubeTextures[faceIdx].window;
  513. const colorName = `CubeProbeRT${probeID}${faceIdx}`;
  514. const depthStencilName = `CubeProbeDS${probeID}${faceIdx}`; // ProbeResource
  515. ppl.addRenderWindow(colorName, cameraConfigs.radianceFormat, width, height, window);
  516. ppl.addDepthStencil(depthStencilName, gfx.Format.DEPTH_STENCIL, width, height, ResourceResidency.MEMORYLESS); // Rendering
  517. const probePass = ppl.addRenderPass(width, height, 'default');
  518. probePass.name = `CubeProbe${probeID}${faceIdx}`;
  519. this._buildReflectionProbePass(probePass, cameraConfigs, id, probe.camera, colorName, depthStencilName, mainLight, scene);
  520. }
  521. probe.needRender = false;
  522. }
  523. ++probeID;
  524. if (probeID === maxProbeCount) {
  525. break;
  526. }
  527. }
  528. }
  529. _buildReflectionProbePass(pass, cameraConfigs, id, camera, colorName, depthStencilName, mainLight, scene = null) {
  530. const QueueHint = rendering.QueueHint;
  531. const SceneFlags = rendering.SceneFlags; // set viewport
  532. const colorStoreOp = cameraConfigs.enableMSAA ? StoreOp.DISCARD : StoreOp.STORE; // bind output render target
  533. if (forwardNeedClearColor(camera)) {
  534. this._reflectionProbeClearColor.x = camera.clearColor.x;
  535. this._reflectionProbeClearColor.y = camera.clearColor.y;
  536. this._reflectionProbeClearColor.z = camera.clearColor.z;
  537. const clearColor = rendering.packRGBE(this._reflectionProbeClearColor);
  538. this._clearColor.x = clearColor.x;
  539. this._clearColor.y = clearColor.y;
  540. this._clearColor.z = clearColor.z;
  541. this._clearColor.w = clearColor.w;
  542. pass.addRenderTarget(colorName, LoadOp.CLEAR, colorStoreOp, this._clearColor);
  543. } else {
  544. pass.addRenderTarget(colorName, LoadOp.LOAD, colorStoreOp);
  545. } // bind depth stencil buffer
  546. if (camera.clearFlag & ClearFlagBit.DEPTH_STENCIL) {
  547. pass.addDepthStencil(depthStencilName, LoadOp.CLEAR, StoreOp.DISCARD, camera.clearDepth, camera.clearStencil, camera.clearFlag & ClearFlagBit.DEPTH_STENCIL);
  548. } else {
  549. pass.addDepthStencil(depthStencilName, LoadOp.LOAD, StoreOp.DISCARD);
  550. } // Set shadow map if enabled
  551. if (cameraConfigs.enableMainLightShadowMap) {
  552. pass.addTexture(`ShadowMap${id}`, 'cc_shadowMap');
  553. } // TODO(zhouzhenglong): Separate OPAQUE and MASK queue
  554. // add opaque and mask queue
  555. pass.addQueue(QueueHint.NONE, 'reflect-map') // Currently we put OPAQUE and MASK into one queue, so QueueHint is NONE
  556. .addScene(camera, SceneFlags.OPAQUE | SceneFlags.MASK | SceneFlags.REFLECTION_PROBE, mainLight || undefined, scene ? scene : undefined);
  557. }
  558. _addForwardRadiancePasses(ppl, pplConfigs, cameraConfigs, id, camera, width, height, mainLight, colorName, depthStencilName, disableMSAA = false, depthStencilStoreOp = StoreOp.DISCARD) {
  559. const QueueHint = rendering.QueueHint;
  560. const SceneFlags = rendering.SceneFlags; // ----------------------------------------------------------------
  561. // Dynamic states
  562. // ----------------------------------------------------------------
  563. // Prepare camera clear color
  564. const clearColor = camera.clearColor; // Reduce C++/TS interop
  565. this._clearColor.x = clearColor.x;
  566. this._clearColor.y = clearColor.y;
  567. this._clearColor.z = clearColor.z;
  568. this._clearColor.w = clearColor.w; // Prepare camera viewport
  569. const viewport = camera.viewport; // Reduce C++/TS interop
  570. this._viewport.left = Math.round(viewport.x * width);
  571. this._viewport.top = Math.round(viewport.y * height); // Here we must use camera.viewport.width instead of camera.viewport.z, which
  572. // is undefined on native platform. The same as camera.viewport.height.
  573. this._viewport.width = Math.max(Math.round(viewport.width * width), 1);
  574. this._viewport.height = Math.max(Math.round(viewport.height * height), 1); // MSAA
  575. const enableMSAA = !disableMSAA && cameraConfigs.enableMSAA;
  576. assert(!enableMSAA || cameraConfigs.enableSingleForwardPass); // ----------------------------------------------------------------
  577. // Forward Lighting (Main Directional Light)
  578. // ----------------------------------------------------------------
  579. const pass = cameraConfigs.enableSingleForwardPass ? this._addForwardSingleRadiancePass(ppl, pplConfigs, cameraConfigs, id, camera, enableMSAA, width, height, mainLight, colorName, depthStencilName, depthStencilStoreOp) : this._addForwardMultipleRadiancePasses(ppl, cameraConfigs, id, camera, width, height, mainLight, colorName, depthStencilName, depthStencilStoreOp); // Planar Shadow
  580. if (cameraConfigs.enableMainLightPlanarShadowMap) {
  581. this._addPlanarShadowQueue(camera, mainLight, pass);
  582. } // ----------------------------------------------------------------
  583. // Forward Lighting (Blend)
  584. // ----------------------------------------------------------------
  585. // Add transparent queue
  586. const sceneFlags = SceneFlags.BLEND | (camera.geometryRenderer ? SceneFlags.GEOMETRY : SceneFlags.NONE);
  587. pass.addQueue(QueueHint.BLEND).addScene(camera, sceneFlags, mainLight || undefined);
  588. return pass;
  589. }
  590. _addForwardSingleRadiancePass(ppl, pplConfigs, cameraConfigs, id, camera, enableMSAA, width, height, mainLight, colorName, depthStencilName, depthStencilStoreOp) {
  591. assert(cameraConfigs.enableSingleForwardPass); // ----------------------------------------------------------------
  592. // Forward Lighting (Main Directional Light)
  593. // ----------------------------------------------------------------
  594. let pass;
  595. if (enableMSAA) {
  596. const msaaRadianceName = `MsaaRadiance${id}`;
  597. const msaaDepthStencilName = `MsaaDepthStencil${id}`;
  598. const sampleCount = cameraConfigs.settings.msaa.sampleCount;
  599. const msPass = ppl.addMultisampleRenderPass(width, height, sampleCount, 0, 'default');
  600. msPass.name = 'MsaaForwardPass'; // MSAA always discards depth stencil
  601. this._buildForwardMainLightPass(msPass, cameraConfigs, id, camera, msaaRadianceName, msaaDepthStencilName, StoreOp.DISCARD, mainLight);
  602. msPass.resolveRenderTarget(msaaRadianceName, colorName);
  603. pass = msPass;
  604. } else {
  605. pass = ppl.addRenderPass(width, height, 'default');
  606. pass.name = 'ForwardPass';
  607. this._buildForwardMainLightPass(pass, cameraConfigs, id, camera, colorName, depthStencilName, depthStencilStoreOp, mainLight);
  608. }
  609. assert(pass !== undefined); // Forward Lighting (Additive Lights)
  610. this.forwardLighting.addLightQueues(pass, camera, pplConfigs.mobileMaxSpotLightShadowMaps);
  611. return pass;
  612. }
  613. _addForwardMultipleRadiancePasses(ppl, cameraConfigs, id, camera, width, height, mainLight, colorName, depthStencilName, depthStencilStoreOp) {
  614. assert(!cameraConfigs.enableSingleForwardPass); // Forward Lighting (Main Directional Light)
  615. let pass = ppl.addRenderPass(width, height, 'default');
  616. pass.name = 'ForwardPass';
  617. const firstStoreOp = this.forwardLighting.isMultipleLightPassesNeeded() ? StoreOp.STORE : depthStencilStoreOp;
  618. this._buildForwardMainLightPass(pass, cameraConfigs, id, camera, colorName, depthStencilName, firstStoreOp, mainLight); // Forward Lighting (Additive Lights)
  619. pass = this.forwardLighting.addLightPasses(colorName, depthStencilName, depthStencilStoreOp, id, width, height, camera, this._viewport, ppl, pass);
  620. return pass;
  621. }
  622. _buildForwardMainLightPass(pass, cameraConfigs, id, camera, colorName, depthStencilName, depthStencilStoreOp, mainLight, scene = null) {
  623. const QueueHint = rendering.QueueHint;
  624. const SceneFlags = rendering.SceneFlags; // set viewport
  625. pass.setViewport(this._viewport);
  626. const colorStoreOp = cameraConfigs.enableMSAA ? StoreOp.DISCARD : StoreOp.STORE; // bind output render target
  627. if (forwardNeedClearColor(camera)) {
  628. pass.addRenderTarget(colorName, LoadOp.CLEAR, colorStoreOp, this._clearColor);
  629. } else {
  630. pass.addRenderTarget(colorName, LoadOp.LOAD, colorStoreOp);
  631. } // bind depth stencil buffer
  632. if (DEBUG) {
  633. if (colorName === cameraConfigs.colorName && depthStencilName !== cameraConfigs.depthStencilName) {
  634. warn('Default framebuffer cannot use custom depth stencil buffer');
  635. }
  636. }
  637. if (camera.clearFlag & ClearFlagBit.DEPTH_STENCIL) {
  638. pass.addDepthStencil(depthStencilName, LoadOp.CLEAR, depthStencilStoreOp, camera.clearDepth, camera.clearStencil, camera.clearFlag & ClearFlagBit.DEPTH_STENCIL);
  639. } else {
  640. pass.addDepthStencil(depthStencilName, LoadOp.LOAD, depthStencilStoreOp);
  641. } // Set shadow map if enabled
  642. if (cameraConfigs.enableMainLightShadowMap) {
  643. pass.addTexture(`ShadowMap${id}`, 'cc_shadowMap');
  644. } // TODO(zhouzhenglong): Separate OPAQUE and MASK queue
  645. // add opaque and mask queue
  646. pass.addQueue(QueueHint.NONE) // Currently we put OPAQUE and MASK into one queue, so QueueHint is NONE
  647. .addScene(camera, SceneFlags.OPAQUE | SceneFlags.MASK, mainLight || undefined, scene ? scene : undefined);
  648. }
  649. _addPlanarShadowQueue(camera, mainLight, pass) {
  650. const QueueHint = rendering.QueueHint;
  651. const SceneFlags = rendering.SceneFlags;
  652. pass.addQueue(QueueHint.BLEND, 'planar-shadow').addScene(camera, SceneFlags.SHADOW_CASTER | SceneFlags.PLANAR_SHADOW | SceneFlags.BLEND, mainLight || undefined);
  653. }
  654. });
  655. BuiltinForwardPassBuilder.ConfigOrder = 100;
  656. BuiltinForwardPassBuilder.RenderOrder = 100;
  657. _export("BuiltinBloomPassBuilder", BuiltinBloomPassBuilder = class BuiltinBloomPassBuilder {
  658. constructor() {
  659. // Bloom
  660. this._clearColorTransparentBlack = new Color(0, 0, 0, 0);
  661. this._bloomParams = new Vec4(0, 0, 0, 0);
  662. this._bloomTexSize = new Vec4(0, 0, 0, 0);
  663. this._bloomWidths = [];
  664. this._bloomHeights = [];
  665. this._bloomTexNames = [];
  666. }
  667. getConfigOrder() {
  668. return 0;
  669. }
  670. getRenderOrder() {
  671. return 200;
  672. }
  673. configCamera(camera, pipelineConfigs, cameraConfigs) {
  674. cameraConfigs.enableBloom = cameraConfigs.settings.bloom.enabled && !!cameraConfigs.settings.bloom.material;
  675. if (cameraConfigs.enableBloom) {
  676. ++cameraConfigs.remainingPasses;
  677. }
  678. }
  679. windowResize(ppl, pplConfigs, cameraConfigs, window) {
  680. if (cameraConfigs.enableBloom) {
  681. const id = window.renderWindowId;
  682. let bloomWidth = cameraConfigs.width;
  683. let bloomHeight = cameraConfigs.height;
  684. for (let i = 0; i !== cameraConfigs.settings.bloom.iterations + 1; ++i) {
  685. bloomWidth = Math.max(Math.floor(bloomWidth / 2), 1);
  686. bloomHeight = Math.max(Math.floor(bloomHeight / 2), 1);
  687. ppl.addRenderTarget(`BloomTex${id}_${i}`, cameraConfigs.radianceFormat, bloomWidth, bloomHeight);
  688. }
  689. }
  690. }
  691. setup(ppl, pplConfigs, cameraConfigs, camera, context, prevRenderPass) {
  692. if (!cameraConfigs.enableBloom) {
  693. return prevRenderPass;
  694. }
  695. --cameraConfigs.remainingPasses;
  696. assert(cameraConfigs.remainingPasses >= 0);
  697. const id = camera.window.renderWindowId;
  698. assert(!!cameraConfigs.settings.bloom.material);
  699. return this._addKawaseDualFilterBloomPasses(ppl, pplConfigs, cameraConfigs, cameraConfigs.settings, cameraConfigs.settings.bloom.material, id, cameraConfigs.width, cameraConfigs.height, context.colorName);
  700. }
  701. _addKawaseDualFilterBloomPasses(ppl, pplConfigs, cameraConfigs, settings, bloomMaterial, id, width, height, radianceName) {
  702. const QueueHint = rendering.QueueHint; // Based on Kawase Dual Filter Blur. Saves bandwidth on mobile devices.
  703. // eslint-disable-next-line max-len
  704. // https://community.arm.com/cfs-file/__key/communityserver-blogs-components-weblogfiles/00-00-00-20-66/siggraph2015_2D00_mmg_2D00_marius_2D00_slides.pdf
  705. // Size: [prefilter(1/2), downsample(1/4), downsample(1/8), downsample(1/16), ...]
  706. const iterations = settings.bloom.iterations;
  707. const sizeCount = iterations + 1;
  708. this._bloomWidths.length = sizeCount;
  709. this._bloomHeights.length = sizeCount;
  710. this._bloomWidths[0] = Math.max(Math.floor(width / 2), 1);
  711. this._bloomHeights[0] = Math.max(Math.floor(height / 2), 1);
  712. for (let i = 1; i !== sizeCount; ++i) {
  713. this._bloomWidths[i] = Math.max(Math.floor(this._bloomWidths[i - 1] / 2), 1);
  714. this._bloomHeights[i] = Math.max(Math.floor(this._bloomHeights[i - 1] / 2), 1);
  715. } // Bloom texture names
  716. this._bloomTexNames.length = sizeCount;
  717. for (let i = 0; i !== sizeCount; ++i) {
  718. this._bloomTexNames[i] = `BloomTex${id}_${i}`;
  719. } // Setup bloom parameters
  720. this._bloomParams.x = pplConfigs.useFloatOutput ? 1 : 0;
  721. this._bloomParams.x = 0; // unused
  722. this._bloomParams.z = settings.bloom.threshold;
  723. this._bloomParams.w = settings.bloom.enableAlphaMask ? 1 : 0; // Prefilter pass
  724. const prefilterPass = ppl.addRenderPass(this._bloomWidths[0], this._bloomHeights[0], 'cc-bloom-prefilter');
  725. prefilterPass.addRenderTarget(this._bloomTexNames[0], LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack);
  726. prefilterPass.addTexture(radianceName, 'inputTexture');
  727. prefilterPass.setVec4('g_platform', pplConfigs.platform);
  728. prefilterPass.setVec4('bloomParams', this._bloomParams);
  729. prefilterPass.addQueue(QueueHint.OPAQUE).addFullscreenQuad(bloomMaterial, 0); // Downsample passes
  730. for (let i = 1; i !== sizeCount; ++i) {
  731. const downPass = ppl.addRenderPass(this._bloomWidths[i], this._bloomHeights[i], 'cc-bloom-downsample');
  732. downPass.addRenderTarget(this._bloomTexNames[i], LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack);
  733. downPass.addTexture(this._bloomTexNames[i - 1], 'bloomTexture');
  734. this._bloomTexSize.x = this._bloomWidths[i - 1];
  735. this._bloomTexSize.y = this._bloomHeights[i - 1];
  736. downPass.setVec4('g_platform', pplConfigs.platform);
  737. downPass.setVec4('bloomTexSize', this._bloomTexSize);
  738. downPass.addQueue(QueueHint.OPAQUE).addFullscreenQuad(bloomMaterial, 1);
  739. } // Upsample passes
  740. for (let i = iterations; i-- > 0;) {
  741. const upPass = ppl.addRenderPass(this._bloomWidths[i], this._bloomHeights[i], 'cc-bloom-upsample');
  742. upPass.addRenderTarget(this._bloomTexNames[i], LoadOp.CLEAR, StoreOp.STORE, this._clearColorTransparentBlack);
  743. upPass.addTexture(this._bloomTexNames[i + 1], 'bloomTexture');
  744. this._bloomTexSize.x = this._bloomWidths[i + 1];
  745. this._bloomTexSize.y = this._bloomHeights[i + 1];
  746. upPass.setVec4('g_platform', pplConfigs.platform);
  747. upPass.setVec4('bloomTexSize', this._bloomTexSize);
  748. upPass.addQueue(QueueHint.OPAQUE).addFullscreenQuad(bloomMaterial, 2);
  749. } // Combine pass
  750. const combinePass = ppl.addRenderPass(width, height, 'cc-bloom-combine');
  751. combinePass.addRenderTarget(radianceName, LoadOp.LOAD, StoreOp.STORE);
  752. combinePass.addTexture(this._bloomTexNames[0], 'bloomTexture');
  753. combinePass.setVec4('g_platform', pplConfigs.platform);
  754. combinePass.setVec4('bloomParams', this._bloomParams);
  755. combinePass.addQueue(QueueHint.BLEND).addFullscreenQuad(bloomMaterial, 3);
  756. if (cameraConfigs.remainingPasses === 0) {
  757. return addCopyToScreenPass(ppl, pplConfigs, cameraConfigs, radianceName);
  758. } else {
  759. return combinePass;
  760. }
  761. }
  762. });
  763. _export("BuiltinToneMappingPassBuilder", BuiltinToneMappingPassBuilder = class BuiltinToneMappingPassBuilder {
  764. constructor() {
  765. this._colorGradingTexSize = new Vec2(0, 0);
  766. }
  767. getConfigOrder() {
  768. return 0;
  769. }
  770. getRenderOrder() {
  771. return 300;
  772. }
  773. configCamera(camera, pplConfigs, cameraConfigs) {
  774. const settings = cameraConfigs.settings;
  775. cameraConfigs.enableColorGrading = settings.colorGrading.enabled && !!settings.colorGrading.material && !!settings.colorGrading.colorGradingMap;
  776. cameraConfigs.enableToneMapping = cameraConfigs.enableHDR // From Half to RGBA8
  777. || cameraConfigs.enableColorGrading; // Color grading
  778. if (cameraConfigs.enableToneMapping) {
  779. ++cameraConfigs.remainingPasses;
  780. }
  781. }
  782. windowResize(ppl, pplConfigs, cameraConfigs) {
  783. if (cameraConfigs.enableColorGrading) {
  784. assert(!!cameraConfigs.settings.colorGrading.material);
  785. cameraConfigs.settings.colorGrading.material.setProperty('colorGradingMap', cameraConfigs.settings.colorGrading.colorGradingMap);
  786. }
  787. }
  788. setup(ppl, pplConfigs, cameraConfigs, camera, context, prevRenderPass) {
  789. if (!cameraConfigs.enableToneMapping) {
  790. return prevRenderPass;
  791. }
  792. --cameraConfigs.remainingPasses;
  793. assert(cameraConfigs.remainingPasses >= 0);
  794. if (cameraConfigs.remainingPasses === 0) {
  795. return this._addCopyAndTonemapPass(ppl, pplConfigs, cameraConfigs, cameraConfigs.nativeWidth, cameraConfigs.nativeHeight, context.colorName, cameraConfigs.colorName);
  796. } else {
  797. const id = cameraConfigs.renderWindowId;
  798. const ldrColorPrefix = cameraConfigs.enableShadingScale ? `ScaledLdrColor` : `LdrColor`;
  799. const ldrColorName = getPingPongRenderTarget(context.colorName, ldrColorPrefix, id);
  800. const radianceName = context.colorName;
  801. context.colorName = ldrColorName;
  802. return this._addCopyAndTonemapPass(ppl, pplConfigs, cameraConfigs, cameraConfigs.width, cameraConfigs.height, radianceName, ldrColorName);
  803. }
  804. }
  805. _addCopyAndTonemapPass(ppl, pplConfigs, cameraConfigs, width, height, radianceName, colorName) {
  806. let pass;
  807. const settings = cameraConfigs.settings;
  808. if (cameraConfigs.enableColorGrading) {
  809. assert(!!settings.colorGrading.material);
  810. assert(!!settings.colorGrading.colorGradingMap);
  811. const lutTex = settings.colorGrading.colorGradingMap;
  812. this._colorGradingTexSize.x = lutTex.width;
  813. this._colorGradingTexSize.y = lutTex.height;
  814. const isSquareMap = lutTex.width === lutTex.height;
  815. if (isSquareMap) {
  816. pass = ppl.addRenderPass(width, height, 'cc-color-grading-8x8');
  817. } else {
  818. pass = ppl.addRenderPass(width, height, 'cc-color-grading-nx1');
  819. }
  820. pass.addRenderTarget(colorName, LoadOp.CLEAR, StoreOp.STORE, sClearColorTransparentBlack);
  821. pass.addTexture(radianceName, 'sceneColorMap');
  822. pass.setVec4('g_platform', pplConfigs.platform);
  823. pass.setVec2('lutTextureSize', this._colorGradingTexSize);
  824. pass.setFloat('contribute', settings.colorGrading.contribute);
  825. pass.addQueue(rendering.QueueHint.OPAQUE).addFullscreenQuad(settings.colorGrading.material, isSquareMap ? 1 : 0);
  826. } else {
  827. pass = ppl.addRenderPass(width, height, 'cc-tone-mapping');
  828. pass.addRenderTarget(colorName, LoadOp.CLEAR, StoreOp.STORE, sClearColorTransparentBlack);
  829. pass.addTexture(radianceName, 'inputTexture');
  830. pass.setVec4('g_platform', pplConfigs.platform);
  831. if (settings.toneMapping.material) {
  832. pass.addQueue(rendering.QueueHint.OPAQUE).addFullscreenQuad(settings.toneMapping.material, 0);
  833. } else {
  834. assert(!!cameraConfigs.copyAndTonemapMaterial);
  835. pass.addQueue(rendering.QueueHint.OPAQUE).addFullscreenQuad(cameraConfigs.copyAndTonemapMaterial, 0);
  836. }
  837. }
  838. return pass;
  839. }
  840. });
  841. _export("BuiltinFXAAPassBuilder", BuiltinFXAAPassBuilder = class BuiltinFXAAPassBuilder {
  842. constructor() {
  843. // FXAA
  844. this._fxaaParams = new Vec4(0, 0, 0, 0);
  845. }
  846. getConfigOrder() {
  847. return 0;
  848. }
  849. getRenderOrder() {
  850. return 400;
  851. }
  852. configCamera(camera, pplConfigs, cameraConfigs) {
  853. cameraConfigs.enableFXAA = cameraConfigs.settings.fxaa.enabled && !!cameraConfigs.settings.fxaa.material;
  854. if (cameraConfigs.enableFXAA) {
  855. ++cameraConfigs.remainingPasses;
  856. }
  857. }
  858. setup(ppl, pplConfigs, cameraConfigs, camera, context, prevRenderPass) {
  859. if (!cameraConfigs.enableFXAA) {
  860. return prevRenderPass;
  861. }
  862. --cameraConfigs.remainingPasses;
  863. assert(cameraConfigs.remainingPasses >= 0);
  864. const id = cameraConfigs.renderWindowId;
  865. const ldrColorPrefix = cameraConfigs.enableShadingScale ? `ScaledLdrColor` : `LdrColor`;
  866. const ldrColorName = getPingPongRenderTarget(context.colorName, ldrColorPrefix, id);
  867. assert(!!cameraConfigs.settings.fxaa.material);
  868. if (cameraConfigs.remainingPasses === 0) {
  869. if (cameraConfigs.enableShadingScale) {
  870. this._addFxaaPass(ppl, pplConfigs, cameraConfigs.settings.fxaa.material, cameraConfigs.width, cameraConfigs.height, context.colorName, ldrColorName);
  871. return addCopyToScreenPass(ppl, pplConfigs, cameraConfigs, ldrColorName);
  872. } else {
  873. assert(cameraConfigs.width === cameraConfigs.nativeWidth);
  874. assert(cameraConfigs.height === cameraConfigs.nativeHeight);
  875. return this._addFxaaPass(ppl, pplConfigs, cameraConfigs.settings.fxaa.material, cameraConfigs.width, cameraConfigs.height, context.colorName, cameraConfigs.colorName);
  876. }
  877. } else {
  878. const inputColorName = context.colorName;
  879. context.colorName = ldrColorName;
  880. const lastPass = this._addFxaaPass(ppl, pplConfigs, cameraConfigs.settings.fxaa.material, cameraConfigs.width, cameraConfigs.height, inputColorName, ldrColorName);
  881. return lastPass;
  882. }
  883. }
  884. _addFxaaPass(ppl, pplConfigs, fxaaMaterial, width, height, ldrColorName, colorName) {
  885. this._fxaaParams.x = width;
  886. this._fxaaParams.y = height;
  887. this._fxaaParams.z = 1 / width;
  888. this._fxaaParams.w = 1 / height;
  889. const pass = ppl.addRenderPass(width, height, 'cc-fxaa');
  890. pass.addRenderTarget(colorName, LoadOp.CLEAR, StoreOp.STORE, sClearColorTransparentBlack);
  891. pass.addTexture(ldrColorName, 'sceneColorMap');
  892. pass.setVec4('g_platform', pplConfigs.platform);
  893. pass.setVec4('texSize', this._fxaaParams);
  894. pass.addQueue(rendering.QueueHint.OPAQUE).addFullscreenQuad(fxaaMaterial, 0);
  895. return pass;
  896. }
  897. });
  898. _export("BuiltinFsrPassBuilder", BuiltinFsrPassBuilder = class BuiltinFsrPassBuilder {
  899. constructor() {
  900. // FSR
  901. this._fsrParams = new Vec4(0, 0, 0, 0);
  902. this._fsrTexSize = new Vec4(0, 0, 0, 0);
  903. }
  904. getConfigOrder() {
  905. return 0;
  906. }
  907. getRenderOrder() {
  908. return 500;
  909. }
  910. configCamera(camera, pplConfigs, cameraConfigs) {
  911. // FSR (Depend on Shading scale)
  912. cameraConfigs.enableFSR = cameraConfigs.settings.fsr.enabled && !!cameraConfigs.settings.fsr.material && cameraConfigs.enableShadingScale && cameraConfigs.shadingScale < 1.0;
  913. if (cameraConfigs.enableFSR) {
  914. ++cameraConfigs.remainingPasses;
  915. }
  916. }
  917. setup(ppl, pplConfigs, cameraConfigs, camera, context, prevRenderPass) {
  918. if (!cameraConfigs.enableFSR) {
  919. return prevRenderPass;
  920. }
  921. --cameraConfigs.remainingPasses;
  922. const inputColorName = context.colorName;
  923. const outputColorName = cameraConfigs.remainingPasses === 0 ? cameraConfigs.colorName : getPingPongRenderTarget(context.colorName, 'UiColor', cameraConfigs.renderWindowId);
  924. context.colorName = outputColorName;
  925. assert(!!cameraConfigs.settings.fsr.material);
  926. return this._addFsrPass(ppl, pplConfigs, cameraConfigs, cameraConfigs.settings, cameraConfigs.settings.fsr.material, cameraConfigs.renderWindowId, cameraConfigs.width, cameraConfigs.height, inputColorName, cameraConfigs.nativeWidth, cameraConfigs.nativeHeight, outputColorName);
  927. }
  928. _addFsrPass(ppl, pplConfigs, cameraConfigs, settings, fsrMaterial, id, width, height, inputColorName, nativeWidth, nativeHeight, outputColorName) {
  929. this._fsrTexSize.x = width;
  930. this._fsrTexSize.y = height;
  931. this._fsrTexSize.z = nativeWidth;
  932. this._fsrTexSize.w = nativeHeight;
  933. this._fsrParams.x = clamp(1.0 - settings.fsr.sharpness, 0.02, 0.98);
  934. const uiColorPrefix = 'UiColor';
  935. const fsrColorName = getPingPongRenderTarget(outputColorName, uiColorPrefix, id);
  936. const easuPass = ppl.addRenderPass(nativeWidth, nativeHeight, 'cc-fsr-easu');
  937. easuPass.addRenderTarget(fsrColorName, LoadOp.CLEAR, StoreOp.STORE, sClearColorTransparentBlack);
  938. easuPass.addTexture(inputColorName, 'outputResultMap');
  939. easuPass.setVec4('g_platform', pplConfigs.platform);
  940. easuPass.setVec4('fsrTexSize', this._fsrTexSize);
  941. easuPass.addQueue(rendering.QueueHint.OPAQUE).addFullscreenQuad(fsrMaterial, 0);
  942. const rcasPass = ppl.addRenderPass(nativeWidth, nativeHeight, 'cc-fsr-rcas');
  943. rcasPass.addRenderTarget(outputColorName, LoadOp.CLEAR, StoreOp.STORE, sClearColorTransparentBlack);
  944. rcasPass.addTexture(fsrColorName, 'outputResultMap');
  945. rcasPass.setVec4('g_platform', pplConfigs.platform);
  946. rcasPass.setVec4('fsrTexSize', this._fsrTexSize);
  947. rcasPass.setVec4('fsrParams', this._fsrParams);
  948. rcasPass.addQueue(rendering.QueueHint.OPAQUE).addFullscreenQuad(fsrMaterial, 1);
  949. return rcasPass;
  950. }
  951. });
  952. _export("BuiltinUiPassBuilder", BuiltinUiPassBuilder = class BuiltinUiPassBuilder {
  953. getConfigOrder() {
  954. return 0;
  955. }
  956. getRenderOrder() {
  957. return 1000;
  958. }
  959. setup(ppl, pplConfigs, cameraConfigs, camera, context, prevRenderPass) {
  960. assert(!!prevRenderPass);
  961. let flags = rendering.SceneFlags.UI;
  962. if (cameraConfigs.enableProfiler) {
  963. flags |= rendering.SceneFlags.PROFILER;
  964. prevRenderPass.showStatistics = true;
  965. }
  966. prevRenderPass.addQueue(rendering.QueueHint.BLEND, 'default', 'default').addScene(camera, flags);
  967. return prevRenderPass;
  968. }
  969. });
  970. if (rendering) {
  971. ({
  972. QueueHint,
  973. SceneFlags
  974. } = rendering);
  975. class BuiltinPipelineBuilder {
  976. constructor() {
  977. this._pipelineEvent = cclegacy.director.root.pipelineEvent;
  978. this._forwardPass = new BuiltinForwardPassBuilder();
  979. this._bloomPass = new BuiltinBloomPassBuilder();
  980. this._toneMappingPass = new BuiltinToneMappingPassBuilder();
  981. this._fxaaPass = new BuiltinFXAAPassBuilder();
  982. this._fsrPass = new BuiltinFsrPassBuilder();
  983. this._uiPass = new BuiltinUiPassBuilder();
  984. // Internal cached resources
  985. this._clearColor = new Color(0, 0, 0, 1);
  986. this._viewport = new Viewport();
  987. this._configs = new PipelineConfigs();
  988. this._cameraConfigs = new CameraConfigs();
  989. // Materials
  990. this._copyAndTonemapMaterial = new Material();
  991. // Internal States
  992. this._initialized = false;
  993. // TODO(zhouzhenglong): Make default effect asset loading earlier and remove this flag
  994. this._passBuilders = [];
  995. }
  996. _setupPipelinePreview(camera, cameraConfigs) {
  997. const isEditorView = camera.cameraUsage === CameraUsage.SCENE_VIEW || camera.cameraUsage === CameraUsage.PREVIEW;
  998. if (isEditorView) {
  999. const editorSettings = rendering.getEditorPipelineSettings();
  1000. if (editorSettings) {
  1001. cameraConfigs.settings = editorSettings;
  1002. } else {
  1003. cameraConfigs.settings = defaultSettings;
  1004. }
  1005. } else {
  1006. if (camera.pipelineSettings) {
  1007. cameraConfigs.settings = camera.pipelineSettings;
  1008. } else {
  1009. cameraConfigs.settings = defaultSettings;
  1010. }
  1011. }
  1012. }
  1013. _preparePipelinePasses(cameraConfigs) {
  1014. const passBuilders = this._passBuilders;
  1015. passBuilders.length = 0;
  1016. const settings = cameraConfigs.settings;
  1017. if (settings._passes) {
  1018. for (const pass of settings._passes) {
  1019. passBuilders.push(pass);
  1020. }
  1021. assert(passBuilders.length === settings._passes.length);
  1022. }
  1023. passBuilders.push(this._forwardPass);
  1024. if (settings.bloom.enabled) {
  1025. passBuilders.push(this._bloomPass);
  1026. }
  1027. passBuilders.push(this._toneMappingPass);
  1028. if (settings.fxaa.enabled) {
  1029. passBuilders.push(this._fxaaPass);
  1030. }
  1031. if (settings.fsr.enabled) {
  1032. passBuilders.push(this._fsrPass);
  1033. }
  1034. passBuilders.push(this._uiPass);
  1035. }
  1036. _setupBuiltinCameraConfigs(camera, pipelineConfigs, cameraConfigs) {
  1037. const window = camera.window;
  1038. const isMainGameWindow = camera.cameraUsage === CameraUsage.GAME && !!window.swapchain; // Window
  1039. cameraConfigs.isMainGameWindow = isMainGameWindow;
  1040. cameraConfigs.renderWindowId = window.renderWindowId; // Camera
  1041. cameraConfigs.colorName = window.colorName;
  1042. cameraConfigs.depthStencilName = window.depthStencilName; // Pipeline
  1043. cameraConfigs.enableFullPipeline = (camera.visibility & Layers.Enum.DEFAULT) !== 0;
  1044. cameraConfigs.enableProfiler = DEBUG && isMainGameWindow;
  1045. cameraConfigs.remainingPasses = 0; // Shading scale
  1046. cameraConfigs.shadingScale = cameraConfigs.settings.shadingScale;
  1047. cameraConfigs.enableShadingScale = cameraConfigs.settings.enableShadingScale && cameraConfigs.shadingScale !== 1.0;
  1048. cameraConfigs.nativeWidth = Math.max(Math.floor(window.width), 1);
  1049. cameraConfigs.nativeHeight = Math.max(Math.floor(window.height), 1);
  1050. cameraConfigs.width = cameraConfigs.enableShadingScale ? Math.max(Math.floor(cameraConfigs.nativeWidth * cameraConfigs.shadingScale), 1) : cameraConfigs.nativeWidth;
  1051. cameraConfigs.height = cameraConfigs.enableShadingScale ? Math.max(Math.floor(cameraConfigs.nativeHeight * cameraConfigs.shadingScale), 1) : cameraConfigs.nativeHeight; // Radiance
  1052. cameraConfigs.enableHDR = cameraConfigs.enableFullPipeline && pipelineConfigs.useFloatOutput;
  1053. cameraConfigs.radianceFormat = cameraConfigs.enableHDR ? gfx.Format.RGBA16F : gfx.Format.RGBA8; // Tone Mapping
  1054. cameraConfigs.copyAndTonemapMaterial = this._copyAndTonemapMaterial; // Depth
  1055. cameraConfigs.enableStoreSceneDepth = false;
  1056. }
  1057. _setupCameraConfigs(camera, pipelineConfigs, cameraConfigs) {
  1058. this._setupPipelinePreview(camera, cameraConfigs);
  1059. this._preparePipelinePasses(cameraConfigs);
  1060. sortPipelinePassBuildersByConfigOrder(this._passBuilders);
  1061. this._setupBuiltinCameraConfigs(camera, pipelineConfigs, cameraConfigs);
  1062. for (const builder of this._passBuilders) {
  1063. if (builder.configCamera) {
  1064. builder.configCamera(camera, pipelineConfigs, cameraConfigs);
  1065. }
  1066. }
  1067. } // ----------------------------------------------------------------
  1068. // Interface
  1069. // ----------------------------------------------------------------
  1070. windowResize(ppl, window, camera, nativeWidth, nativeHeight) {
  1071. setupPipelineConfigs(ppl, this._configs);
  1072. this._setupCameraConfigs(camera, this._configs, this._cameraConfigs); // Render Window (UI)
  1073. const id = window.renderWindowId;
  1074. ppl.addRenderWindow(this._cameraConfigs.colorName, Format.RGBA8, nativeWidth, nativeHeight, window, this._cameraConfigs.depthStencilName);
  1075. const width = this._cameraConfigs.width;
  1076. const height = this._cameraConfigs.height;
  1077. if (this._cameraConfigs.enableShadingScale) {
  1078. ppl.addDepthStencil(`ScaledSceneDepth_${id}`, Format.DEPTH_STENCIL, width, height);
  1079. ppl.addRenderTarget(`ScaledRadiance0_${id}`, this._cameraConfigs.radianceFormat, width, height);
  1080. ppl.addRenderTarget(`ScaledRadiance1_${id}`, this._cameraConfigs.radianceFormat, width, height);
  1081. ppl.addRenderTarget(`ScaledLdrColor0_${id}`, Format.RGBA8, width, height);
  1082. ppl.addRenderTarget(`ScaledLdrColor1_${id}`, Format.RGBA8, width, height);
  1083. } else {
  1084. ppl.addDepthStencil(`SceneDepth_${id}`, Format.DEPTH_STENCIL, width, height);
  1085. ppl.addRenderTarget(`Radiance0_${id}`, this._cameraConfigs.radianceFormat, width, height);
  1086. ppl.addRenderTarget(`Radiance1_${id}`, this._cameraConfigs.radianceFormat, width, height);
  1087. ppl.addRenderTarget(`LdrColor0_${id}`, Format.RGBA8, width, height);
  1088. ppl.addRenderTarget(`LdrColor1_${id}`, Format.RGBA8, width, height);
  1089. }
  1090. ppl.addRenderTarget(`UiColor0_${id}`, Format.RGBA8, nativeWidth, nativeHeight);
  1091. ppl.addRenderTarget(`UiColor1_${id}`, Format.RGBA8, nativeWidth, nativeHeight);
  1092. for (const builder of this._passBuilders) {
  1093. if (builder.windowResize) {
  1094. builder.windowResize(ppl, this._configs, this._cameraConfigs, window, camera, nativeWidth, nativeHeight);
  1095. }
  1096. }
  1097. }
  1098. setup(cameras, ppl) {
  1099. // TODO(zhouzhenglong): Make default effect asset loading earlier and remove _initMaterials
  1100. if (this._initMaterials(ppl)) {
  1101. return;
  1102. } // Render cameras
  1103. // log(`==================== One Frame ====================`);
  1104. for (const camera of cameras) {
  1105. // Skip invalid camera
  1106. if (!camera.scene || !camera.window) {
  1107. continue;
  1108. } // Setup camera configs
  1109. this._setupCameraConfigs(camera, this._configs, this._cameraConfigs); // log(`Setup camera: ${camera.node!.name}, window: ${camera.window.renderWindowId}, isFull: ${this._cameraConfigs.enableFullPipeline}, `
  1110. // + `size: ${camera.window.width}x${camera.window.height}`);
  1111. this._pipelineEvent.emit(PipelineEventType.RENDER_CAMERA_BEGIN, camera); // Build pipeline
  1112. if (this._cameraConfigs.enableFullPipeline) {
  1113. this._buildForwardPipeline(ppl, camera, camera.scene, this._passBuilders);
  1114. } else {
  1115. this._buildSimplePipeline(ppl, camera);
  1116. }
  1117. this._pipelineEvent.emit(PipelineEventType.RENDER_CAMERA_END, camera);
  1118. }
  1119. } // ----------------------------------------------------------------
  1120. // Pipelines
  1121. // ----------------------------------------------------------------
  1122. _buildSimplePipeline(ppl, camera) {
  1123. const width = Math.max(Math.floor(camera.window.width), 1);
  1124. const height = Math.max(Math.floor(camera.window.height), 1);
  1125. const colorName = this._cameraConfigs.colorName;
  1126. const depthStencilName = this._cameraConfigs.depthStencilName;
  1127. const viewport = camera.viewport; // Reduce C++/TS interop
  1128. this._viewport.left = Math.round(viewport.x * width);
  1129. this._viewport.top = Math.round(viewport.y * height); // Here we must use camera.viewport.width instead of camera.viewport.z, which
  1130. // is undefined on native platform. The same as camera.viewport.height.
  1131. this._viewport.width = Math.max(Math.round(viewport.width * width), 1);
  1132. this._viewport.height = Math.max(Math.round(viewport.height * height), 1);
  1133. const clearColor = camera.clearColor; // Reduce C++/TS interop
  1134. this._clearColor.x = clearColor.x;
  1135. this._clearColor.y = clearColor.y;
  1136. this._clearColor.z = clearColor.z;
  1137. this._clearColor.w = clearColor.w;
  1138. const pass = ppl.addRenderPass(width, height, 'default'); // bind output render target
  1139. if (forwardNeedClearColor(camera)) {
  1140. pass.addRenderTarget(colorName, LoadOp.CLEAR, StoreOp.STORE, this._clearColor);
  1141. } else {
  1142. pass.addRenderTarget(colorName, LoadOp.LOAD, StoreOp.STORE);
  1143. } // bind depth stencil buffer
  1144. if (camera.clearFlag & ClearFlagBit.DEPTH_STENCIL) {
  1145. pass.addDepthStencil(depthStencilName, LoadOp.CLEAR, StoreOp.DISCARD, camera.clearDepth, camera.clearStencil, camera.clearFlag & ClearFlagBit.DEPTH_STENCIL);
  1146. } else {
  1147. pass.addDepthStencil(depthStencilName, LoadOp.LOAD, StoreOp.DISCARD);
  1148. }
  1149. pass.setViewport(this._viewport); // The opaque queue is used for Reflection probe preview
  1150. pass.addQueue(QueueHint.OPAQUE).addScene(camera, SceneFlags.OPAQUE); // The blend queue is used for UI and Gizmos
  1151. let flags = SceneFlags.BLEND | SceneFlags.UI;
  1152. if (this._cameraConfigs.enableProfiler) {
  1153. flags |= SceneFlags.PROFILER;
  1154. pass.showStatistics = true;
  1155. }
  1156. pass.addQueue(QueueHint.BLEND).addScene(camera, flags);
  1157. }
  1158. _buildForwardPipeline(ppl, camera, scene, passBuilders) {
  1159. sortPipelinePassBuildersByRenderOrder(passBuilders);
  1160. const context = {
  1161. colorName: '',
  1162. depthStencilName: ''
  1163. };
  1164. let lastPass = undefined;
  1165. for (const builder of passBuilders) {
  1166. if (builder.setup) {
  1167. lastPass = builder.setup(ppl, this._configs, this._cameraConfigs, camera, context, lastPass);
  1168. }
  1169. }
  1170. assert(this._cameraConfigs.remainingPasses === 0);
  1171. }
  1172. _initMaterials(ppl) {
  1173. if (this._initialized) {
  1174. return 0;
  1175. }
  1176. setupPipelineConfigs(ppl, this._configs); // When add new effect asset, please add its uuid to the dependentAssets in cc.config.json.
  1177. this._copyAndTonemapMaterial._uuid = `builtin-pipeline-tone-mapping-material`;
  1178. this._copyAndTonemapMaterial.initialize({
  1179. effectName: 'pipeline/post-process/tone-mapping'
  1180. });
  1181. if (this._copyAndTonemapMaterial.effectAsset) {
  1182. this._initialized = true;
  1183. }
  1184. return this._initialized ? 0 : 1;
  1185. }
  1186. }
  1187. rendering.setCustomPipeline('Builtin', new BuiltinPipelineBuilder());
  1188. } // if (rendering)
  1189. _cclegacy._RF.pop();
  1190. _crd = false;
  1191. }
  1192. };
  1193. });
  1194. //# sourceMappingURL=f3f54528bfcd10077eb00a2121ed5d1424412e76.js.map