// 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); }
/// <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(); }