CameraRenderer.cs 6.5 KB
Newer Older
timchen1002's avatar
timchen1002 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
using UnityEngine;
using UnityEngine.Rendering;

/// <summary>
/// 相机渲染管理类:单独控制每个相机的渲染
/// </summary>
public partial class CameraRenderer
{
    ScriptableRenderContext context;
    Camera camera;

    const string bufferName = "Render Camera";

    // 创建缓冲区
    CommandBuffer buffer = new CommandBuffer
    {
        name = bufferName
    };

    // 存储相机剔除后的结果
    CullingResults cullingResults;

    // 着色器标记ID
    static ShaderTagId unlitShaderTagId = new ShaderTagId("SRPDefaultUnlit");
    static ShaderTagId litShaderTagId = new ShaderTagId("CustomLit");

    static int frameBufferId = Shader.PropertyToID("_CameraFrameBuffer");


    Lighting lighting = new Lighting();

    PostFXStack postFXStack = new PostFXStack();

    bool useHDR;

    /// <summary>
    /// 相机渲染
    /// </summary>
    /// <param name="context"></param>
    /// <param name="camera"></param>
    /// <param name="allowHDR"></param>
    /// <param name="useDynamicBatching"></param>
    /// <param name="useGPUInstancing"></param>
    /// <param name="useLightsPerObject"></param>
    /// <param name="shadowSettings"></param>
    /// <param name="postFXSettings"></param>
    /// <param name="colorLUTResolution"></param>
    public void Render(ScriptableRenderContext context, Camera camera, bool allowHDR, bool useDynamicBatching, bool useGPUInstancing, bool useLightsPerObject, ShadowSettings shadowSettings, PostFXSettings postFXSettings, int colorLUTResolution)
    {
        this.context = context;
        this.camera = camera;
        // 设置buffer缓冲区的名字
        PrepareBuffer();
        // 在Game视图绘制的几何体也绘制到Scene视图中
        PrepareForSceneWindow();
        if (!Cull(shadowSettings.maxDistance))
        {
            return;
        }

        useHDR = allowHDR && camera.allowHDR;

        context.SetupCameraProperties(camera);
        // 获得相机的clear flags
        CameraClearFlags flags = camera.clearFlags;

        buffer.BeginSample(sampleName);
        ExecuteBuffer();
        lighting.Setup(context, cullingResults, shadowSettings, useLightsPerObject);
        postFXStack.Setup(context, camera, postFXSettings, useHDR, colorLUTResolution);
        buffer.EndSample(sampleName);
        Setup();

        // 绘制可见几何体
        DrawVisibleGeometry(useDynamicBatching, useGPUInstancing, useLightsPerObject);
        // 绘制SRP不支持的内置shader类型
        DrawUnsupportedShaders();

        // 绘制Gizmos
        DrawGizmosBeforeFX();
        if (postFXStack.IsActive)
        {
            if (flags > CameraClearFlags.Color)
            {
                flags = CameraClearFlags.Color;
            }
            postFXStack.Render(frameBufferId);
        }
        DrawGizmosAfterFX();

        Cleanup();
        // 提交缓冲区
        Submit();
    }

    /// <summary>
    /// 剔除
    /// </summary>
    /// <returns></returns>
    bool Cull(float maxShadowDistance)
    {
        if (camera.TryGetCullingParameters(out ScriptableCullingParameters p))
        {
            p.shadowDistance = Mathf.Min(maxShadowDistance, camera.farClipPlane);
            cullingResults = context.Cull(ref p);
            return true;
        }
        return false;
    }

    /// <summary>
    /// 设置相机的属性和矩阵,在着色器中被称为unity_matrixvp
    /// </summary>
    void Setup()
    {
        context.SetupCameraProperties(camera);
        // 得到相机的clearflags
        CameraClearFlags flags = camera.clearFlags;

        if (postFXStack.IsActive)
        {
            buffer.GetTemporaryRT(frameBufferId, camera.pixelWidth, camera.pixelHeight, 32, FilterMode.Bilinear, useHDR ? RenderTextureFormat.DefaultHDR: RenderTextureFormat.Default);
            buffer.SetRenderTarget(frameBufferId, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store);
        }

        // 设置相机清除状态
        buffer.ClearRenderTarget(flags <= CameraClearFlags.Depth, flags == CameraClearFlags.Color, flags == CameraClearFlags.Color ? camera.backgroundColor.linear : Color.clear);
        buffer.BeginSample(sampleName);
        ExecuteBuffer();
    }

    void Cleanup()
    {
        // 释放申请的RT内存空间
        lighting.Cleanup();
        if (postFXStack.IsActive)
        {
            buffer.ReleaseTemporaryRT(frameBufferId);
        }
    }

    /// <summary>
    /// 提交缓冲区命令
    /// </summary>
    void Submit()
    {
        buffer.EndSample(sampleName);
        ExecuteBuffer();
        context.Submit();
    }

    /// <summary>
    /// 执行缓冲区命令
    /// </summary>
    void ExecuteBuffer()
    {
        context.ExecuteCommandBuffer(buffer);
        buffer.Clear();
    }

    /// <summary>
    /// 绘制可见几何体,顺序:不透明物体->天空盒->透明物体
    /// </summary>
    void DrawVisibleGeometry(bool useDynamicBatching, bool useGPUInstancing, bool useLightsPerObject)
    {
        PerObjectData lightsPerObjectFlags = useLightsPerObject ? PerObjectData.LightData | PerObjectData.LightIndices : PerObjectData.None;
        // 设置绘制顺序和指定渲染相机
        var sortingSettings = new SortingSettings(camera)
        {
            criteria = SortingCriteria.CommonOpaque
        };
        // 设置渲染的shader pass和渲染顺序
        var drawingSettings = new DrawingSettings(unlitShaderTagId, sortingSettings)
        {
            enableDynamicBatching = useDynamicBatching,
            enableInstancing = useGPUInstancing,
            perObjectData = PerObjectData.Lightmaps | PerObjectData.ShadowMask | PerObjectData.LightProbe | PerObjectData.OcclusionProbe | PerObjectData.LightProbeProxyVolume | PerObjectData.ReflectionProbes | lightsPerObjectFlags,
        };
        // 渲染CustomLit表示的pass块
        drawingSettings.SetShaderPassName(1, litShaderTagId);

        // 只绘制RenderQueue为opaque不透明物体
        var filteringSettings = new FilteringSettings(RenderQueueRange.opaque);

        // 绘制不透明物体
        context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings);
        // 绘制天空盒
        context.DrawSkybox(camera);
        sortingSettings.criteria = SortingCriteria.CommonTransparent;
        drawingSettings.sortingSettings = sortingSettings;
        // 只绘制RenderQueue为transparent透明的物体
        filteringSettings.renderQueueRange = RenderQueueRange.transparent;
        // 绘制透明物体
        context.DrawRenderers(cullingResults, ref drawingSettings, ref filteringSettings);
    }
}