ThomagicRenderer/Runtime/Scripts/CameraRenderer.cs

677 lines
33 KiB
C#

using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.XR;
namespace Assets.ThoMagic.Renderer
{
public class CameraRenderer : IDisposable
{
internal static int nextCameraRendererId = 0;
int cameraRendererId;
public static IInstanceRenderSettings ReflectionProbeSettings;
public readonly Camera Camera;
public IInstanceRenderSettings cameraSettings;
private readonly bool _singlePassInstanced = false;
private int cachedBufferHash;
private Vector3 _origin;
private Light _mainLight;
List<InstanceStreamer> visibleStreams = new List<InstanceStreamer>();
List<PrefabData> prefabData = new List<PrefabData>();
List<GraphicsBuffer.IndirectDrawIndexedArgs> indirectDrawIndexedArgs = new List<GraphicsBuffer.IndirectDrawIndexedArgs>();
Dictionary<int, float> objRenderDistanceCache = new Dictionary<int, float>();
Dictionary<uint, InstanceRenderSettings> appliedSettings = new Dictionary<uint, InstanceRenderSettings>();
List<uint> cullableIndexes = new List<uint>();
public Camera ReferenceCamera { get; private set; }
private CommandBuffer commandBuffer;
private ComputeShader instancingShader;
private ComputeBuffer prefabBuffer;
private GraphicsBuffer indirectDrawIndexedArgsBuffer;
private ComputeBuffer metaBuffer;
private ComputeBuffer cullableIndexesBuffer;
private ComputeBuffer visibleIndexesBuffer;
private ComputeBuffer visibleShadowIndexesBuffer;
private float cachedFov;
private float cachedBias;
private bool lodInvalid;
SceneRenderSettings sceneSettings = new SceneRenderSettings();
private Plane[] _cachedFrustumPlanes;
private Vector4[] _cachedShaderFrustumPlanes;
internal bool instanceCountChanged = true;
internal bool rebuildPrefabs = true;
private int cullShaderId = 0, clearShaderId = 0;
private uint maxInstancesCount = 0;
private uint indexBufferOffset = 0;
private int lastCamSettingsHash = 0;
public CameraRenderer(Camera camera)
{
commandBuffer = new CommandBuffer();
cameraRendererId = Interlocked.Increment(ref nextCameraRendererId);
instancingShader = UnityEngine.Object.Instantiate(Resources.Load<ComputeShader>("ThoMagic Renderer Instancing"));
instancingShader.hideFlags = HideFlags.HideAndDontSave;
cullShaderId = instancingShader.FindKernel("Cull_64");
clearShaderId = instancingShader.FindKernel("Clear_64");
instancingShader.name = $"ThoMagic Renderer Instancing - {camera.name}";
Camera = camera != null ? camera : throw new ArgumentNullException(nameof(camera));
cameraSettings = camera.GetComponent<IInstanceRenderSettings>();
ReferenceCamera = camera;
if (camera.cameraType == CameraType.Game || camera.cameraType == CameraType.VR)
{
_singlePassInstanced = XRSettings.enabled && (XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePassInstanced || XRSettings.stereoRenderingMode == XRSettings.StereoRenderingMode.SinglePassMultiview);
if (Application.isEditor && XRSettings.enabled && !_singlePassInstanced && XRSettings.loadedDeviceName == "MockHMD Display" && this.LoadMockHmdSetting() == "SinglePassInstanced")
_singlePassInstanced = true;
}
}
public void SetFloatingOrigin(in Vector3 origin)
{
_origin = origin;
}
public void SetReferenceCamera(Camera camera)
{
ReferenceCamera = camera != null ? camera : Camera;
cameraSettings = ReferenceCamera.GetComponent<IInstanceRenderSettings>();
}
public void SetMainLight(Light light) => _mainLight = light;
private void CalculateFrustumPlanes()
{
if (_cachedFrustumPlanes == null)
_cachedFrustumPlanes = new Plane[6];
GeometryUtility.CalculateFrustumPlanes(ReferenceCamera, _cachedFrustumPlanes);
if (_cachedShaderFrustumPlanes == null)
_cachedShaderFrustumPlanes = new Vector4[6];
for (int index = 0; index < 6; ++index)
_cachedShaderFrustumPlanes[index] = new Vector4(_cachedFrustumPlanes[index].normal.x, _cachedFrustumPlanes[index].normal.y, _cachedFrustumPlanes[index].normal.z, _cachedFrustumPlanes[index].distance);
}
public void Render()
{
//Used in editor if selected camera is not editor scene camera. Then only the culled instances of the selected camera is rendered.
if (ReferenceCamera == null)
SetReferenceCamera(Camera);
if (_mainLight == null)
_mainLight = FindMainLight();
if (_mainLight != null)
{
sceneSettings.HasMainLight = true;
sceneSettings.HasMainLightShadows = _mainLight.shadows > 0;
sceneSettings.MainLightDirection = _mainLight.transform.forward;
}
else
{
sceneSettings.HasMainLight = false;
sceneSettings.HasMainLightShadows = false;
}
var finalSettings = InstanceRenderSettings.Default(ReferenceCamera);
if (ReferenceCamera.cameraType == CameraType.Reflection && ReflectionProbeSettings != null)
finalSettings.Merge(ReflectionProbeSettings.Settings);
if (cameraSettings == null && Application.isEditor && !Application.isPlaying)
cameraSettings = ReferenceCamera.GetComponent<IInstanceRenderSettings>();
if (cameraSettings != null)
finalSettings.Merge(cameraSettings.Settings);
if(finalSettings.GetHashCode() != lastCamSettingsHash)
{
lastCamSettingsHash = finalSettings.GetHashCode();
rebuildPrefabs = true;
}
if (!rebuildPrefabs && Application.isEditor && !Application.isPlaying)
{
foreach (var renderObject in RendererPool.objectsList)
{
var settingsEditor = finalSettings;
var renderObjectSettingsNew = renderObject.GameObject.GetComponent<IInstanceRenderSettings>();
if (renderObjectSettingsNew != null)
settingsEditor.Merge(renderObjectSettingsNew.Settings);
if(!appliedSettings.ContainsKey(renderObject.prefabId) || settingsEditor.GetHashCode() != appliedSettings[renderObject.prefabId].GetHashCode())
{
renderObject.Settings = renderObjectSettingsNew;
rebuildPrefabs = true;
}
}
}
CalculateFrustumPlanes();
//Find visible streams for this frame
visibleStreams.Clear();
foreach (var streamer in RendererPool.streamers.Values)
if (streamer.IsInRange(ReferenceCamera, _cachedFrustumPlanes))
{
streamer.UpdateForCamera(ReferenceCamera, _cachedFrustumPlanes);
visibleStreams.Add(streamer);
}
bool prefabDataChanged = false;
bool noNeedToUpdateIndirectIndexOffsets = false;
//A prefab (object) has been added, removed or changed
if (rebuildPrefabs)
{
noNeedToUpdateIndirectIndexOffsets = true;
rebuildPrefabs = false;
lodInvalid = false;
cachedFov = ReferenceCamera.fieldOfView;
cachedBias = QualitySettings.lodBias;
appliedSettings.Clear();
indirectDrawIndexedArgs.Clear();
prefabData.Clear();
prefabData.AddRange(RendererPool.prefabData);
maxInstancesCount = 0;
indexBufferOffset = 0;
uint batchIndex = 0;
uint prefabCount = 0;
uint indexArgsSize = 0;
int totalIndirectArgsIndex = 0;
foreach (var renderObject in RendererPool.objectsList)
{
var localPrefabData = prefabData[(int)renderObject.prefabId];
var finalObjSettings = finalSettings;
if (renderObject.Settings != null)
{
finalObjSettings.Merge(renderObject.Settings.Settings);
ValidateSettings(ref finalObjSettings);
}
CalculateCullingDistances(renderObject, finalObjSettings, cachedFov, cachedBias, renderObject.LodTransitions, renderObject.LodSizes, renderObject.lods);
float distance1 = RelativeHeightToDistance(finalObjSettings.DensityInDistanceFalloff.x, renderObject.LodSizes[0], cachedFov);
float distance2 = RelativeHeightToDistance(finalObjSettings.DensityInDistanceFalloff.y, renderObject.LodSizes[0], cachedFov);
var densityInDistance = new Vector4(finalObjSettings.DensityInDistance,
distance1,
distance2 - distance1,
finalObjSettings.ShadowDistance);
localPrefabData.lodCount = renderObject.lodCount;
localPrefabData.fadeLods = renderObject.fadeLods;
localPrefabData.batchIndex = batchIndex;
localPrefabData.indexBufferStartOffset = indexBufferOffset;
localPrefabData.maxCount = renderObject.count;
localPrefabData.densityInDistance = densityInDistance;
renderObject.indirectArgsPerSubmeshOffsets.Clear();
indirectDrawIndexedArgs.AddRange(renderObject.indirectDrawIndexedArgs);
for (int i = 0; i < renderObject.lodCount; i++)
{
renderObject.indirectArgsPerLodOffsets[i] = indexArgsSize;
//All indirect arguments for this lod including shadows
for (int z = 0; z < renderObject.indirectArgsPerLodWithShadowsCounts[i]; z++)
{
//Set batchoffset
var idia = indirectDrawIndexedArgs[totalIndirectArgsIndex];
idia.startInstance = indexBufferOffset + (uint)(i * renderObject.count);
indirectDrawIndexedArgs[totalIndirectArgsIndex] = idia;
//**
renderObject.indirectArgsPerSubmeshOffsets.Add(totalIndirectArgsIndex);
totalIndirectArgsIndex++;
indexArgsSize += 5;
}
}
localPrefabData.SetLods(renderObject.lods, renderObject.indirectArgsPerLodOffsets, renderObject.indirectArgsPerLodCounts);
prefabData[(int)renderObject.prefabId] = localPrefabData;
appliedSettings[renderObject.prefabId] = finalObjSettings;
batchIndex += renderObject.lodCount;
indexBufferOffset += renderObject.count * renderObject.lodCount;
maxInstancesCount += renderObject.count;
prefabCount++;
}
//Nothing to draw yet
if (maxInstancesCount == 0)
{
rebuildPrefabs = true;
return;
}
if (metaBuffer == null || metaBuffer.count < maxInstancesCount)
{
metaBuffer?.Dispose();
int nextCount = RendererPool.RESIZE_COUNT * (((int)maxInstancesCount - 1) / RendererPool.RESIZE_COUNT + 1);
metaBuffer = new ComputeBuffer(nextCount, sizeof(uint) * 4, ComputeBufferType.Structured);
metaBuffer.name = $"ThoMagic metaBuffer ({Camera.name})";
cullableIndexesBuffer?.Dispose();
cullableIndexesBuffer = new ComputeBuffer(nextCount, sizeof(uint), ComputeBufferType.Structured);
cullableIndexesBuffer.name = $"ThoMagic cullingIndexesBuffer ({Camera.name})";
}
if (indirectDrawIndexedArgsBuffer == null || indirectDrawIndexedArgsBuffer.count < indirectDrawIndexedArgs.Count)
{
indirectDrawIndexedArgsBuffer?.Dispose();
int nextCount = RendererPool.RESIZE_COUNT * (((int)indirectDrawIndexedArgs.Count - 1) / RendererPool.RESIZE_COUNT + 1);
indirectDrawIndexedArgsBuffer = new GraphicsBuffer(GraphicsBuffer.Target.IndirectArguments, nextCount, GraphicsBuffer.IndirectDrawIndexedArgs.size);
indirectDrawIndexedArgsBuffer.name = $"ThoMagic indirectDrawIndexedArgsBuffer ({Camera.name})";
}
indirectDrawIndexedArgsBuffer.SetData(indirectDrawIndexedArgs);
if (prefabBuffer == null || prefabBuffer.count < prefabCount)
{
prefabBuffer?.Dispose();
int nextCount = RendererPool.RESIZE_COUNT * (((int)prefabCount - 1) / RendererPool.RESIZE_COUNT + 1);
prefabBuffer = new ComputeBuffer(nextCount, PrefabData.Stride, ComputeBufferType.Structured);
prefabBuffer.name = $"ThoMagic prefabBuffer ({Camera.name})";
}
if (visibleIndexesBuffer == null || visibleIndexesBuffer.count < indexBufferOffset)
{
visibleIndexesBuffer?.Dispose();
int nextCount = RendererPool.RESIZE_COUNT * (((int)indexBufferOffset - 1) / RendererPool.RESIZE_COUNT + 1);
visibleIndexesBuffer = new ComputeBuffer(nextCount, sizeof(uint), ComputeBufferType.Structured);
visibleIndexesBuffer.name = $"ThoMagic visibleIndexesBuffer ({Camera.name})";
visibleShadowIndexesBuffer?.Dispose();
visibleShadowIndexesBuffer = new ComputeBuffer(nextCount, sizeof(uint), ComputeBufferType.Structured);
visibleShadowIndexesBuffer.name = $"ThoMagic visibleShadowIndexesBuffer ({Camera.name})";
};
prefabDataChanged = true;
instanceCountChanged = true;
}
//Nothing to draw yet
if (maxInstancesCount == 0)
return;
//Either instances have been added/removed or the visible streams have changed.
//We need to rebuild the visible instances index buffer
if (instanceCountChanged || BuffersChanged(visibleStreams, ref cachedBufferHash))
{
if (instanceCountChanged)
{
if (!noNeedToUpdateIndirectIndexOffsets)//If already rebuild by prefab update, this is not needed
{
maxInstancesCount = 0;
indexBufferOffset = 0;
uint indexArgsSize = 0;
int totalIndirectArgsIndex = 0;
foreach (var renderObject in RendererPool.objectsList)
{
for (int i = 0; i < renderObject.lodCount; i++)
{
//All indirect arguments for this lod including shadows
for (int z = 0; z < renderObject.indirectArgsPerLodWithShadowsCounts[i]; z++)
{
//Set batchoffset
var idia = indirectDrawIndexedArgs[totalIndirectArgsIndex];
idia.startInstance = indexBufferOffset + (uint)(i * renderObject.count);
indirectDrawIndexedArgs[totalIndirectArgsIndex] = idia;
//**
totalIndirectArgsIndex++;
indexArgsSize += 5;
}
}
var pd = prefabData[(int)renderObject.prefabId];
if (pd.maxCount != renderObject.count)
prefabDataChanged = true;
pd.indexBufferStartOffset = indexBufferOffset;
pd.maxCount = renderObject.count;
prefabData[(int)renderObject.prefabId] = pd;
indexBufferOffset += renderObject.count * renderObject.lodCount;
maxInstancesCount += renderObject.count;
}
if (metaBuffer == null || metaBuffer.count < maxInstancesCount)
{
metaBuffer?.Dispose();
int nextCount = RendererPool.RESIZE_COUNT * (((int)maxInstancesCount - 1) / RendererPool.RESIZE_COUNT + 1);
metaBuffer = new ComputeBuffer(nextCount, sizeof(uint) * 4, ComputeBufferType.Structured);
metaBuffer.name = $"ThoMagic metaBuffer ({Camera.name})";
cullableIndexesBuffer?.Dispose();
cullableIndexesBuffer = new ComputeBuffer(nextCount, sizeof(uint), ComputeBufferType.Structured);
cullableIndexesBuffer.name = $"ThoMagic cullingIndexesBuffer ({Camera.name})";
}
if (visibleIndexesBuffer == null || visibleIndexesBuffer.count < indexBufferOffset)
{
visibleIndexesBuffer?.Dispose();
int nextCount = RendererPool.RESIZE_COUNT * (((int)indexBufferOffset - 1) / RendererPool.RESIZE_COUNT + 1);
visibleIndexesBuffer = new ComputeBuffer(nextCount, sizeof(uint), ComputeBufferType.Structured);
visibleIndexesBuffer.name = $"ThoMagic visibleIndexesBuffer ({Camera.name})";
visibleShadowIndexesBuffer?.Dispose();
visibleShadowIndexesBuffer = new ComputeBuffer(nextCount, sizeof(uint), ComputeBufferType.Structured);
visibleShadowIndexesBuffer.name = $"ThoMagic visibleShadowIndexesBuffer ({Camera.name})";
};
indirectDrawIndexedArgsBuffer.SetData(indirectDrawIndexedArgs);
}
}
instanceCountChanged = false;
cullableIndexes.Clear();
foreach (var stream in visibleStreams)
{
foreach (var objectInstanceIds in stream.objectInstanceIds.Values)
{
cullableIndexes.AddRange(objectInstanceIds);
}
}
cullableIndexesBuffer.SetData(cullableIndexes);
}
//Nothing to render
if (cullableIndexes.Count == 0 || RendererPool.globalInstanceBuffer == null)
return;
//Lod settings changed, update prefab lod data
if (cachedFov != ReferenceCamera.fieldOfView || cachedBias != QualitySettings.lodBias || lodInvalid)
{
lodInvalid = false;
cachedFov = ReferenceCamera.fieldOfView;
cachedBias = QualitySettings.lodBias;
foreach (var renderObject in RendererPool.objectsList)
{
CalculateCullingDistances(renderObject, appliedSettings[renderObject.prefabId], cachedFov, cachedBias, renderObject.LodTransitions, renderObject.LodSizes, renderObject.lods);
float distance1 = RelativeHeightToDistance(appliedSettings[renderObject.prefabId].DensityInDistanceFalloff.x, renderObject.LodSizes[0], cachedFov);
float distance2 = RelativeHeightToDistance(appliedSettings[renderObject.prefabId].DensityInDistanceFalloff.y, renderObject.LodSizes[0], cachedFov);
var densityInDistance = new Vector4(appliedSettings[renderObject.prefabId].DensityInDistance,
distance1,
distance2 - distance1,
appliedSettings[renderObject.prefabId].ShadowDistance);
var pd = prefabData[(int)renderObject.prefabId];
pd.SetLods(renderObject.lods, renderObject.indirectArgsPerLodOffsets, renderObject.indirectArgsPerLodCounts);
pd.densityInDistance = densityInDistance;
prefabData[(int)renderObject.prefabId] = pd;
}
prefabDataChanged = true;
}
if(prefabDataChanged)
prefabBuffer.SetData(prefabData);
//Compute culling
//Reset visible count of instances to zero
/*instancingShader.SetInt("_Count", indirectDrawIndexedArgs.Count);
instancingShader.SetBuffer(clearShaderId, "perCamIndirectArgumentsBuffer", indirectDrawIndexedArgsBuffer);
instancingShader.Dispatch(clearShaderId, Mathf.CeilToInt(indirectDrawIndexedArgs.Count / 64.0f), 1, 1);
//Cull
instancingShader.SetBuffer(cullShaderId, "globalInstances", RendererPool.globalInstanceBuffer);
instancingShader.SetBuffer(cullShaderId, "perCamPrefabs", prefabBuffer);
instancingShader.SetBuffer(cullShaderId, "perCamMeta", metaBuffer);
instancingShader.SetBuffer(cullShaderId, "perCamIndirectArgumentsBuffer", indirectDrawIndexedArgsBuffer);
instancingShader.SetBuffer(cullShaderId, "perCamCullableIndexesBuffer", cullableIndexesBuffer);
instancingShader.SetBuffer(cullShaderId, "perCamVisibleIndexesBuffer", visibleIndexesBuffer);
instancingShader.SetBuffer(cullShaderId, "perCamShadowVisibleIndexesBuffer", visibleShadowIndexesBuffer);
instancingShader.SetVector("_CameraPosition", ReferenceCamera.transform.position);
instancingShader.SetVectorArray("_FrustumPlanes", _cachedShaderFrustumPlanes);
instancingShader.SetVector("_ShadowDirection", sceneSettings.MainLightDirection);
instancingShader.SetInt("_Count", cullableIndexes.Count);
instancingShader.Dispatch(cullShaderId, Mathf.CeilToInt(cullableIndexes.Count / 64.0f), 1, 1);*/
commandBuffer.Clear();
commandBuffer.SetComputeIntParam(instancingShader, "_CountClear", indirectDrawIndexedArgs.Count);
commandBuffer.SetComputeBufferParam(instancingShader, clearShaderId, "perCamIndirectArgumentsBuffer", indirectDrawIndexedArgsBuffer);
commandBuffer.DispatchCompute(instancingShader, clearShaderId, Mathf.CeilToInt(indirectDrawIndexedArgs.Count / 64.0f), 1, 1);
commandBuffer.SetComputeBufferParam(instancingShader, cullShaderId, "globalInstances", RendererPool.globalInstanceBuffer);
commandBuffer.SetComputeBufferParam(instancingShader, cullShaderId, "perCamPrefabs", prefabBuffer);
commandBuffer.SetComputeBufferParam(instancingShader, cullShaderId, "perCamMeta", metaBuffer);
commandBuffer.SetComputeBufferParam(instancingShader, cullShaderId, "perCamIndirectArgumentsBuffer", indirectDrawIndexedArgsBuffer);
commandBuffer.SetComputeBufferParam(instancingShader, cullShaderId, "perCamCullableIndexesBuffer", cullableIndexesBuffer);
commandBuffer.SetComputeBufferParam(instancingShader, cullShaderId, "perCamVisibleIndexesBuffer", visibleIndexesBuffer);
commandBuffer.SetComputeBufferParam(instancingShader, cullShaderId, "perCamShadowVisibleIndexesBuffer", visibleShadowIndexesBuffer);
commandBuffer.SetComputeVectorParam(instancingShader, "_CameraPosition", ReferenceCamera.transform.position);
commandBuffer.SetComputeVectorArrayParam(instancingShader, "_FrustumPlanes", _cachedShaderFrustumPlanes);
commandBuffer.SetComputeVectorParam(instancingShader, "_ShadowDirection", sceneSettings.MainLightDirection);
commandBuffer.SetComputeIntParam(instancingShader, "_CountCull", cullableIndexes.Count);
commandBuffer.DispatchCompute(instancingShader, cullShaderId, Mathf.CeilToInt(cullableIndexes.Count / 64.0f), 1, 1);
Graphics.ExecuteCommandBuffer(commandBuffer);
var fence = Graphics.CreateGraphicsFence(GraphicsFenceType.AsyncQueueSynchronisation, SynchronisationStageFlags.ComputeProcessing);
Graphics.WaitOnAsyncGraphicsFence(fence);
//Render all prefabs (objects)
foreach (var renderObject in RendererPool.objectsList)
if (renderObject.count > 0)//Ignore if no instance is registered
RenderObject(renderObject, appliedSettings[renderObject.prefabId]);
}
private void CalculateCullingDistances(
ObjectData renderObject,
InstanceRenderSettings finalSettings,
float fieldOfView,
float bias,
float[] relativeTransitionHeight,
float[] detailSize,
Vector4[] lodData)
{
for (int index = 0; index < relativeTransitionHeight.Length; ++index)
lodData[index] = new Vector4(index > 0 ? lodData[index - 1].y : 0.0f, RelativeHeightToDistance(relativeTransitionHeight[index], detailSize[index], fieldOfView) * bias, detailSize[index], 0.0f);
var renderDistance = Mathf.Min(finalSettings.RenderDistance, RelativeHeightToDistance(renderObject.LodTransitions[renderObject.LodTransitions.Length - 1], renderObject.LodSizes[renderObject.LodTransitions.Length - 1], this.ReferenceCamera.fieldOfView, QualitySettings.lodBias));
objRenderDistanceCache[renderObject.GetHashCode()] = renderDistance;
for (int index = 0; index < renderObject.LodSizes.Length; ++index)
{
renderObject.lods[index].x = Mathf.Min(renderObject.lods[index].x, renderDistance);
renderObject.lods[index].y = Mathf.Min(renderObject.lods[index].y, renderDistance);
}
}
public static float RelativeHeightToDistance(
float relativeHeight,
float size,
float fieldOfView)
{
if (relativeHeight <= 0.0f || relativeHeight == float.MaxValue)
return float.MaxValue;
float num = Mathf.Tan((float)(Math.PI / 180.0 * (double)fieldOfView * 0.5));
return size * 0.5f / relativeHeight / num;
}
private void RenderObject(
ObjectData obj,
InstanceRenderSettings renderSettings)
{
if (LayerIsCulled(ReferenceCamera, obj.GameObject.layer) || (/*(!Application.isEditor || Application.isPlaying) &&*/ SceneIsCulled(ReferenceCamera, obj.GameObject)))
return;
if (!renderSettings.Render)
return;
foreach(var drawGroup in obj.drawGroups)
{
if (drawGroup == null) continue;
drawGroup.SetInstances(RendererPool.globalInstanceBuffer, visibleIndexesBuffer, metaBuffer);
drawGroup.Draw(Camera, obj, indirectDrawIndexedArgsBuffer);
}
if (!renderSettings.Shadows)
return;
foreach (var drawGroup in obj.drawShadowGroups)
{
if (drawGroup == null) continue;
drawGroup.SetInstances(RendererPool.globalInstanceBuffer, visibleShadowIndexesBuffer, metaBuffer);
drawGroup.Draw(Camera, obj, indirectDrawIndexedArgsBuffer);
}
}
private void ValidateSettings(ref InstanceRenderSettings settings)
{
if (settings.RenderDistance <= 0.0f)
settings.RenderDistance = this.ReferenceCamera.farClipPlane;
if (settings.ShadowDistance > 0.0f)
return;
settings.ShadowDistance = settings.RenderDistance;
}
private bool LayerIsCulled(Camera camera, int layer)
{
if (camera.cullingMask != -1)
{
int num = layer;
if ((camera.cullingMask & 1 << num) == 0)
return true;
}
return false;
}
private bool SceneIsCulled(Camera camera, GameObject gameObject)
{
if (camera.scene != null && camera.scene.handle != 0 && camera.scene != gameObject.scene)
return true;
else
return false;
}
private string LoadMockHmdSetting()
{
try
{
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
Type type = assembly.GetType("Unity.XR.MockHMD.MockHMDBuildSettings", false);
if (!(type == (Type)null))
{
object obj = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue((object)null);
return type.GetField("renderMode").GetValue(obj).ToString();
}
}
}
catch
{
}
return null;
}
private Light FindMainLight()
{
Light currentLight = null;
foreach (Light otherLight in UnityEngine.Object.FindObjectsOfType<Light>())
{
if (otherLight.type == LightType.Directional)
{
if (otherLight.shadows > 0)
{
currentLight = otherLight;
break;
}
if (currentLight == null)
currentLight = otherLight;
else if (otherLight.intensity > currentLight.intensity)
currentLight = otherLight;
}
}
return currentLight;
}
private float RelativeHeightToDistance(
float relativeHeight,
float size,
float fieldOfView,
float bias)
{
if ((double)relativeHeight <= 0.0 || (double)relativeHeight == 3.40282346638529E+38)
return float.MaxValue;
float num = Mathf.Tan((float)(Math.PI / 180.0 * (double)fieldOfView * 0.5));
return size * 0.5f / relativeHeight / num * bias;
}
private bool BuffersChanged(List<InstanceStreamer> buffers, ref int cachedHash)
{
int hash = ComputeHash(buffers);
if (hash == cachedHash)
return false;
cachedHash = hash;
return true;
}
private int ComputeHash(List<InstanceStreamer> buffers)
{
if (buffers == null || buffers.Count == 0)
return 0;
int num = buffers[0].GetHashCode();
for (int index = 1; index < buffers.Count; ++index)
num = HashCode.Combine(num, buffers[index].GetHashCode());
return num;
}
public void Dispose()
{
UnityEngine.Object.DestroyImmediate(instancingShader);
prefabBuffer?.Dispose();
indirectDrawIndexedArgsBuffer?.Dispose();
metaBuffer?.Dispose();
cullableIndexesBuffer?.Dispose();
visibleIndexesBuffer?.Dispose();
visibleShadowIndexesBuffer?.Dispose();
commandBuffer?.Dispose();
prefabBuffer = null;
indirectDrawIndexedArgsBuffer = null;
metaBuffer = null;
visibleIndexesBuffer = null;
visibleShadowIndexesBuffer = null;
}
}
}