private Vector4 GenerateRotation() { float xAngle = m_randomXAngle ? Random.Range(0f, 1f) * 360f : 0; float yAngle = m_randomYAngle ? Random.Range(0f, 1f) * 360f : 0; float zAngle = m_randomZAngle ? Random.Range(0f, 1f) * 360f : 0; Quaternion temp = Quaternion.Euler(xAngle, yAngle, zAngle); return(InstancingUtilities.VectorFromQuaternion(temp)); }
public void ModifyScale(int index, Vector3 scale, float original) { //unpack, vector multiply to scale, repack, store Vector3 originalUnpacked = InstancingUtilities.UnpackScaleVectorFromFloat(original); originalUnpacked.Scale(scale); float modifiedPacked = InstancingUtilities.PackScaleVectorToFloat(originalUnpacked); m_positions[index].w = modifiedPacked; }
//legacy function to build arrays private void PopulateDataArrays() { int spawnedCount = 0; Terrain t = Terrain.activeTerrain; while (spawnedCount < m_positions.Length) { float x = Random.Range(-720f, 720f); float y = 0; float z = Random.Range(-720f, 720f); float u = (x + 720f) / t.terrainData.size.x; float v = (z + 720f) / t.terrainData.size.z; u = Mathf.Round(u * t.terrainData.alphamapWidth); v = Mathf.Round(v * t.terrainData.alphamapHeight); Color c = t.terrainData.alphamapTextures[0].GetPixel((int)u, (int)v); float layer = Mathf.Max(c.r, c.g, c.b, c.a); if (m_legacyLayer != -1) { if (Mathf.Approximately(c[m_legacyLayer], layer)) { float size = InstancingUtilities.PackScaleVectorToFloat(GenerateScale()); Vector3 position = new Vector3(x, y, z); m_positions[spawnedCount] = new Vector4(position.x, position.y, position.z, size); m_rotations[spawnedCount] = GenerateRotation(); if (m_customData != null) { m_customData[spawnedCount] = GenerateCustomData(); } spawnedCount++; } } else if (m_legacyLayer == -1) { float size = InstancingUtilities.PackScaleVectorToFloat(GenerateScale()); Vector3 position = new Vector3(x, y, z); m_positions[spawnedCount] = new Vector4(position.x, position.y, position.z, size); m_rotations[spawnedCount] = GenerateRotation(); if (m_customData != null) { m_customData[spawnedCount] = GenerateCustomData(); } spawnedCount++; } } }
private void UpdateComputeShader() { m_cachedCameraData.Set(m_mainCamera.nearClipPlane, m_mainCamera.farClipPlane, m_mainCamera.fieldOfView * Mathf.Deg2Rad, m_mainCamera.aspect); InstancingUtilities.GetFrustumPlanes(m_frustumPlanes, m_mainCamera); InstancingUtilities.UnrollFloats(m_frustumPlanes, m_frustumPlanesUnrolled); InstancingUtilities.UnrollFloats(m_mainCamera.transform.localToWorldMatrix, m_cameraToWorldMatrixUnrolled); //Used to linearize Z buffer values. x is (1 - far / near), y is (far / near), z is (x / far) and w is (y / far). float farOverNear = m_mainCamera.farClipPlane / m_mainCamera.nearClipPlane; Vector4 _ZBufferParams = new Vector4(1f - farOverNear, farOverNear, 1, 1); m_computeShader.SetTextureFromGlobal(m_cachedComputeMaxDepthKernel, "_DepthTexture", "_CameraDepthTexture"); m_computeShader.SetVector("_ZBufferParams", _ZBufferParams); m_computeShader.SetFloat("maxShadowRange", m_maxShadowRange); m_computeShader.SetInt("yAxisDownsample", m_yAxisDownsample); m_computeShader.SetFloats("frustumPlanes", m_frustumPlanesUnrolled); m_computeShader.SetVector("camData", m_cachedCameraData); m_computeShader.SetFloats("cameraToWorldMatrix", m_cameraToWorldMatrixUnrolled); m_computeShader.SetVector("lightDir", m_directionalLight.transform.forward); }
public void GenerateGridInstances() { Terrain t = Terrain.activeTerrain; Vector3 terrainSize = t.terrainData.size; Vector3[] totalSpawnedInstances = new Vector3[0]; for (int i = 0; i < m_spawningRules.Length; i++) { int sqrtMaxInstances = Mathf.CeilToInt(Mathf.Sqrt(Mathf.Abs((terrainSize.x * terrainSize.z * m_spawningRules[i].m_instanceDensity / 100f)))); float stepSize = 1f / sqrtMaxInstances; float maxJitter1D = Mathf.Clamp01(m_spawningRules[i].m_gridJitter) * stepSize * 0.5f; //divide by 2 because we use jitter as +/- Vector3 maxJitter = new Vector3(maxJitter1D, 0f, maxJitter1D); maxJitter.Scale(terrainSize); //the jitter needs to be in world size Vector3[] possibleInstances = new Vector3[sqrtMaxInstances * sqrtMaxInstances]; int spawnCount = 0; //Unity terrains do not have their origin at the center, but rather at the bottom left hand side, this is why the for loops can start from 0 for (int x = 0; x < sqrtMaxInstances; x++) { for (int z = 0; z < sqrtMaxInstances; z++) { float worldStepX = x * stepSize * terrainSize.x; float worldStepZ = z * stepSize * terrainSize.z; Vector3 pos = new Vector3(t.GetPosition().x + worldStepX, 0, t.GetPosition().z + worldStepZ); pos += new Vector3(Random.Range(-1f, 1f) * maxJitter.x, 0, Random.Range(-1f, 1f) * maxJitter.z); if (m_spawningRules[i].m_layer != -1) { Color layerWeight = new Color(0, 0, 0, 0); if (GetSplatWeightAtLocation(pos, t, ref layerWeight)) { if (layerWeight[m_spawningRules[i].m_layer] > 0 && layerWeight[m_spawningRules[i].m_layer] > Random.Range(0f, 1f)) { //we can successfully generate something now! possibleInstances[spawnCount] = pos; spawnCount++; } } } else if (m_spawningRules[i].m_layer == -1) { possibleInstances[spawnCount] = pos; spawnCount++; } } } totalSpawnedInstances = MergeArraysWithCount <Vector3>(totalSpawnedInstances, possibleInstances, spawnCount); } m_positions = new Vector4[totalSpawnedInstances.Length]; m_rotations = new Vector4[totalSpawnedInstances.Length]; if (m_UseCustomData) { m_customData = new Vector4[totalSpawnedInstances.Length]; } for (int i = 0; i < totalSpawnedInstances.Length; i++) { m_positions[i] = new Vector4(totalSpawnedInstances[i].x, totalSpawnedInstances[i].y, totalSpawnedInstances[i].z, InstancingUtilities.PackScaleVectorToFloat(GenerateScale())); m_rotations[i] = GenerateRotation(); if (m_customData != null) { m_customData[i] = GenerateCustomData(); } } m_instanceCount = totalSpawnedInstances.Length; Debug.Log("Number of instances generated: " + totalSpawnedInstances.Length); m_dataDirty = true; #if (UNITY_EDITOR) UnityEditor.EditorUtility.SetDirty(this); #endif }
private static void DrawHandle() { Tools.hidden = false; if (m_selectedInstancedAssets.Count > 0) { Tools.hidden = true; Vector2 lastSelectedInstance = m_lastSelectedInstancedObject; IndirectInstancedAsset asset = m_registeredInstancedAssets[(int)lastSelectedInstance.x]; Vector3 lastSelectedInstancePosition = asset.m_instanceData.m_positions[(int)lastSelectedInstance.y]; Vector4 vec4Rotation = asset.m_instanceData.m_rotations[(int)lastSelectedInstance.y]; Quaternion lastSelectedInstanceRotation = InstancingUtilities.QuaternionFromVector(vec4Rotation); if (Tools.pivotMode == PivotMode.Center) { Bounds selectedObjectsBounds = new Bounds(lastSelectedInstancePosition, Vector3.zero); for (int i = 0; i < m_selectedInstancedAssets.Count; i++) { lastSelectedInstance = m_selectedInstancedAssets[i]; asset = m_registeredInstancedAssets[(int)lastSelectedInstance.x]; lastSelectedInstancePosition = asset.m_instanceData.m_positions[(int)lastSelectedInstance.y]; selectedObjectsBounds.Encapsulate(lastSelectedInstancePosition); } for (int i = 0; i < Selection.transforms.Length; i++) { selectedObjectsBounds.Encapsulate(Selection.transforms[i].position); } lastSelectedInstancePosition = selectedObjectsBounds.center; } float handleSize = HandleUtility.GetHandleSize(lastSelectedInstancePosition); Quaternion previousRotation; if (Tools.pivotRotation == PivotRotation.Global) { previousRotation = Tools.handleRotation; } else { previousRotation = lastSelectedInstanceRotation; } EditorGUI.BeginChangeCheck(); Transform[] selectedGameObjects = Selection.transforms; switch (Tools.current) { case Tool.Move: if (m_currentEvent.type == EventType.MouseDown) { Debug.Log("Rebuilding initial lists."); //build a list of initial sizes of selected instances m_selectedInitialInstances.Clear(); for (int i = 0; i < m_selectedInstancedAssets.Count; i++) { Debug.Log("adding"); Vector2 currentInstance = m_selectedInstancedAssets[i]; Vector3 position = m_registeredInstancedAssets[(int)currentInstance.x].m_instanceData.m_positions[(int)currentInstance.y]; m_selectedInitialInstances.Add(position); Debug.Log("Count is: " + m_selectedInitialInstances.Count); } //build a list of initial sizes of selected game objects m_selectedInitialGameObjects.Clear(); for (int i = 0; i < selectedGameObjects.Length; i++) { Vector3 position = selectedGameObjects[i].localPosition; m_selectedInitialGameObjects.Add(position); } } Vector3 newPosition; if (Tools.pivotRotation == PivotRotation.Global) { newPosition = Handles.PositionHandle(lastSelectedInstancePosition, Quaternion.identity); } else { newPosition = Handles.PositionHandle(lastSelectedInstancePosition, lastSelectedInstanceRotation); } float xAxisMovement = newPosition.x - lastSelectedInstancePosition.x; float yAxisMovement = newPosition.y - lastSelectedInstancePosition.y; float zAxisMovement = newPosition.z - lastSelectedInstancePosition.z; if (EditorGUI.EndChangeCheck()) { UndoStateInstance.m_instance.m_lastUsedTool = Tool.Move; //set undo state here, else last used tool will change on mouse down and cause incorrect undo history based on tool swapping UndoStateInstance.m_instance.SetUndoState(m_selectedInitialInstances, m_selectedInstancedAssets); for (int i = 0; i < m_selectedInstancedAssets.Count; i++) { Vector2 currentInstance = m_selectedInstancedAssets[i]; IndirectInstancedAsset currentAsset = m_registeredInstancedAssets[(int)currentInstance.x]; Undo.RegisterCompleteObjectUndo(UndoStateInstance.m_instance, "Undo instanced move"); UndoStateInstance.m_instance.IncrementModifiedCounter(); if (Mathf.Abs(xAxisMovement) > 0.01f) { currentAsset.m_instanceData.m_positions[(int)currentInstance.y].x += xAxisMovement; } if (Mathf.Abs(yAxisMovement) > 0.01f) { currentAsset.m_instanceData.m_positions[(int)currentInstance.y].y += yAxisMovement; } if (Mathf.Abs(zAxisMovement) > 0.01f) { currentAsset.m_instanceData.m_positions[(int)currentInstance.y].z += zAxisMovement; } if (Mathf.Abs(xAxisMovement) > 0.01f || Mathf.Abs(yAxisMovement) > 0.01f || Mathf.Abs(zAxisMovement) > 0.01f) { currentAsset.AddDirtyPosition((int)currentInstance.y); } } Undo.RecordObjects(selectedGameObjects, "Undo game object move"); for (int i = 0; i < selectedGameObjects.Length; i++) { Vector3 displacedPosition = selectedGameObjects[i].position; if (Mathf.Abs(xAxisMovement) > 0.01f) { displacedPosition.x += xAxisMovement; } if (Mathf.Abs(yAxisMovement) > 0.01f) { displacedPosition.y += yAxisMovement; } if (Mathf.Abs(zAxisMovement) > 0.01f) { displacedPosition.z += zAxisMovement; } selectedGameObjects[i].position = displacedPosition; } } break; case Tool.Rotate: //allows rotation back to (0,0,0) with shift + n if (m_currentEvent.keyCode == KeyCode.N && m_currentEvent.shift) { for (int i = 0; i < m_selectedInstancedAssets.Count; i++) { Vector2 currentInstance = m_selectedInstancedAssets[i]; IndirectInstancedAsset currentAsset = m_registeredInstancedAssets[(int)currentInstance.x]; currentAsset.m_instanceData.m_rotations[(int)currentInstance.y] = new Vector4(0, 0, 0, 1); //The identity quaternion currentAsset.AddDirtyRotation((int)currentInstance.y); } //also reset the gizmo, this isnt really needed as the next frame will already be correct and 1 frame is not noticeable, but added for consistency Tools.handleRotation = Quaternion.identity; previousRotation = Quaternion.identity; } if (m_currentEvent.type == EventType.MouseDown) { Debug.Log("Rebuilding initial lists."); //build a list of initial sizes of selected instances m_selectedInitialInstances.Clear(); for (int i = 0; i < m_selectedInstancedAssets.Count; i++) { Vector2 currentInstance = m_selectedInstancedAssets[i]; Vector4 rotation = m_registeredInstancedAssets[(int)currentInstance.x].m_instanceData.m_rotations[(int)currentInstance.y]; m_selectedInitialInstances.Add(rotation); } //build a list of initial sizes of selected game objects m_selectedInitialGameObjects.Clear(); for (int i = 0; i < selectedGameObjects.Length; i++) { Vector4 rotation = InstancingUtilities.VectorFromQuaternion(selectedGameObjects[i].rotation); m_selectedInitialGameObjects.Add(rotation); } } Quaternion newRotation = Handles.RotationHandle(previousRotation, lastSelectedInstancePosition); //The new rotation value modified by the user's interaction with the handle. if (EditorGUI.EndChangeCheck()) { UndoStateInstance.m_instance.m_lastUsedTool = Tool.Rotate; UndoStateInstance.m_instance.SetUndoState(m_selectedInitialInstances, m_selectedInstancedAssets); Quaternion delta = Quaternion.Inverse(previousRotation) * newRotation; for (int i = 0; i < m_selectedInstancedAssets.Count; i++) { Vector2 currentInstance = m_selectedInstancedAssets[i]; IndirectInstancedAsset currentAsset = m_registeredInstancedAssets[(int)currentInstance.x]; Quaternion instancedObjectRotation = InstancingUtilities.QuaternionFromVector(currentAsset.m_instanceData.m_rotations[(int)currentInstance.y]); Undo.RegisterCompleteObjectUndo(UndoStateInstance.m_instance, "Undo instanced rotation"); UndoStateInstance.m_instance.IncrementModifiedCounter(); //lhs happens first, so if we want a local space rotation, we do a delta rotation in the objects frame of reference by object quaternion on lhs //if we want a world space rotation, then lhs is the delta, and the objects rotation happens after, in the world space frame of reference if (Tools.pivotRotation == PivotRotation.Local) { instancedObjectRotation = instancedObjectRotation * delta; } else { instancedObjectRotation = delta * instancedObjectRotation; } currentAsset.m_instanceData.m_rotations[(int)currentInstance.y] = InstancingUtilities.VectorFromQuaternion(instancedObjectRotation); currentAsset.AddDirtyRotation((int)currentInstance.y); } Undo.RecordObjects(selectedGameObjects, "Undo game object rotation"); for (int i = 0; i < selectedGameObjects.Length; i++) { Quaternion gameObjectRotation = selectedGameObjects[i].rotation; if (Tools.pivotRotation == PivotRotation.Local) { gameObjectRotation = gameObjectRotation * delta; } else { gameObjectRotation = delta * gameObjectRotation; } selectedGameObjects[i].rotation = gameObjectRotation; } //https://math.stackexchange.com/questions/40164/how-do-you-rotate-a-vector-by-a-unit-quaternion Tools.handleRotation = newRotation; } break; case Tool.Scale: //allows scaling back to (1,1,1) with shift + n if (m_currentEvent.keyCode == KeyCode.N && m_currentEvent.shift) { for (int i = 0; i < m_selectedInstancedAssets.Count; i++) { Vector2 currentInstance = m_selectedInstancedAssets[i]; IndirectInstancedAsset currentAsset = m_registeredInstancedAssets[(int)currentInstance.x]; currentAsset.m_instanceData.m_positions[(int)currentInstance.y].w = InstancingUtilities.PackScaleVectorToFloat(Vector3.one); currentAsset.AddDirtyScale((int)currentInstance.y); } } if (m_currentEvent.type == EventType.MouseDown) { m_currentScale = Vector3.one; Debug.Log("Rebuilding initial lists."); //build a list of initial sizes of selected instances m_selectedInitialInstances.Clear(); for (int i = 0; i < m_selectedInstancedAssets.Count; i++) { Vector2 currentInstance = m_selectedInstancedAssets[i]; float scale = m_registeredInstancedAssets[(int)currentInstance.x].m_instanceData.m_positions[(int)currentInstance.y].w; m_selectedInitialInstances.Add(new Vector4(scale, 0, 0, 0)); } //build a list of initial sizes of selected game objects m_selectedInitialGameObjects.Clear(); for (int i = 0; i < selectedGameObjects.Length; i++) { Vector3 scale = selectedGameObjects[i].localScale; m_selectedInitialGameObjects.Add(scale); } } Vector3 newScale = Handles.ScaleHandle(m_currentScale, lastSelectedInstancePosition, lastSelectedInstanceRotation, handleSize); if (EditorGUI.EndChangeCheck()) { UndoStateInstance.m_instance.m_lastUsedTool = Tool.Scale; UndoStateInstance.m_instance.SetUndoState(m_selectedInitialInstances, m_selectedInstancedAssets); m_currentScale = newScale; for (int i = 0; i < m_selectedInstancedAssets.Count; i++) { Vector2 currentInstance = m_selectedInstancedAssets[i]; IndirectInstancedAsset currentAsset = m_registeredInstancedAssets[(int)currentInstance.x]; Undo.RegisterCompleteObjectUndo(UndoStateInstance.m_instance, "Undo instanced scaling"); UndoStateInstance.m_instance.IncrementModifiedCounter(); currentAsset.m_instanceData.ModifyScale((int)currentInstance.y, m_currentScale, m_selectedInitialInstances[i].x); currentAsset.AddDirtyScale((int)currentInstance.y); } Undo.RecordObjects(selectedGameObjects, "Undo game object scaling"); for (int i = 0; i < selectedGameObjects.Length; i++) { Vector3 objectScale = InstancingUtilities.MultiplyVector3(m_selectedInitialGameObjects[i], m_currentScale); selectedGameObjects[i].localScale = objectScale; } } break; } } }
private void UpdateComputeShader() { if (m_debugAppendCount) { m_argsBuffersArray[0][0].GetData(m_argsArray[0][0]); m_argsBuffersArray[1][0].GetData(m_argsArray[1][0]); m_argsBuffersArray[2][0].GetData(m_argsArray[2][0]); Debug.Log("Previous frame append count: " + m_argsArray[0][0][1].ToString("f3") + " and lod1: " + m_argsArray[1][0][1].ToString("f3") + " and lod2: " + m_argsArray[2][0][1].ToString("f3")); } #if UNITY_EDITOR if (m_dirtyPositionInstances.Count > 0 || m_dirtyRotationInstances.Count > 0 || m_dirtyScaleInstances.Count > 0) { if (m_dirtyPositionInstances.Count > 0 || m_dirtyScaleInstances.Count > 0) { m_positionBuffer.SetData(m_instanceData.m_positions); m_dirtyPositionInstances.Clear(); m_dirtyScaleInstances.Clear(); } if (m_dirtyRotationInstances.Count > 0) { m_rotationBuffer.SetData(m_instanceData.m_rotations); m_dirtyRotationInstances.Clear(); } } #endif InstancingUtilities.GetFrustumPlanes(m_frustumPlanes, m_mainCamera); Vector4 screenSpaceLODSize = Vector4.zero; for (int i = 0; i < m_cachedNumLods; i++) { screenSpaceLODSize[i] = Mathf.Pow((m_LodSettings[i].screenSize * 0.5f), 2); } Vector4 frustumBoundingSphere = InstancingUtilities.GenerateFrustumBoundingSphere(m_mainCamera, m_coarseCullFarDistance); int[] shadowSettingsArray = new int[m_cachedNumLods]; for (int i = 0; i < m_cachedNumLods; i++) { shadowSettingsArray[i] = (int)m_LodSettings[i].shadowSetting; } InstancingUtilities.UnrollFloats(m_frustumPlanes, m_frustumPlanesUnrolled); InstancingUtilities.UnrollFloats(m_shadowRegionPlanes, m_shadowRegionPlanesUnrolled); InstancingUtilities.UnrollFloats(m_mainCamera.projectionMatrix, m_cameraProjectionMatrixUnrolled); m_computeShader.SetVector("cameraData", m_mainCamera.transform.position); m_computeShader.SetFloats("cameraProjectionMatrix", m_cameraProjectionMatrixUnrolled); m_computeShader.SetFloats("frustumPlanes", m_frustumPlanesUnrolled); m_computeShader.SetFloats("shadowRegionPlanes", m_shadowRegionPlanesUnrolled); m_computeShader.SetVector("screenSpaceLODSize", screenSpaceLODSize); //should not occur every update m_computeShader.SetFloat("Time", Time.time); m_computeShader.SetInts("castShadowsLOD", shadowSettingsArray); //should not occur every update m_computeShader.SetVector("frustumBoundingSphere", frustumBoundingSphere); for (int i = 0; i < m_cachedNumLods; i++) { m_appendBuffers[i].SetCounterValue(0); } m_computeShader.Dispatch(m_cachedComputeKernel, Mathf.CeilToInt(m_instanceCount / 256f), 1, 1); for (int i = 0; i < m_cachedNumLods; i++) { for (int j = 0; j < m_LodSettings[i].mesh.subMeshCount; j++) { ComputeBuffer.CopyCount(m_appendBuffers[i], m_argsBuffersArray[i][j], 1 * sizeof(uint)); } } }
private void InitComputeShader() { m_instanceCount = m_instanceData.m_instanceCount; m_shadowRegionBuffer = m_shadowCullingManager._m_shadowRegionPlanes; m_computeShader.SetBuffer(m_cachedShadowComputeKernel, "gpuShadowRegionPlanes", m_shadowRegionBuffer); for (int i = 0; i < m_cachedNumLods; i++) { //create the append buffer for a given lod and bind it to the two compute kernels and all materials of that lod m_appendBuffers[i] = new ComputeBuffer(m_instanceCount, 36 * sizeof(float), ComputeBufferType.Counter); m_computeShader.SetBuffer(m_cachedComputeKernel, "lod" + i + "Buffer", m_appendBuffers[i]); m_computeShader.SetBuffer(m_cachedShadowComputeKernel, "lod" + i + "Buffer", m_appendBuffers[i]); //we can cache the strings for performance for (int j = 0; j < m_materials[i].Length; j++) { m_materials[i][j].SetBuffer("batchDataBuffer", m_appendBuffers[i]); } } m_positionBuffer = new ComputeBuffer(m_instanceCount, 4 * sizeof(float)); m_rotationBuffer = new ComputeBuffer(m_instanceCount, 4 * sizeof(float)); if (m_instanceData.m_UseCustomData) { m_customDataBuffer = new ComputeBuffer(m_instanceCount, 4 * sizeof(float)); } else { m_customDataBuffer = null; } for (int i = 0; i < m_cachedNumLods; i++) { for (int j = 0; j < m_LodSettings[i].mesh.subMeshCount; j++) { m_argsArray[i][j] = new uint[5]; m_argsBuffersArray[i][j] = new ComputeBuffer(1, m_argsArray[i][j].Length * sizeof(uint), ComputeBufferType.IndirectArguments); m_argsArray[i][j][0] = (uint)m_LodSettings[i].mesh.GetIndexCount(j); // - index count per instance, m_argsArray[i][j][1] = (uint)m_instanceCount; // - instance count, m_argsArray[i][j][2] = (uint)m_LodSettings[i].mesh.GetIndexStart(j); // - start index location, m_argsArray[i][j][3] = (uint)0; // - base vertex location m_argsArray[i][j][4] = (uint)0; // - start instance location. m_argsBuffersArray[i][j].SetData(m_argsArray[i][j]); } } m_instanceData.m_dataDirty = false; #if (UNITY_EDITOR) if (!Application.isPlaying) { SceneViewInstancing.UnregisterIndirectInstancedAsset(this); SceneViewInstancing.RegisterIndirectInstancedAsset(this); } #endif m_positions = m_instanceData.m_positions; m_rotations = m_instanceData.m_rotations; m_customData = m_instanceData.m_customData; Vector4 aabbExtents = m_LodSettings[0].mesh.bounds.extents; aabbExtents.w = InstancingUtilities.BoundingSphereFromAABB(aabbExtents.x, aabbExtents.y, aabbExtents.z); Vector4 aabbCenter = m_LodSettings[0].mesh.bounds.center; Vector4 screenSpaceLODSize = Vector4.zero; for (int i = 0; i < m_cachedNumLods; i++) { screenSpaceLODSize[i] = Mathf.Pow((m_LodSettings[i].screenSize * 0.5f), 2); } Vector2 screenDim = new Vector2(m_mainCamera.pixelWidth, m_mainCamera.pixelHeight); m_computeShader.SetVector("boundingExtents", aabbExtents); m_computeShader.SetVector("boundingCenter", aabbCenter); m_computeShader.SetVector("screenSpaceLODSize", screenSpaceLODSize); m_computeShader.SetVector("screenDim", screenDim); m_computeShader.SetInt("numLODs", (int)m_cachedNumLods); int[] shadowSettingsArray = new int[m_cachedNumLods]; for (int i = 0; i < m_cachedNumLods; i++) { shadowSettingsArray[i] = (int)m_LodSettings[i].shadowSetting; } m_computeShader.SetInts("castShadowsLOD", shadowSettingsArray); m_positionBuffer.SetData(m_positions); m_rotationBuffer.SetData(m_rotations); if (m_customDataBuffer != null) { m_customDataBuffer.SetData(m_customData); } m_computeShader.SetBuffer(m_cachedComputeKernel, "rotationBuffer", m_rotationBuffer); m_computeShader.SetBuffer(m_cachedComputeKernel, "positionBuffer", m_positionBuffer); if (m_customDataBuffer != null) { m_computeShader.SetBuffer(m_cachedComputeKernel, "customDataBuffer", m_customDataBuffer); } m_computeShader.SetBuffer(m_cachedShadowComputeKernel, "rotationBuffer", m_rotationBuffer); m_computeShader.SetBuffer(m_cachedShadowComputeKernel, "positionBuffer", m_positionBuffer); if (m_customDataBuffer != null) { m_computeShader.SetBuffer(m_cachedShadowComputeKernel, "customDataBuffer", m_customDataBuffer); } }