private void OnPreRender() { RenderTexture _rawOcclusionMask; using (new DisposableProfiler("1. Occlusion Mask Render (No Gfx Time)")) { _rawOcclusionMask = mOcclusionMaskRenderer.Render(); } using (new DisposableProfiler("2. Generate FoV")) { // Note: Next steps will result in Two masks: Generated "Extended Occlusion Mask" will be stored for later use in Light Mixing, // and second "Fit Occlusion Mask" will be created next and used during scene rendering. Vector3 _fovCenterInWorldSpace = transform.TransformPoint(fovCenterOffset); Vector3 _fovCenterOffsetInViewSpace = mMainCamera.WorldToViewportPoint(_fovCenterInWorldSpace) - new Vector3(0.5f, 0.5f, 0); Vector3 _fovCenterOffsetInExtendedViewSpace = _fovCenterOffsetInViewSpace * (float)mCurrentMaskParameters.cameraOrthographicSize / mCurrentMaskParameters.extendedCameraSize; mPostProcessingStack.GenerateFovMask(_rawOcclusionMask, occlusionMaskExtended, renderSettings, _fovCenterOffsetInExtendedViewSpace, fovDistance, mCurrentMaskParameters); } using (new DisposableProfiler("3. Fit Occlusion Mask")) { // Note: Fit Occlusion Mask is cut from "Extended Occlusion Mask" to be used in Occlusion affected shaders during scene render. mPostProcessingStack.FitExtendedOcclusionMask(occlusionMaskExtended, globalOcclusionMask, mCurrentMaskParameters); } using (new DisposableProfiler("4. Blur Fit Occlusion Mask")) { // Note: This blur is used only with shaders during scene render, so 1 pass should be enough. mPostProcessingStack.BlurOcclusionMask(globalOcclusionMask, renderSettings, mCurrentMaskParameters.cameraOrthographicSize); } // Note: After execution of this method, MainCamera.Render will be executed and scene will be drawn. }
private void OnPreRender() { if (renderSettings.doubleFrameRenderingMode && mDoubleFrameRendererSwitch == false) { Shader.SetGlobalVector("_FovMaskTransformation", globalOcclusionMask.GetTransformation(mMainCamera)); return; } using (new DisposableProfiler("1. Occlusion Mask Render (No Gfx Time)")) { mOcclusionPPRT = mOcclusionRenderer.Render(mMainCamera, operationParameters.occlusionPPRTParameter, matrixRotationMode); if (mMatrixRotationModeBlend > 0.001f) { mPostProcessingStack.BlurOcclusionMaskRotation(mOcclusionPPRT.renderTexture, renderSettings, operationParameters.cameraOrthographicSize, mMatrixRotationModeBlend); } } using (new DisposableProfiler("2. Generate FoV")) { if (occlusionMaskExtended == null) { occlusionMaskExtended = new PixelPerfectRT(operationParameters.fovPPRTParameter); } else { occlusionMaskExtended.Update(operationParameters.fovPPRTParameter); } // Note: Next steps will result in Two masks: Generated "Extended Occlusion Mask" will be stored for later use in Light Mixing, // and second "Fit Occlusion Mask" will be created next and used during scene rendering. Vector3 _fovCenterInWorldSpace = transform.TransformPoint(fovCenterOffset); Vector3 _fovCenterOffsetInViewSpace = mMainCamera.WorldToViewportPoint(_fovCenterInWorldSpace) - new Vector3(0.5f, 0.5f, 0); Vector3 _fovCenterOffsetInExtendedViewSpace = _fovCenterOffsetInViewSpace * (float)operationParameters.cameraOrthographicSize / mOcclusionPPRT.orthographicSize; mPostProcessingStack.GenerateFovMask(mOcclusionPPRT, occlusionMaskExtended, renderSettings, _fovCenterOffsetInExtendedViewSpace, fovDistance, operationParameters); } using (new DisposableProfiler("3. Fit Occlusion Mask")) { globalOcclusionMask.Update(operationParameters.lightPPRTParameter); // Note: Fit Occlusion Mask is cut from "Extended Occlusion Mask" to be used in Occlusion affected shaders during scene render. PixelPerfectRT.Transform(occlusionMaskExtended, globalOcclusionMask, materialContainer.PPRTTransformMaterial); // Update shader global transformation for occlusionMaskExtended so sprites can transform mask correctly. Shader.SetGlobalVector("_FovMaskTransformation", globalOcclusionMask.GetTransformation(mMainCamera)); } using (new DisposableProfiler("4. Blur Fit Occlusion Mask")) { // Note: This blur is used only with shaders during scene render, so 1 pass should be enough. mPostProcessingStack.BlurOcclusionMask(globalOcclusionMask.renderTexture, renderSettings, operationParameters.cameraOrthographicSize); globalOcclusionMask.renderTexture.filterMode = FilterMode.Point; } // Note: After execution of this method, MainCamera.Render will be executed and scene will be drawn. }
private void OnPreRender() { if (renderSettings.doubleFrameRenderingMode && mDoubleFrameRendererSwitch == false) { Shader.SetGlobalVector("_ObjectFovMaskTransformation", objectOcclusionMask.GetTransformation(mMainCamera)); return; } using (new DisposableProfiler("1. Occlusion Mask Render (No Gfx Time)")) { mOcclusionPPRT = mOcclusionRenderer.Render(mMainCamera, operationParameters.occlusionPPRTParameter, matrixRotationMode); if (mMatrixRotationModeBlend > 0.001f) { mPostProcessingStack.BlurOcclusionMaskRotation(mOcclusionPPRT.renderTexture, renderSettings, operationParameters.cameraOrthographicSize, mMatrixRotationModeBlend); } } using (new DisposableProfiler("2. Generate FoV")) { if (wallFloorOcclusionMask == null) { floorOcclusionMask = new PixelPerfectRT(operationParameters.fovPPRTParameter); wallFloorOcclusionMask = new PixelPerfectRT(operationParameters.fovPPRTParameter); } else { floorOcclusionMask.Update(operationParameters.fovPPRTParameter); wallFloorOcclusionMask.Update(operationParameters.fovPPRTParameter); } // This step will result in two masks: floorOcclusionMask used later in light mixing, and floorWallOcclusionMask which is only used for calculating // objects / wallmounts sprite visibility. Vector3 _fovCenterInWorldSpace = transform.TransformPoint(fovCenterOffset); Vector3 _fovCenterOffsetInViewSpace = mMainCamera.WorldToViewportPoint(_fovCenterInWorldSpace) - new Vector3(0.5f, 0.5f, 0); Vector3 _fovCenterOffsetInExtendedViewSpace = _fovCenterOffsetInViewSpace * (float)operationParameters.cameraOrthographicSize / mOcclusionPPRT.orthographicSize; mPostProcessingStack.GenerateFovMask(mOcclusionPPRT, floorOcclusionMask, wallFloorOcclusionMask, renderSettings, _fovCenterOffsetInExtendedViewSpace, fovDistance, operationParameters); if (!renderSettings.disableAsyncGPUReadback && SystemInfo.supportsAsyncGPUReadback) { // Request asynchronous callback for access to texture data. // Used for sampling point visibility from mask. AsyncGPUReadback.Request(wallFloorOcclusionMask.renderTexture, 0, AsyncReadCallback); } else { //async readback not supported, instead use synchronous readback RenderTexture.active = wallFloorOcclusionMask.renderTexture; mTex2DWallFloorOcclusionMask.ReadPixels(new Rect(0, 0, wallFloorOcclusionMask.renderTexture.width, wallFloorOcclusionMask.renderTexture.height), 0, 0); mTex2DWallFloorOcclusionMask.Apply(); } } using (new DisposableProfiler("3. Object Occlusion Mask")) { // These step calculates the objectOcclusionMask using the wallFloorOcclusionMask, so that objects / wallmounts will be hidden // if they are not in view objectOcclusionMask.Update(operationParameters.lightPPRTParameter); PixelPerfectRT.Transform(wallFloorOcclusionMask, objectOcclusionMask, materialContainer); // Update shader global transformation for occlusionMaskExtended so sprites can transform mask correctly. Shader.SetGlobalVector("_ObjectFovMaskTransformation", objectOcclusionMask.GetTransformation(mMainCamera)); } using (new DisposableProfiler("4. Blur Object Occlusion Mask")) { // Note: This blur is used only with shaders during scene render, so 1 pass should be enough. mPostProcessingStack.BlurOcclusionMask(objectOcclusionMask.renderTexture, renderSettings, operationParameters.cameraOrthographicSize); objectOcclusionMask.renderTexture.filterMode = FilterMode.Point; } // Note: After execution of this method, MainCamera.Render will be executed and scene will be drawn. }