public void DestroyDecalEntity(DecalEntity decalEntity)
        {
            if (!m_DecalEntityIndexer.IsValid(decalEntity))
            {
                return;
            }

            var decalItem = m_DecalEntityIndexer.GetItem(decalEntity);

            m_DecalEntityIndexer.DestroyDecalEntity(decalEntity);

            int chunkIndex = decalItem.chunkIndex;
            int arrayIndex = decalItem.arrayIndex;

            DecalEntityChunk   entityChunk   = entityChunks[chunkIndex];
            DecalCachedChunk   cachedChunk   = cachedChunks[chunkIndex];
            DecalCulledChunk   culledChunk   = culledChunks[chunkIndex];
            DecalDrawCallChunk drawCallChunk = drawCallChunks[chunkIndex];

            int lastArrayIndex = entityChunk.count - 1;

            if (arrayIndex != lastArrayIndex)
            {
                m_DecalEntityIndexer.UpdateIndex(entityChunk.decalEntities[lastArrayIndex], arrayIndex);
            }

            entityChunk.RemoveAtSwapBack(arrayIndex);
            cachedChunk.RemoveAtSwapBack(arrayIndex);
            culledChunk.RemoveAtSwapBack(arrayIndex);
            drawCallChunk.RemoveAtSwapBack(arrayIndex);
        }
Example #2
0
        private void Execute(DecalEntityChunk entityChunk, DecalCachedChunk cachedChunk, int count)
        {
            if (count == 0)
            {
                return;
            }

            cachedChunk.currentJobHandle.Complete();

            // Make sure draw order is up to date
            var material = entityChunk.material;

            if (material.HasProperty("_DrawOrder"))
            {
                cachedChunk.drawOrder = material.GetInt("_DrawOrder");
            }

            // Shader can change any time in editor, so we have to update passes each time
#if !UNITY_EDITOR
            if (!cachedChunk.isCreated)
#endif
            {
                int passIndexDBuffer = material.FindPass(DecalShaderPassNames.DBufferProjector);
                cachedChunk.passIndexDBuffer = passIndexDBuffer;

                int passIndexEmissive = material.FindPass(DecalShaderPassNames.DecalProjectorForwardEmissive);
                cachedChunk.passIndexEmissive = passIndexEmissive;

                int passIndexScreenSpace = material.FindPass(DecalShaderPassNames.DecalScreenSpaceProjector);
                cachedChunk.passIndexScreenSpace = passIndexScreenSpace;

                int passIndexGBuffer = material.FindPass(DecalShaderPassNames.DecalGBufferProjector);
                cachedChunk.passIndexGBuffer = passIndexGBuffer;

                cachedChunk.isCreated = true;
            }

            using (new ProfilingScope(null, m_SamplerJob))
            {
                UpdateTransformsJob updateTransformJob = new UpdateTransformsJob()
                {
                    positions       = cachedChunk.positions,
                    rotations       = cachedChunk.rotation,
                    scales          = cachedChunk.scales,
                    dirty           = cachedChunk.dirty,
                    scaleModes      = cachedChunk.scaleModes,
                    sizeOffsets     = cachedChunk.sizeOffsets,
                    decalToWorlds   = cachedChunk.decalToWorlds,
                    normalToWorlds  = cachedChunk.normalToWorlds,
                    boundingSpheres = cachedChunk.boundingSpheres,
                    minDistance     = 0.0001f,
                };

                var handle = updateTransformJob.Schedule(entityChunk.transformAccessArray);
                cachedChunk.currentJobHandle = handle;
            }
        }
        public DecalEntity CreateDecalEntity(DecalProjector decalProjector)
        {
            var material = decalProjector.material;

            if (material == null)
            {
                material = errorMaterial;
            }

            using (new ProfilingScope(null, m_AddDecalSampler))
            {
                int chunkIndex  = CreateChunkIndex(material);
                int entityIndex = entityChunks[chunkIndex].count;

                DecalEntity entity = m_DecalEntityIndexer.CreateDecalEntity(entityIndex, chunkIndex);

                DecalEntityChunk   entityChunk   = entityChunks[chunkIndex];
                DecalCachedChunk   cachedChunk   = cachedChunks[chunkIndex];
                DecalCulledChunk   culledChunk   = culledChunks[chunkIndex];
                DecalDrawCallChunk drawCallChunk = drawCallChunks[chunkIndex];

                // Make sure we have space to add new entity
                if (entityChunks[chunkIndex].capacity == entityChunks[chunkIndex].count)
                {
                    using (new ProfilingScope(null, m_ResizeChunks))
                    {
                        int newCapacity = entityChunks[chunkIndex].capacity + entityChunks[chunkIndex].capacity;
                        newCapacity = math.max(8, newCapacity);

                        entityChunk.SetCapacity(newCapacity);
                        cachedChunk.SetCapacity(newCapacity);
                        culledChunk.SetCapacity(newCapacity);
                        drawCallChunk.SetCapacity(newCapacity);
                    }
                }

                entityChunk.Push();
                cachedChunk.Push();
                culledChunk.Push();
                drawCallChunk.Push();

                entityChunk.decalProjectors[entityIndex] = decalProjector;
                entityChunk.decalEntities[entityIndex]   = entity;
                entityChunk.transformAccessArray.Add(decalProjector.transform);

                UpdateDecalEntityData(entity, decalProjector);

                return(entity);
            }
        }
        public void UpdateDecalEntityData(DecalEntity decalEntity, DecalProjector decalProjector)
        {
            var decalItem = m_DecalEntityIndexer.GetItem(decalEntity);

            int chunkIndex = decalItem.chunkIndex;
            int arrayIndex = decalItem.arrayIndex;

            DecalCachedChunk cachedChunk = cachedChunks[chunkIndex];

            cachedChunk.sizeOffsets[arrayIndex] = Matrix4x4.Translate(decalProjector.decalOffset) * Matrix4x4.Scale(decalProjector.decalSize);

            float   drawDistance   = decalProjector.drawDistance;
            float   fadeScale      = decalProjector.fadeScale;
            float   startAngleFade = decalProjector.startAngleFade;
            float   endAngleFade   = decalProjector.endAngleFade;
            Vector4 uvScaleBias    = decalProjector.uvScaleBias;
            int     layerMask      = decalProjector.gameObject.layer;
            ulong   sceneLayerMask = decalProjector.gameObject.sceneCullingMask;
            float   fadeFactor     = decalProjector.fadeFactor;

            cachedChunk.drawDistances[arrayIndex] = new Vector2(drawDistance, fadeScale);
            // In the shader to remap from cosine -1 to 1 to new range 0..1  (with 0 - 0 degree and 1 - 180 degree)
            // we do 1.0 - (dot() * 0.5 + 0.5) => 0.5 * (1 - dot())
            // we actually square that to get smoother result => x = (0.5 - 0.5 * dot())^2
            // Do a remap in the shader. 1.0 - saturate((x - start) / (end - start))
            // After simplification => saturate(a + b * dot() * (dot() - 2.0))
            // a = 1.0 - (0.25 - start) / (end - start), y = - 0.25 / (end - start)
            if (startAngleFade == 180.0f) // angle fade is disabled
            {
                cachedChunk.angleFades[arrayIndex] = new Vector2(0.0f, 0.0f);
            }
            else
            {
                float angleStart = startAngleFade / 180.0f;
                float angleEnd   = endAngleFade / 180.0f;
                var   range      = Mathf.Max(0.0001f, angleEnd - angleStart);
                cachedChunk.angleFades[arrayIndex] = new Vector2(1.0f - (0.25f - angleStart) / range, -0.25f / range);
            }
            cachedChunk.uvScaleBias[arrayIndex]     = uvScaleBias;
            cachedChunk.layerMasks[arrayIndex]      = layerMask;
            cachedChunk.sceneLayerMasks[arrayIndex] = sceneLayerMask;
            cachedChunk.fadeFactors[arrayIndex]     = fadeFactor;
            cachedChunk.scaleModes[arrayIndex]      = decalProjector.scaleMode;

            cachedChunk.positions[arrayIndex] = decalProjector.transform.position;
            cachedChunk.rotation[arrayIndex]  = decalProjector.transform.rotation;
            cachedChunk.scales[arrayIndex]    = decalProjector.transform.lossyScale;
            cachedChunk.dirty[arrayIndex]     = true;
        }
Example #5
0
        public void Execute(DecalCachedChunk cachedChunk, DecalCulledChunk culledChunk, int count)
        {
            cachedChunk.currentJobHandle.Complete();

            CullingGroup cullingGroup = culledChunk.cullingGroups;

            cullingGroup.targetCamera = m_Camera;
            cullingGroup.SetDistanceReferencePoint(m_Camera.transform.position);
            cullingGroup.SetBoundingDistances(m_BoundingDistance);
            cachedChunk.boundingSpheres.CopyTo(cachedChunk.boundingSphereArray);
            cullingGroup.SetBoundingSpheres(cachedChunk.boundingSphereArray);
            cullingGroup.SetBoundingSphereCount(count);

            culledChunk.cameraPosition = m_Camera.transform.position;
            culledChunk.cullingMask    = m_Camera.cullingMask;
#if UNITY_EDITOR
            culledChunk.sceneCullingMask = GetSceneCullingMaskFromCamera(m_Camera);
#endif
        }
Example #6
0
        private void Draw(CommandBuffer cmd, DecalEntityChunk decalEntityChunk, DecalCachedChunk decalCachedChunk, DecalDrawCallChunk decalDrawCallChunk, int passIndex)
        {
            var mesh     = m_EntityManager.decalProjectorMesh;
            var material = GetMaterial(decalEntityChunk);

            decalCachedChunk.propertyBlock.SetVector("unity_LightData", new Vector4(1, 1, 1, 0)); // GetMainLight requires z component to be set

            int subCallCount = decalDrawCallChunk.subCallCount;

            for (int i = 0; i < subCallCount; ++i)
            {
                var subCall = decalDrawCallChunk.subCalls[i];

                for (int j = subCall.start; j < subCall.end; ++j)
                {
                    decalCachedChunk.propertyBlock.SetMatrix("_NormalToWorld", decalDrawCallChunk.normalToDecals[j]);
                    cmd.DrawMesh(mesh, decalDrawCallChunk.decalToWorlds[j], material, 0, passIndex, decalCachedChunk.propertyBlock);
                }
            }
        }
        protected override int GetPassIndex(DecalCachedChunk decalCachedChunk)
        {
            switch (m_Technique)
            {
            case DecalTechnique.DBuffer:
                return(((decalCachedChunk.passIndexDBuffer == -1) && (decalCachedChunk.passIndexEmissive == -1)) ? 0 : -1);

            case DecalTechnique.ScreenSpace:
                return(decalCachedChunk.passIndexScreenSpace == -1 ? 0 : -1);

            case DecalTechnique.GBuffer:
                return(decalCachedChunk.passIndexGBuffer == -1 ? 0 : -1);

            case DecalTechnique.Invalid:
                return(0);

            default:
                return(0);
            }
        }
Example #8
0
        private void Execute(CommandBuffer cmd, DecalEntityChunk decalEntityChunk, DecalCachedChunk decalCachedChunk, DecalDrawCallChunk decalDrawCallChunk, int count)
        {
            decalCachedChunk.currentJobHandle.Complete();
            decalDrawCallChunk.currentJobHandle.Complete();

            Material material  = GetMaterial(decalEntityChunk);
            int      passIndex = GetPassIndex(decalCachedChunk);

            if (count == 0 || passIndex == -1 || material == null)
            {
                return;
            }

            if (SystemInfo.supportsInstancing && material.enableInstancing)
            {
                DrawInstanced(cmd, decalEntityChunk, decalCachedChunk, decalDrawCallChunk, passIndex);
            }
            else
            {
                Draw(cmd, decalEntityChunk, decalCachedChunk, decalDrawCallChunk, passIndex);
            }
        }
 protected override int GetPassIndex(DecalCachedChunk decalCachedChunk) => decalCachedChunk.passIndexGBuffer;
 protected override int GetPassIndex(DecalCachedChunk decalCachedChunk) => decalCachedChunk.passIndexEmissive;
Example #11
0
        private void DrawInstanced(CommandBuffer cmd, DecalEntityChunk decalEntityChunk, DecalCachedChunk decalCachedChunk, DecalDrawCallChunk decalDrawCallChunk, int passIndex)
        {
            var mesh     = m_EntityManager.decalProjectorMesh;
            var material = GetMaterial(decalEntityChunk);

            decalCachedChunk.propertyBlock.SetVector("unity_LightData", new Vector4(1, 1, 1, 0)); // GetMainLight requires z component to be set

            int subCallCount = decalDrawCallChunk.subCallCount;

            for (int i = 0; i < subCallCount; ++i)
            {
                var subCall = decalDrawCallChunk.subCalls[i];

                var decalToWorldSlice = decalDrawCallChunk.decalToWorlds.Reinterpret <Matrix4x4>();
                NativeArray <Matrix4x4> .Copy(decalToWorldSlice, subCall.start, m_WorldToDecals, 0, subCall.count);

                var normalToWorldSlice = decalDrawCallChunk.normalToDecals.Reinterpret <Matrix4x4>();
                NativeArray <Matrix4x4> .Copy(normalToWorldSlice, subCall.start, m_NormalToDecals, 0, subCall.count);

                decalCachedChunk.propertyBlock.SetMatrixArray("_NormalToWorld", m_NormalToDecals);
                cmd.DrawMeshInstanced(mesh, 0, material, passIndex, m_WorldToDecals, subCall.end - subCall.start, decalCachedChunk.propertyBlock);
            }
        }
Example #12
0
 protected abstract int GetPassIndex(DecalCachedChunk decalCachedChunk);
Example #13
0
 protected override int GetPassIndex(DecalCachedChunk decalCachedChunk) => decalCachedChunk.passIndexScreenSpace;