private void ResolveRenderingTextures(OperationParameters iParameters)
    {
        // Prepare render textures.
        floorOcclusionMask           = new PixelPerfectRT(operationParameters.fovPPRTParameter);
        wallFloorOcclusionMask       = new PixelPerfectRT(operationParameters.fovPPRTParameter);
        mTex2DWallFloorOcclusionMask = new Texture2D(wallFloorOcclusionMask.renderTexture.width, wallFloorOcclusionMask.renderTexture.height, TextureFormat.RGB24, false);

        objectOcclusionMask = new PixelPerfectRT(operationParameters.lightPPRTParameter);

        obstacleLightMask = new PixelPerfectRT(operationParameters.obstacleLightPPRTParameter);

        // Let members handle their own textures.
        // Possibly move to container?
        mPostProcessingStack.ResetRenderingTextures(iParameters);
        mBackgroundRenderer.ResetRenderingTextures(iParameters);
    }
    public void CreateWallLightMask(
        PixelPerfectRT iLightMask,
        PixelPerfectRT iObstacleLightMask,
        RenderSettings iRenderSettings,
        float iCameraSize)
    {
        // Down Scale light mask and blur it.
        PixelPerfectRT.Transform(iLightMask, iObstacleLightMask, mMaterialContainer);

        mMaterialContainer.lightWallBlurMaterial.SetVector("_MultiLimit",
                                                           new Vector4(iRenderSettings.occlusionMaskMultiplier, iRenderSettings.occlusionMaskLimit, 0, 0));

        Blur(iObstacleLightMask.renderTexture, mMaterialContainer.lightWallBlurMaterial,
             iRenderSettings.occlusionBlurInterpolation, iRenderSettings.occlusionBlurIterations,
             blurRenderTextureOccLight, iCameraSize);
    }
    public void GenerateFovMask(
        PixelPerfectRT iRawOcclusionMask,
        PixelPerfectRT iGlobalOcclusionExtendedMask,
        RenderSettings iRenderSettings,
        Vector3 iFovCenterInViewSpace,
        float iFovDistance,
        OperationParameters iOperationParameters)
    {
        mMaterialContainer.fovMaterial.SetVector("_PositionOffset", iFovCenterInViewSpace);
        mMaterialContainer.fovMaterial.SetFloat("_OcclusionSpread", iRenderSettings.fovOcclusionSpread);

        // Adjust scale from Extended mask to Screen size mask.
        float   _yUVScale         = 1 / ((float)iGlobalOcclusionExtendedMask.renderTexture.width / iGlobalOcclusionExtendedMask.renderTexture.height);
        Vector3 _adjustedDistance = iFovDistance * iOperationParameters.cameraViewportUnitsInWorldSpace * iRawOcclusionMask.orthographicSize / iGlobalOcclusionExtendedMask.orthographicSize;

        mMaterialContainer.fovMaterial.SetVector("_Distance", new Vector3(_adjustedDistance.x, _yUVScale, iRenderSettings.fovHorizonSmooth));

        iRawOcclusionMask.renderTexture.filterMode = FilterMode.Bilinear;
        PixelPerfectRT.Blit(iRawOcclusionMask, iGlobalOcclusionExtendedMask, mMaterialContainer.fovMaterial);
    }
Example #4
0
    public PixelPerfectRT Render(
        Camera iCameraToMatch,
        PixelPerfectRTParameter iPPRTParameter,
        bool iMatrixRotationMode)
    {
        // Arrange.
        Vector2 _renderPosition;

        if (iMatrixRotationMode == false)
        {
            _renderPosition = iPPRTParameter.GetFilteredRendererPosition(iCameraToMatch.transform.position, mPreviousCameraPosition, mPreviousFilteredPosition);
        }
        else
        {
            // Note: Do not apply PixelPerfect position when matrix is rotating.
            _renderPosition = iCameraToMatch.transform.position;
        }

        mPreviousCameraPosition   = iCameraToMatch.transform.position;
        mPreviousFilteredPosition = _renderPosition;

        mMaskCamera.enabled            = false;
        mMaskCamera.backgroundColor    = new Color(0, 0, 0, 0);
        mMaskCamera.transform.position = _renderPosition;
        mMaskCamera.orthographicSize   = iPPRTParameter.orthographicSize;

        if (mPPRenderTexture == null)
        {
            mPPRenderTexture = new PixelPerfectRT(iPPRTParameter);
        }
        else
        {
            mPPRenderTexture.Update(iPPRTParameter);
        }

        // Execute.
        mPPRenderTexture.Render(mMaskCamera);

        return(mPPRenderTexture);
    }
Example #5
0
    private void OnRenderImage(RenderTexture iSource, RenderTexture iDestination)
    {
        if (renderSettings.doubleFrameRenderingMode)
        {
            if (mDoubleFrameRendererSwitch)
            {
                var _blitMaterial = materialContainer.blitMaterial;
                _blitMaterial.SetVector("_LightTransform", mlightPPRT.GetTransformation(mMainCamera));
                _blitMaterial.SetVector("_OcclusionTransform", floorOcclusionMask.GetTransformation(mMainCamera));

                Graphics.Blit(iSource, iDestination, _blitMaterial);

                mDoubleFrameRendererSwitch = false;
                return;
            }

            mDoubleFrameRendererSwitch = true;
        }

        if (materialContainer.blitMaterial == null)
        {
            Debug.Log($"FovSystemManager: Unable to blit Fov mask. {nameof(materialContainer.blitMaterial)} not provided.");
            return;
        }

        if (objectOcclusionMask == null)
        {
            Graphics.Blit(iSource, iDestination);
            return;
        }

        using (new DisposableProfiler("5. Light Mask Render (No Gfx Time)"))
        {
            mlightPPRT = mLightMaskRenderer.Render(
                mMainCamera,
                operationParameters.lightPPRTParameter,
                floorOcclusionMask,
                renderSettings,
                matrixRotationMode);
        }

        using (new DisposableProfiler("6. Generate Obstacle Light Mask"))
        {
            mPostProcessingStack.CreateWallLightMask(
                mlightPPRT,
                obstacleLightMask,
                renderSettings,
                operationParameters.cameraOrthographicSize);
        }

        // Debug View Selection.
        if (renderSettings.viewMode == RenderSettings.ViewMode.LightLayer)
        {
            PixelPerfectRT.Transform(mlightPPRT, iDestination, mMainCamera, materialContainer);

            return;
        }
        else if (renderSettings.viewMode == RenderSettings.ViewMode.WallLayer)
        {
            PixelPerfectRT.Transform(obstacleLightMask, iDestination, mMainCamera, materialContainer);

            return;
        }
        else if (renderSettings.viewMode == RenderSettings.ViewMode.FovObjectOcclusion)
        {
            PixelPerfectRT.Transform(objectOcclusionMask, iDestination, mMainCamera, materialContainer);

            return;
        }
        else if (renderSettings.viewMode == RenderSettings.ViewMode.FovFloorOcclusion)
        {
            PixelPerfectRT.Transform(floorOcclusionMask, iDestination, mMainCamera, materialContainer);

            return;
        }
        else if (renderSettings.viewMode == RenderSettings.ViewMode.FovWallAndFloorOcclusion)
        {
            PixelPerfectRT.Transform(wallFloorOcclusionMask, iDestination, mMainCamera, materialContainer);

            return;
        }
        else if (renderSettings.viewMode == RenderSettings.ViewMode.Obstacle)
        {
            PixelPerfectRT.Transform(mOcclusionPPRT, iDestination, mMainCamera, materialContainer);

            return;
        }

        using (new DisposableProfiler("7. Light Mask Blur"))
        {
            mPostProcessingStack.BlurLightMask(mlightPPRT.renderTexture, renderSettings, operationParameters.cameraOrthographicSize, mMatrixRotationModeBlend);
        }

        RenderTexture _backgroundMask = null;

        using (new DisposableProfiler("8. Render Background"))
        {
            _backgroundMask = mBackgroundRenderer.Render(renderSettings);
        }

        // Debug Views Selection.
        if (renderSettings.viewMode == RenderSettings.ViewMode.LightLayerBlurred)
        {
            PixelPerfectRT.Transform(mlightPPRT, iDestination, mMainCamera, materialContainer);

            return;
        }
        else if (renderSettings.viewMode == RenderSettings.ViewMode.Background)
        {
            Graphics.Blit(_backgroundMask, iDestination);

            return;
        }

        using (new DisposableProfiler("9. Blit Scene with Mixed Lights"))
        {
            mlightPPRT.renderTexture.filterMode         = FilterMode.Bilinear;
            obstacleLightMask.renderTexture.filterMode  = FilterMode.Bilinear;
            floorOcclusionMask.renderTexture.filterMode = matrixRotationMode ? FilterMode.Bilinear : FilterMode.Point;

            var _blitMaterial = materialContainer.blitMaterial;
            _blitMaterial.SetTexture("_LightMask", mlightPPRT.renderTexture);
            _blitMaterial.SetTexture("_OcclusionMask", floorOcclusionMask.renderTexture);
            _blitMaterial.SetTexture("_ObstacleLightMask", obstacleLightMask.renderTexture);
            _blitMaterial.SetVector("_LightTransform", mlightPPRT.GetTransformation(mMainCamera));
            _blitMaterial.SetVector("_OcclusionTransform", floorOcclusionMask.GetTransformation(mMainCamera));

            _blitMaterial.SetTexture("_BackgroundTex", _backgroundMask);
            _blitMaterial.SetVector("_AmbLightBloomSA", new Vector4(renderSettings.ambient, renderSettings.lightMultiplier, renderSettings.bloomSensitivity, renderSettings.bloomAdd));
            _blitMaterial.SetFloat("_BackgroundMultiplier", renderSettings.backgroundMultiplier);

            Graphics.Blit(iSource, iDestination, _blitMaterial);
        }
    }
Example #6
0
    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.
    }