using UnityEngine;
using UnityEngine.Rendering;
///
/// 相机渲染管理类:单独控制每个相机的渲染
///
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;
///
/// 相机渲染
///
///
///
///
///
///
///
///
///
///
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();
}
///
/// 剔除
///
///
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;
}
///
/// 设置相机的属性和矩阵,在着色器中被称为unity_matrixvp
///
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);
}
}
///
/// 提交缓冲区命令
///
void Submit()
{
buffer.EndSample(sampleName);
ExecuteBuffer();
context.Submit();
}
///
/// 执行缓冲区命令
///
void ExecuteBuffer()
{
context.ExecuteCommandBuffer(buffer);
buffer.Clear();
}
///
/// 绘制可见几何体,顺序:不透明物体->天空盒->透明物体
///
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);
}
}