// Here you can implement the rendering logic.
            // Use <c>ScriptableRenderContext</c> to issue drawing commands or execute command buffers
            // https://docs.unity3d.com/ScriptReference/Rendering.ScriptableRenderContext.html
            // You don't have to call ScriptableRenderContext.submit, the render pipeline will call it at specific points in the pipeline.
            public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
            {
                var cmd = CommandBufferPool.Get(profilerSampler.name);

                renderBounds   = StylizedGrassRenderer.Instance.bounds;
                frustrumPlanes = GeometryUtility.CalculateFrustumPlanes(StylizedGrassRenderer.Instance.renderCam);

                using (new ProfilingScope(cmd, profilerSampler))
                {
                    foreach (KeyValuePair <int, List <GrassBender> > layer in StylizedGrassRenderer.GrassBenders)
                    {
                        foreach (GrassBender b in layer.Value)
                        {
                            if (b.enabled == false)
                            {
                                continue;
                            }

                            props.SetVector("_Params", new Vector4(b.strength, b.heightOffset, b.pushStrength, b.scaleMultiplier));

                            if (b.benderType == GrassBenderBase.BenderType.Trail)
                            {
                                if (!b.trailRenderer)
                                {
                                    continue;
                                }

                                if (!b.trailRenderer.emitting)
                                {
                                    continue;
                                }

                                if (!GeometryUtility.TestPlanesAABB(frustrumPlanes, b.trailRenderer.bounds))
                                {
                                    continue;
                                }

                                m_TrailRenderer = b.trailRenderer;
                                m_TrailRenderer.SetPropertyBlock(props);

                                //Trail
                                m_TrailRenderer.emitting             = b.gameObject.activeInHierarchy;
                                m_TrailRenderer.generateLightingData = true;
                                m_TrailRenderer.widthMultiplier      = b.trailRadius;
                                m_TrailRenderer.time = b.trailLifetime;
                                m_TrailRenderer.minVertexDistance = b.trailAccuracy;
                                m_TrailRenderer.widthCurve        = b.widthOverLifetime;
                                m_TrailRenderer.colorGradient     = GrassBenderBase.GetGradient(b.strengthOverLifetime);

                                //If disabled, temporarly enable in order to bake mesh
                                trailEnabled = m_TrailRenderer.enabled ? true : false;
                                if (!trailEnabled)
                                {
                                    m_TrailRenderer.enabled = true;
                                }

                                if (b.bakedMesh == null)
                                {
                                    b.bakedMesh = new Mesh();
                                }
                                m_TrailRenderer.BakeMesh(b.bakedMesh, renderingData.cameraData.camera, false);

                                cmd.DrawMesh(b.bakedMesh, Matrix4x4.identity, GrassBenderBase.TrailMaterial, 0, 0, props);

                                //Note: Faster, but crashed when trails are disabled (Case 1200430)
                                //cmd.DrawRenderer(m_TrailRenderer, GrassBenderBase.TrailMaterial, 0, 0);

                                if (!trailEnabled)
                                {
                                    m_TrailRenderer.enabled = false;
                                }

                                //trailMesh.Clear();
                            }
                            if (b.benderType == GrassBenderBase.BenderType.ParticleSystem)
                            {
                                if (!b.particleSystem)
                                {
                                    continue;
                                }

                                if (!GeometryUtility.TestPlanesAABB(frustrumPlanes, b.particleRenderer.bounds))
                                {
                                    continue;
                                }

                                m_ParticleRenderer = b.particleRenderer;
                                m_ParticleRenderer.SetPropertyBlock(props);

                                var grad = b.particleSystem.colorOverLifetime;
                                grad.enabled = true;
                                grad.color   = GrassBenderBase.GetGradient(b.strengthOverLifetime);
                                bool localSpace = b.particleSystem.main.simulationSpace == ParticleSystemSimulationSpace.Local;

                                //Note: DrawRenderes with particle systems appear to be broken. Only renders to scene cam when it redraws. Bake the mesh down and render it instead.
                                //Todo: Create repo project and file bug report.
                                //cmd.DrawRenderer(m_ParticleRenderer, m_Material, 0, 0);
                                if (!b.bakedMesh)
                                {
                                    b.bakedMesh = new Mesh();
                                }
                                m_ParticleRenderer.BakeMesh(b.bakedMesh, renderingData.cameraData.camera);

                                cmd.DrawMesh(b.bakedMesh, localSpace ? m_ParticleRenderer.localToWorldMatrix : Matrix4x4.identity, GrassBenderBase.MeshMaterial, 0, b.alphaBlending ? 1 : 0, props);

                                //Also draw particle trails
                                if (b.hasParticleTrails)
                                {
                                    if (!b.particleTrailMesh)
                                    {
                                        b.particleTrailMesh = new Mesh();
                                    }

                                    m_ParticleRenderer.BakeTrailsMesh(b.particleTrailMesh, renderingData.cameraData.camera);
                                    cmd.DrawMesh(b.particleTrailMesh, m_ParticleRenderer.localToWorldMatrix, GrassBenderBase.TrailMaterial, 1, 0, props);
                                    //cmd.DrawRenderer(m_ParticleRenderer, GrassBenderBase.TrailMaterial, 1, 0);
                                }
                            }
                            if (b.benderType == GrassBenderBase.BenderType.Mesh)
                            {
                                if (!b.meshRenderer)
                                {
                                    continue;
                                }

                                if (!GeometryUtility.TestPlanesAABB(frustrumPlanes, b.meshRenderer.bounds))
                                {
                                    continue;
                                }

                                m_MeshRenderer = b.meshRenderer;
                                m_MeshRenderer.SetPropertyBlock(props);

                                cmd.DrawRenderer(m_MeshRenderer, GrassBenderBase.MeshMaterial, 0, b.alphaBlending ? 1 : 0);
                            }
                        }
                    }

                    //Mask edges of bend area, avoids streaking at edges
                    if (enableEdgeMasking)
                    {
                        cmd.SetGlobalTexture("_BendMapInput", BuiltinRenderTextureType.CurrentActive);
                        cmd.Blit(BuiltinRenderTextureType.CurrentActive, bendVectorID, m_MaskMat);
                        cmd.SetGlobalTexture(StylizedGrassRenderer.VECTOR_MAP_PARAM, bendVectorID);
                    }
                }
                context.ExecuteCommandBuffer(cmd);
                CommandBufferPool.Release(cmd);
            }
Пример #2
0
        /// <summary>
        /// Initialize the particle system. Any existing particle system on the
        /// game object will be modified to be compatible with the tile grid material.
        /// If no particle system exists, then one will be created.
        /// </summary>
        void InitParticleSystem()
        {
            // Get the local particle system or create one if it doesn't exist.
            localParticleSystem = GetComponent <ParticleSystem>();
            bool hasLocalParticleSytem = localParticleSystem != null;

            if (hasLocalParticleSytem == false)
            {
                localParticleSystem = gameObject.AddComponent <ParticleSystem>();
            }

            // Stop the particle system before modifying its modules.
            LocalParticleSystem.Stop();

            // Modify the main module.
            ParticleSystem.MainModule main = LocalParticleSystem.main;
            main.playOnAwake     = false;
            main.startLifetime   = hasLocalParticleSytem ? main.startLifetime : defaultStartLifetime;
            main.duration        = main.startLifetime.constantMax;
            main.loop            = false;
            main.startSize       = GetMaxParticleSize() * GetParticleSystemScale();
            main.startColor      = hasLocalParticleSytem ? main.startColor : LocalSpriteRenderer.color;
            main.maxParticles    = GetMaxParticleCount();
            main.simulationSpace = ParticleSystemSimulationSpace.World;
            main.gravityModifier = GravityModifier;

            // Modify the emission module to be disabled since we'll manually be emitting particles.
            ParticleSystem.EmissionModule emission = LocalParticleSystem.emission;
            emission.enabled = false;

            // Modify the shape module so that it's disabled. We'll be manually be emitting the particles
            // at specific locations.
            ParticleSystem.ShapeModule shape = LocalParticleSystem.shape;
            shape.enabled = false;

            // Modify the collision module. Some properties retain their original settings
            // if a prexisting component existed. Otherwise, use default values.
            ParticleSystem.CollisionModule collision = LocalParticleSystem.collision;
            collision.enabled      = IsCollisionEnabled;
            collision.type         = ParticleSystemCollisionType.World;
            collision.mode         = CollisionMode == SpriteExploderCollisionMode.Collision3D ? ParticleSystemCollisionMode.Collision3D : ParticleSystemCollisionMode.Collision2D;
            collision.dampen       = hasLocalParticleSytem ? collision.dampen : new ParticleSystem.MinMaxCurve(defaultMinDampen, defaultMaxDampen);
            collision.bounce       = hasLocalParticleSytem ? collision.bounce : new ParticleSystem.MinMaxCurve(defaultMinBounce, defaultMaxBounce);
            collision.lifetimeLoss = hasLocalParticleSytem ? collision.lifetimeLoss : defaultLifetimeLoss;

            // Modify the particle system renderer component. In particular, setting the material,
            // enabling gpu instancing, and setting the active vertex streams.
            ParticleSystemRenderer particleSystemRenderer = GetComponent <ParticleSystemRenderer>();

            particleSystemRenderer.renderMode          = ParticleSystemRenderMode.Mesh;
            particleSystemRenderer.mesh                = Resources.GetBuiltinResource <Mesh>("Quad.fbx");
            particleSystemRenderer.enableGPUInstancing = true;
            particleSystemRenderer.minParticleSize     = 0.0f;
            particleSystemRenderer.maxParticleSize     = 1.0f;

            Material material = Resources.Load <Material>(materialResourcePath);

            particleSystemRenderer.material = material;

            MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock();

            materialPropertyBlock.SetTexture("_GridTex", GetTexture());
            materialPropertyBlock.SetInt("_SubdivisionCountX", GetSubdivisionCountX());
            materialPropertyBlock.SetInt("_SubdivisionCountY", GetSubdivisionCountY());
            materialPropertyBlock.SetFloat("_Rotation", GetMaterialRotaion());
            materialPropertyBlock.SetVector("_Flip", GetFlipVector4());
            particleSystemRenderer.SetPropertyBlock(materialPropertyBlock);

            List <ParticleSystemVertexStream> streams = new List <ParticleSystemVertexStream>();

            streams.Add(ParticleSystemVertexStream.Position);
            streams.Add(ParticleSystemVertexStream.UV);
            streams.Add(ParticleSystemVertexStream.Color);
            streams.Add(ParticleSystemVertexStream.Custom1X); // Used to pass tile data to the shader

            particleSystemRenderer.SetActiveVertexStreams(streams);

            // Play the particle system now that the modules and renderer are setup.
            LocalParticleSystem.Play();
        }