UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

665 lines (662 loc) 29.8 kB
import { now } from '../../core/time.js'; import { Vec3 } from '../../core/math/vec3.js'; import { Color } from '../../core/math/color.js'; import { LIGHTSHAPE_PUNCTUAL, LIGHTTYPE_OMNI, LIGHTTYPE_SPOT, LIGHTTYPE_DIRECTIONAL, FOG_NONE, FOG_LINEAR, LAYERID_DEPTH } from '../constants.js'; import { Renderer } from './renderer.js'; import { LightCamera } from './light-camera.js'; import { RenderPassForward } from './render-pass-forward.js'; import { RenderPassPostprocessing } from './render-pass-postprocessing.js'; var _noLights = [ [], [], [] ]; var tmpColor = new Color(); var _drawCallList = { drawCalls: [], shaderInstances: [], isNewMaterial: [], lightMaskChanged: [], clear: function clear() { this.drawCalls.length = 0; this.shaderInstances.length = 0; this.isNewMaterial.length = 0; this.lightMaskChanged.length = 0; } }; function vogelDiskPrecalculationSamples(numSamples) { var samples = []; for(var i = 0; i < numSamples; ++i){ var r = Math.sqrt(i + 0.5) / Math.sqrt(numSamples); samples.push(r); } return samples; } function vogelSpherePrecalculationSamples(numSamples) { var samples = []; for(var i = 0; i < numSamples; i++){ var weight = i / numSamples; var radius = Math.sqrt(weight * weight); samples.push(radius); } return samples; } class ForwardRenderer extends Renderer { destroy() { super.destroy(); } dispatchGlobalLights(scene) { var ambientUniform = this.ambientColor; tmpColor.linear(scene.ambientLight); ambientUniform[0] = tmpColor.r; ambientUniform[1] = tmpColor.g; ambientUniform[2] = tmpColor.b; if (scene.physicalUnits) { for(var i = 0; i < 3; i++){ ambientUniform[i] *= scene.ambientLuminance; } } this.ambientId.setValue(ambientUniform); this.skyboxIntensityId.setValue(scene.physicalUnits ? scene.skyboxLuminance : scene.skyboxIntensity); this.cubeMapRotationMatrixId.setValue(scene._skyboxRotationMat3.data); } _resolveLight(scope, i) { var light = "light" + i; this.lightColorId[i] = scope.resolve("" + light + "_color"); this.lightDir[i] = new Float32Array(3); this.lightDirId[i] = scope.resolve("" + light + "_direction"); this.lightShadowMapId[i] = scope.resolve("" + light + "_shadowMap"); this.lightShadowMatrixId[i] = scope.resolve("" + light + "_shadowMatrix"); this.lightShadowParamsId[i] = scope.resolve("" + light + "_shadowParams"); this.lightShadowIntensity[i] = scope.resolve("" + light + "_shadowIntensity"); this.lightShadowSearchAreaId[i] = scope.resolve("" + light + "_shadowSearchArea"); this.lightRadiusId[i] = scope.resolve("" + light + "_radius"); this.lightPos[i] = new Float32Array(3); this.lightPosId[i] = scope.resolve("" + light + "_position"); this.lightWidth[i] = new Float32Array(3); this.lightWidthId[i] = scope.resolve("" + light + "_halfWidth"); this.lightHeight[i] = new Float32Array(3); this.lightHeightId[i] = scope.resolve("" + light + "_halfHeight"); this.lightInAngleId[i] = scope.resolve("" + light + "_innerConeAngle"); this.lightOutAngleId[i] = scope.resolve("" + light + "_outerConeAngle"); this.lightCookieId[i] = scope.resolve("" + light + "_cookie"); this.lightCookieIntId[i] = scope.resolve("" + light + "_cookieIntensity"); this.lightCookieMatrixId[i] = scope.resolve("" + light + "_cookieMatrix"); this.lightCookieOffsetId[i] = scope.resolve("" + light + "_cookieOffset"); this.lightCameraParamsId[i] = scope.resolve("" + light + "_cameraParams"); this.lightSoftShadowParamsId[i] = scope.resolve("" + light + "_softShadowParams"); this.shadowMatrixPaletteId[i] = scope.resolve("" + light + "_shadowMatrixPalette[0]"); this.shadowCascadeDistancesId[i] = scope.resolve("" + light + "_shadowCascadeDistances"); this.shadowCascadeCountId[i] = scope.resolve("" + light + "_shadowCascadeCount"); this.shadowCascadeBlendId[i] = scope.resolve("" + light + "_shadowCascadeBlend"); } setLTCDirectionalLight(wtm, cnt, dir, campos, far) { this.lightPos[cnt][0] = campos.x - dir.x * far; this.lightPos[cnt][1] = campos.y - dir.y * far; this.lightPos[cnt][2] = campos.z - dir.z * far; this.lightPosId[cnt].setValue(this.lightPos[cnt]); var hWidth = wtm.transformVector(new Vec3(-0.5, 0, 0)); this.lightWidth[cnt][0] = hWidth.x * far; this.lightWidth[cnt][1] = hWidth.y * far; this.lightWidth[cnt][2] = hWidth.z * far; this.lightWidthId[cnt].setValue(this.lightWidth[cnt]); var hHeight = wtm.transformVector(new Vec3(0, 0, 0.5)); this.lightHeight[cnt][0] = hHeight.x * far; this.lightHeight[cnt][1] = hHeight.y * far; this.lightHeight[cnt][2] = hHeight.z * far; this.lightHeightId[cnt].setValue(this.lightHeight[cnt]); } dispatchDirectLights(dirs, mask, camera) { var cnt = 0; var scope = this.device.scope; for(var i = 0; i < dirs.length; i++){ if (!(dirs[i].mask & mask)) continue; var directional = dirs[i]; var wtm = directional._node.getWorldTransform(); if (!this.lightColorId[cnt]) { this._resolveLight(scope, cnt); } this.lightColorId[cnt].setValue(directional._colorLinear); wtm.getY(directional._direction).mulScalar(-1); directional._direction.normalize(); this.lightDir[cnt][0] = directional._direction.x; this.lightDir[cnt][1] = directional._direction.y; this.lightDir[cnt][2] = directional._direction.z; this.lightDirId[cnt].setValue(this.lightDir[cnt]); if (directional.shape !== LIGHTSHAPE_PUNCTUAL) { this.setLTCDirectionalLight(wtm, cnt, directional._direction, camera._node.getPosition(), camera.farClip); } if (directional.castShadows) { var lightRenderData = directional.getRenderData(camera, 0); var biases = directional._getUniformBiasValues(lightRenderData); this.lightShadowMapId[cnt].setValue(lightRenderData.shadowBuffer); this.lightShadowMatrixId[cnt].setValue(lightRenderData.shadowMatrix.data); this.shadowMatrixPaletteId[cnt].setValue(directional._shadowMatrixPalette); this.shadowCascadeDistancesId[cnt].setValue(directional._shadowCascadeDistances); this.shadowCascadeCountId[cnt].setValue(directional.numCascades); this.shadowCascadeBlendId[cnt].setValue(1 - directional.cascadeBlend); this.lightShadowIntensity[cnt].setValue(directional.shadowIntensity); this.lightSoftShadowParamsId[cnt].setValue(directional._softShadowParams); var shadowRT = lightRenderData.shadowCamera.renderTarget; if (shadowRT) { this.lightShadowSearchAreaId[cnt].setValue(directional.penumbraSize / lightRenderData.shadowCamera.renderTarget.width * lightRenderData.projectionCompensation); } var cameraParams = directional._shadowCameraParams; cameraParams.length = 4; cameraParams[0] = 0; cameraParams[1] = lightRenderData.shadowCamera._farClip; cameraParams[2] = lightRenderData.shadowCamera._nearClip; cameraParams[3] = 1; this.lightCameraParamsId[cnt].setValue(cameraParams); var params = directional._shadowRenderParams; params.length = 4; params[0] = directional._shadowResolution; params[1] = biases.normalBias; params[2] = biases.bias; params[3] = 0; this.lightShadowParamsId[cnt].setValue(params); } cnt++; } return cnt; } setLTCPositionalLight(wtm, cnt) { var hWidth = wtm.transformVector(new Vec3(-0.5, 0, 0)); this.lightWidth[cnt][0] = hWidth.x; this.lightWidth[cnt][1] = hWidth.y; this.lightWidth[cnt][2] = hWidth.z; this.lightWidthId[cnt].setValue(this.lightWidth[cnt]); var hHeight = wtm.transformVector(new Vec3(0, 0, 0.5)); this.lightHeight[cnt][0] = hHeight.x; this.lightHeight[cnt][1] = hHeight.y; this.lightHeight[cnt][2] = hHeight.z; this.lightHeightId[cnt].setValue(this.lightHeight[cnt]); } dispatchOmniLight(scope, omni, cnt) { var wtm = omni._node.getWorldTransform(); if (!this.lightColorId[cnt]) { this._resolveLight(scope, cnt); } this.lightRadiusId[cnt].setValue(omni.attenuationEnd); this.lightColorId[cnt].setValue(omni._colorLinear); wtm.getTranslation(omni._position); this.lightPos[cnt][0] = omni._position.x; this.lightPos[cnt][1] = omni._position.y; this.lightPos[cnt][2] = omni._position.z; this.lightPosId[cnt].setValue(this.lightPos[cnt]); if (omni.shape !== LIGHTSHAPE_PUNCTUAL) { this.setLTCPositionalLight(wtm, cnt); } if (omni.castShadows) { var lightRenderData = omni.getRenderData(null, 0); this.lightShadowMapId[cnt].setValue(lightRenderData.shadowBuffer); var biases = omni._getUniformBiasValues(lightRenderData); var params = omni._shadowRenderParams; params.length = 4; params[0] = omni._shadowResolution; params[1] = biases.normalBias; params[2] = biases.bias; params[3] = 1.0 / omni.attenuationEnd; this.lightShadowParamsId[cnt].setValue(params); this.lightShadowIntensity[cnt].setValue(omni.shadowIntensity); var pixelsPerMeter = omni.penumbraSize / lightRenderData.shadowCamera.renderTarget.width; this.lightShadowSearchAreaId[cnt].setValue(pixelsPerMeter); var cameraParams = omni._shadowCameraParams; cameraParams.length = 4; cameraParams[0] = 0; cameraParams[1] = lightRenderData.shadowCamera._farClip; cameraParams[2] = lightRenderData.shadowCamera._nearClip; cameraParams[3] = 0; this.lightCameraParamsId[cnt].setValue(cameraParams); } if (omni._cookie) { this.lightCookieId[cnt].setValue(omni._cookie); this.lightShadowMatrixId[cnt].setValue(wtm.data); this.lightCookieIntId[cnt].setValue(omni.cookieIntensity); } } dispatchSpotLight(scope, spot, cnt) { var wtm = spot._node.getWorldTransform(); if (!this.lightColorId[cnt]) { this._resolveLight(scope, cnt); } this.lightInAngleId[cnt].setValue(spot._innerConeAngleCos); this.lightOutAngleId[cnt].setValue(spot._outerConeAngleCos); this.lightRadiusId[cnt].setValue(spot.attenuationEnd); this.lightColorId[cnt].setValue(spot._colorLinear); wtm.getTranslation(spot._position); this.lightPos[cnt][0] = spot._position.x; this.lightPos[cnt][1] = spot._position.y; this.lightPos[cnt][2] = spot._position.z; this.lightPosId[cnt].setValue(this.lightPos[cnt]); if (spot.shape !== LIGHTSHAPE_PUNCTUAL) { this.setLTCPositionalLight(wtm, cnt); } wtm.getY(spot._direction).mulScalar(-1); spot._direction.normalize(); this.lightDir[cnt][0] = spot._direction.x; this.lightDir[cnt][1] = spot._direction.y; this.lightDir[cnt][2] = spot._direction.z; this.lightDirId[cnt].setValue(this.lightDir[cnt]); if (spot.castShadows) { var lightRenderData = spot.getRenderData(null, 0); this.lightShadowMapId[cnt].setValue(lightRenderData.shadowBuffer); this.lightShadowMatrixId[cnt].setValue(lightRenderData.shadowMatrix.data); var biases = spot._getUniformBiasValues(lightRenderData); var params = spot._shadowRenderParams; params.length = 4; params[0] = spot._shadowResolution; params[1] = biases.normalBias; params[2] = biases.bias; params[3] = 1.0 / spot.attenuationEnd; this.lightShadowParamsId[cnt].setValue(params); this.lightShadowIntensity[cnt].setValue(spot.shadowIntensity); var pixelsPerMeter = spot.penumbraSize / lightRenderData.shadowCamera.renderTarget.width; var fov = lightRenderData.shadowCamera._fov * Math.PI / 180.0; var fovRatio = 1.0 / Math.tan(fov / 2.0); this.lightShadowSearchAreaId[cnt].setValue(pixelsPerMeter * fovRatio); var cameraParams = spot._shadowCameraParams; cameraParams.length = 4; cameraParams[0] = 0; cameraParams[1] = lightRenderData.shadowCamera._farClip; cameraParams[2] = lightRenderData.shadowCamera._nearClip; cameraParams[3] = 0; this.lightCameraParamsId[cnt].setValue(cameraParams); } if (spot._cookie) { if (!spot.castShadows) { var cookieMatrix = LightCamera.evalSpotCookieMatrix(spot); this.lightShadowMatrixId[cnt].setValue(cookieMatrix.data); } this.lightCookieId[cnt].setValue(spot._cookie); this.lightCookieIntId[cnt].setValue(spot.cookieIntensity); if (spot._cookieTransform) { spot._cookieTransformUniform[0] = spot._cookieTransform.x; spot._cookieTransformUniform[1] = spot._cookieTransform.y; spot._cookieTransformUniform[2] = spot._cookieTransform.z; spot._cookieTransformUniform[3] = spot._cookieTransform.w; this.lightCookieMatrixId[cnt].setValue(spot._cookieTransformUniform); spot._cookieOffsetUniform[0] = spot._cookieOffset.x; spot._cookieOffsetUniform[1] = spot._cookieOffset.y; this.lightCookieOffsetId[cnt].setValue(spot._cookieOffsetUniform); } } } dispatchLocalLights(sortedLights, mask, usedDirLights) { var cnt = usedDirLights; var scope = this.device.scope; var omnis = sortedLights[LIGHTTYPE_OMNI]; var numOmnis = omnis.length; for(var i = 0; i < numOmnis; i++){ var omni = omnis[i]; if (!(omni.mask & mask)) continue; this.dispatchOmniLight(scope, omni, cnt); cnt++; } var spts = sortedLights[LIGHTTYPE_SPOT]; var numSpts = spts.length; for(var i1 = 0; i1 < numSpts; i1++){ var spot = spts[i1]; if (!(spot.mask & mask)) continue; this.dispatchSpotLight(scope, spot, cnt); cnt++; } } renderForwardPrepareMaterials(camera, renderTarget, drawCalls, sortedLights, layer, pass) { var _camera_fog; var fogParams = (_camera_fog = camera.fog) != null ? _camera_fog : this.scene.fog; var shaderParams = camera.shaderParams; shaderParams.fog = fogParams.type; var _renderTarget_isColorBufferSrgb; shaderParams.srgbRenderTarget = (_renderTarget_isColorBufferSrgb = renderTarget == null ? void 0 : renderTarget.isColorBufferSrgb(0)) != null ? _renderTarget_isColorBufferSrgb : false; var addCall = (drawCall, shaderInstance, isNewMaterial, lightMaskChanged)=>{ _drawCallList.drawCalls.push(drawCall); _drawCallList.shaderInstances.push(shaderInstance); _drawCallList.isNewMaterial.push(isNewMaterial); _drawCallList.lightMaskChanged.push(lightMaskChanged); }; _drawCallList.clear(); var device = this.device; var scene = this.scene; var clusteredLightingEnabled = scene.clusteredLightingEnabled; var _layer_getLightHash; var lightHash = (_layer_getLightHash = layer == null ? void 0 : layer.getLightHash(clusteredLightingEnabled)) != null ? _layer_getLightHash : 0; var prevMaterial = null, prevObjDefs, prevLightMask; var drawCallsCount = drawCalls.length; for(var i = 0; i < drawCallsCount; i++){ var drawCall = drawCalls[i]; if (camera === ForwardRenderer.skipRenderCamera) { if (ForwardRenderer._skipRenderCounter >= ForwardRenderer.skipRenderAfter) { continue; } ForwardRenderer._skipRenderCounter++; } if (layer) { if (layer._skipRenderCounter >= layer.skipRenderAfter) { continue; } layer._skipRenderCounter++; } drawCall.ensureMaterial(device); var material = drawCall.material; var objDefs = drawCall._shaderDefs; var lightMask = drawCall.mask; if (material && material === prevMaterial && objDefs !== prevObjDefs) { prevMaterial = null; } if (material !== prevMaterial) { this._materialSwitches++; material._scene = scene; if (material.dirty) { material.updateUniforms(device, scene); material.dirty = false; } } var shaderInstance = drawCall.getShaderInstance(pass, lightHash, scene, shaderParams, this.viewUniformFormat, this.viewBindGroupFormat, sortedLights); addCall(drawCall, shaderInstance, material !== prevMaterial, !prevMaterial || lightMask !== prevLightMask); prevMaterial = material; prevObjDefs = objDefs; prevLightMask = lightMask; } return _drawCallList; } renderForwardInternal(camera, preparedCalls, sortedLights, pass, drawCallback, flipFaces) { var device = this.device; var scene = this.scene; var passFlag = 1 << pass; var flipFactor = flipFaces ? -1 : 1; var clusteredLightingEnabled = scene.clusteredLightingEnabled; var preparedCallsCount = preparedCalls.drawCalls.length; for(var i = 0; i < preparedCallsCount; i++){ var drawCall = preparedCalls.drawCalls[i]; var newMaterial = preparedCalls.isNewMaterial[i]; var lightMaskChanged = preparedCalls.lightMaskChanged[i]; var shaderInstance = preparedCalls.shaderInstances[i]; var material = drawCall.material; var lightMask = drawCall.mask; if (newMaterial) { var asyncCompile = false; device.setShader(shaderInstance.shader, asyncCompile); material.setParameters(device); if (lightMaskChanged) { var usedDirLights = this.dispatchDirectLights(sortedLights[LIGHTTYPE_DIRECTIONAL], lightMask, camera); if (!clusteredLightingEnabled) { this.dispatchLocalLights(sortedLights, lightMask, usedDirLights); } } this.alphaTestId.setValue(material.alphaTest); device.setBlendState(material.blendState); device.setDepthState(material.depthState); device.setAlphaToCoverage(material.alphaToCoverage); } this.setupCullMode(camera._cullFaces, flipFactor, drawCall); var _drawCall_stencilFront; var stencilFront = (_drawCall_stencilFront = drawCall.stencilFront) != null ? _drawCall_stencilFront : material.stencilFront; var _drawCall_stencilBack; var stencilBack = (_drawCall_stencilBack = drawCall.stencilBack) != null ? _drawCall_stencilBack : material.stencilBack; device.setStencilState(stencilFront, stencilBack); drawCall.setParameters(device, passFlag); device.scope.resolve('meshInstanceId').setValue(drawCall.id); var mesh = drawCall.mesh; this.setVertexBuffers(device, mesh); this.setMorphing(device, drawCall.morphInstance); this.setSkinning(device, drawCall); this.setupMeshUniformBuffers(shaderInstance, drawCall); var style = drawCall.renderStyle; device.setIndexBuffer(mesh.indexBuffer[style]); drawCallback == null ? void 0 : drawCallback(drawCall, i); if (camera.xr && camera.xr.session && camera.xr.views.list.length) { var views = camera.xr.views; for(var v = 0; v < views.list.length; v++){ var view = views.list[v]; device.setViewport(view.viewport.x, view.viewport.y, view.viewport.z, view.viewport.w); this.projId.setValue(view.projMat.data); this.projSkyboxId.setValue(view.projMat.data); this.viewId.setValue(view.viewOffMat.data); this.viewInvId.setValue(view.viewInvOffMat.data); this.viewId3.setValue(view.viewMat3.data); this.viewProjId.setValue(view.projViewOffMat.data); this.viewPosId.setValue(view.positionData); this.viewIndexId.setValue(v); if (v === 0) { this.drawInstance(device, drawCall, mesh, style, true); } else { this.drawInstance2(device, drawCall, mesh, style); } this._forwardDrawCalls++; } } else { this.drawInstance(device, drawCall, mesh, style, true); this._forwardDrawCalls++; } if (i < preparedCallsCount - 1 && !preparedCalls.isNewMaterial[i + 1]) { material.setParameters(device, drawCall.parameters); } } } renderForward(camera, renderTarget, allDrawCalls, sortedLights, pass, drawCallback, layer, flipFaces) { var forwardStartTime = now(); var preparedCalls = this.renderForwardPrepareMaterials(camera, renderTarget, allDrawCalls, sortedLights, layer, pass); this.renderForwardInternal(camera, preparedCalls, sortedLights, pass, drawCallback, flipFaces); _drawCallList.clear(); this._forwardTime += now() - forwardStartTime; } renderForwardLayer(camera, renderTarget, layer, transparent, shaderPass, viewBindGroups, options) { if (options === void 0) options = {}; var { scene, device } = this; var clusteredLightingEnabled = scene.clusteredLightingEnabled; this.setupViewport(camera, renderTarget); var visible, splitLights; if (layer) { var sortTime = now(); layer.sortVisible(camera, transparent); this._sortTime += now() - sortTime; var culledInstances = layer.getCulledInstances(camera); visible = transparent ? culledInstances.transparent : culledInstances.opaque; scene.immediate.onPreRenderLayer(layer, visible, transparent); if (layer.requiresLightCube) { this.lightCube.update(scene.ambientLight, layer._lights); this.constantLightCube.setValue(this.lightCube.colors); } splitLights = layer.splitLights; } else { visible = options.meshInstances; var _options_splitLights; splitLights = (_options_splitLights = options.splitLights) != null ? _options_splitLights : _noLights; } if (clusteredLightingEnabled) { var _options_lightClusters; var lightClusters = (_options_lightClusters = options.lightClusters) != null ? _options_lightClusters : this.worldClustersAllocator.empty; lightClusters.activate(); if (layer) { if (!this.clustersDebugRendered && scene.lighting.debugLayer === layer.id) { this.clustersDebugRendered = true; } } } scene._activeCamera = camera; var _camera_fog; var fogParams = (_camera_fog = camera.fog) != null ? _camera_fog : this.scene.fog; this.setFogConstants(fogParams); var viewCount = this.setCameraUniforms(camera, renderTarget); if (device.supportsUniformBuffers) { this.setupViewUniformBuffers(viewBindGroups, this.viewUniformFormat, this.viewBindGroupFormat, viewCount); } var _options_clearColor; var clearColor = (_options_clearColor = options.clearColor) != null ? _options_clearColor : false; var _options_clearDepth; var clearDepth = (_options_clearDepth = options.clearDepth) != null ? _options_clearDepth : false; var _options_clearStencil; var clearStencil = (_options_clearStencil = options.clearStencil) != null ? _options_clearStencil : false; if (clearColor || clearDepth || clearStencil) { this.clear(camera, clearColor, clearDepth, clearStencil); } var flipFaces = !!(camera._flipFaces ^ (renderTarget == null ? void 0 : renderTarget.flipY)); var forwardDrawCalls = this._forwardDrawCalls; this.renderForward(camera, renderTarget, visible, splitLights, shaderPass, null, layer, flipFaces); if (layer) { layer._forwardDrawCalls += this._forwardDrawCalls - forwardDrawCalls; } } setFogConstants(fogParams) { if (fogParams.type !== FOG_NONE) { tmpColor.linear(fogParams.color); var fogUniform = this.fogColor; fogUniform[0] = tmpColor.r; fogUniform[1] = tmpColor.g; fogUniform[2] = tmpColor.b; this.fogColorId.setValue(fogUniform); if (fogParams.type === FOG_LINEAR) { this.fogStartId.setValue(fogParams.start); this.fogEndId.setValue(fogParams.end); } else { this.fogDensityId.setValue(fogParams.density); } } } setSceneConstants() { var scene = this.scene; this.dispatchGlobalLights(scene); var device = this.device; this._screenSize[0] = device.width; this._screenSize[1] = device.height; this._screenSize[2] = 1 / device.width; this._screenSize[3] = 1 / device.height; this.screenSizeId.setValue(this._screenSize); this.pcssDiskSamplesId.setValue(this.pcssDiskSamples); this.pcssSphereSamplesId.setValue(this.pcssSphereSamples); } buildFrameGraph(frameGraph, layerComposition) { var scene = this.scene; frameGraph.reset(); if (scene.clusteredLightingEnabled) { var { shadowsEnabled, cookiesEnabled } = scene.lighting; this._renderPassUpdateClustered.update(frameGraph, shadowsEnabled, cookiesEnabled, this.lights, this.localLights); frameGraph.addRenderPass(this._renderPassUpdateClustered); } else { this._shadowRendererLocal.buildNonClusteredRenderPasses(frameGraph, this.localLights); } var startIndex = 0; var newStart = true; var renderTarget = null; var renderActions = layerComposition._renderActions; for(var i = startIndex; i < renderActions.length; i++){ var renderAction = renderActions[i]; var { layer, camera } = renderAction; if (renderAction.useCameraPasses) { camera.camera.renderPasses.forEach((renderPass)=>{ frameGraph.addRenderPass(renderPass); }); } else { var isDepthLayer = layer.id === LAYERID_DEPTH; var isGrabPass = isDepthLayer && (camera.renderSceneColorMap || camera.renderSceneDepthMap); if (newStart) { newStart = false; startIndex = i; renderTarget = renderAction.renderTarget; } var nextRenderAction = renderActions[i + 1]; var isNextLayerDepth = nextRenderAction ? !nextRenderAction.useCameraPasses && nextRenderAction.layer.id === LAYERID_DEPTH : false; var isNextLayerGrabPass = isNextLayerDepth && (camera.renderSceneColorMap || camera.renderSceneDepthMap); var nextNeedDirShadows = nextRenderAction ? nextRenderAction.firstCameraUse && this.cameraDirShadowLights.has(nextRenderAction.camera.camera) : false; if (!nextRenderAction || nextRenderAction.renderTarget !== renderTarget || nextNeedDirShadows || isNextLayerGrabPass || isGrabPass) { var isDepthOnly = isDepthLayer && startIndex === i; if (!isDepthOnly) { this.addMainRenderPass(frameGraph, layerComposition, renderTarget, startIndex, i); } if (isDepthLayer) { if (camera.renderSceneColorMap) { var colorGrabPass = camera.camera.renderPassColorGrab; colorGrabPass.source = camera.renderTarget; frameGraph.addRenderPass(colorGrabPass); } if (camera.renderSceneDepthMap) { frameGraph.addRenderPass(camera.camera.renderPassDepthGrab); } } if (renderAction.triggerPostprocess && (camera == null ? void 0 : camera.onPostprocessing)) { var renderPass = new RenderPassPostprocessing(this.device, this, renderAction); frameGraph.addRenderPass(renderPass); } newStart = true; } } } } addMainRenderPass(frameGraph, layerComposition, renderTarget, startIndex, endIndex) { var renderPass = new RenderPassForward(this.device, layerComposition, this.scene, this); renderPass.init(renderTarget); var renderActions = layerComposition._renderActions; for(var i = startIndex; i <= endIndex; i++){ renderPass.addRenderAction(renderActions[i]); } frameGraph.addRenderPass(renderPass); } update(comp) { this.frameUpdate(); this.shadowRenderer.frameUpdate(); this.scene._updateSkyMesh(); this.updateLayerComposition(comp); this.collectLights(comp); this.beginFrame(comp); this.setSceneConstants(); this.cullComposition(comp); this.gpuUpdate(this.processingMeshInstances); } constructor(graphicsDevice){ super(graphicsDevice); var device = this.device; this._forwardDrawCalls = 0; this._materialSwitches = 0; this._depthMapTime = 0; this._forwardTime = 0; this._sortTime = 0; var scope = device.scope; this.fogColorId = scope.resolve('fog_color'); this.fogStartId = scope.resolve('fog_start'); this.fogEndId = scope.resolve('fog_end'); this.fogDensityId = scope.resolve('fog_density'); this.ambientId = scope.resolve('light_globalAmbient'); this.skyboxIntensityId = scope.resolve('skyboxIntensity'); this.cubeMapRotationMatrixId = scope.resolve('cubeMapRotationMatrix'); this.pcssDiskSamplesId = scope.resolve('pcssDiskSamples[0]'); this.pcssSphereSamplesId = scope.resolve('pcssSphereSamples[0]'); this.lightColorId = []; this.lightDir = []; this.lightDirId = []; this.lightShadowMapId = []; this.lightShadowMatrixId = []; this.lightShadowParamsId = []; this.lightShadowIntensity = []; this.lightRadiusId = []; this.lightPos = []; this.lightPosId = []; this.lightWidth = []; this.lightWidthId = []; this.lightHeight = []; this.lightHeightId = []; this.lightInAngleId = []; this.lightOutAngleId = []; this.lightCookieId = []; this.lightCookieIntId = []; this.lightCookieMatrixId = []; this.lightCookieOffsetId = []; this.lightShadowSearchAreaId = []; this.lightCameraParamsId = []; this.lightSoftShadowParamsId = []; this.shadowMatrixPaletteId = []; this.shadowCascadeDistancesId = []; this.shadowCascadeCountId = []; this.shadowCascadeBlendId = []; this.screenSizeId = scope.resolve('uScreenSize'); this._screenSize = new Float32Array(4); this.fogColor = new Float32Array(3); this.ambientColor = new Float32Array(3); this.pcssDiskSamples = vogelDiskPrecalculationSamples(16); this.pcssSphereSamples = vogelSpherePrecalculationSamples(16); } } ForwardRenderer.skipRenderCamera = null; ForwardRenderer._skipRenderCounter = 0; ForwardRenderer.skipRenderAfter = 0; export { ForwardRenderer };