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++;
                }
            }
        }
Example #4
0
        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
        }
Example #6
0
        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;
                }
            }
        }
Example #7
0
        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));
                }
            }
        }
Example #8
0
        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);
            }
        }