internal void Update() { if (!SystemComp.enabled || SystemComp.ParticleCount == 0) { return; } //TODO: How to cache more of this? m_cacheMaterial.CopyPropertiesFromMaterial(_material); switch (RenderMode) { case GeometryRenderMode.Billboard: m_cacheMaterial.EnableKeyword("TC_BILLBOARD"); m_cacheMaterial.DisableKeyword("TC_BILLBOARD_STRETCHED"); m_cacheMaterial.DisableKeyword("TC_MESH"); break; case GeometryRenderMode.StretchedBillboard: case GeometryRenderMode.TailStretchBillboard: m_cacheMaterial.DisableKeyword("TC_BILLBOARD"); m_cacheMaterial.EnableKeyword("TC_BILLBOARD_STRETCHED"); m_cacheMaterial.DisableKeyword("TC_MESH"); break; case GeometryRenderMode.Mesh: m_cacheMaterial.DisableKeyword("TC_BILLBOARD"); m_cacheMaterial.DisableKeyword("TC_BILLBOARD_STRETCHED"); m_cacheMaterial.EnableKeyword("TC_MESH"); break; } //enable sprite uv animation keyword if (spriteSheetAnimation) { m_cacheMaterial.EnableKeyword("TC_UV_SPRITE_ANIM"); m_cacheMaterial.DisableKeyword("TC_UV_NORMAL"); } else { m_cacheMaterial.EnableKeyword("TC_UV_NORMAL"); m_cacheMaterial.DisableKeyword("TC_UV_SPRITE_ANIM"); } Color tint = TintColor; if (tint != curTintColor) { curTintColor = tint; UpdateColourOverLifetime(); } m_cacheMaterial.SetBuffer("particlesRead", Manager.GetParticlesBuffer()); m_cacheMaterial.SetTexture(SID._ColTex, colourOverLifetimeTexture); if (Emitter.DoSizeOverLifetime) { m_cacheMaterial.SetTexture(SID._LifetimeTexture, Emitter.SizeOverLifetimeTexture); } UpdateTailUv(); //Update render state if (m_prevRenderMode != RenderMode) { BuildBuffer(); m_prevRenderMode = RenderMode; } else if (RenderMode == GeometryRenderMode.Mesh && Mesh != m_prevRenderModeMesh) { m_prevRenderModeMesh = Mesh; BuildBuffer(); } Matrix4x4 m; Transform systTransform = SystemComp.transform; switch (Manager.SimulationSpace) { case Space.Local: m = Matrix4x4.TRS(systTransform.position, systTransform.rotation, Vector3.one); break; case Space.Parent: m = Matrix4x4.TRS(ParentPosition, systTransform.parent.rotation, Vector3.one); break; case Space.LocalWithScale: m = Matrix4x4.TRS(systTransform.position, systTransform.rotation, systTransform.localScale); break; default: m = Matrix4x4.identity; break; } m_cacheMaterial.SetMatrix(SID._MatrixM, m); //TODO: Combine into one vector m_cacheMaterial.SetFloat(SID._MaxSpeed, 1.0f / maxSpeed); bool hasColourOverLife = colourGradientMode == ParticleColourGradientMode.OverLifetime; m_cacheMaterial.SetFloat(SID._ColourSpeed, hasColourOverLife ? 0 : 1); //TODO: Combine into float? float gl = glow + 1.0f; m_cacheMaterial.SetVector(SID._Glow, new Vector4(gl, gl, gl, 1.0f)); if (spriteSheetAnimation) { m_cacheMaterial.SetVector("_SpriteAnimSize", new Vector4(spriteSheetColumns, spriteSheetRows, 1.0f / spriteSheetColumns, 1.0f / spriteSheetRows)); m_cacheMaterial.SetFloat("_Cycles", spriteSheetCycles); } m_cacheMaterial.SetVector("_LifeMinMax", new Vector4(Emitter.Energy.Min, Emitter.Energy.Max)); switch (RenderMode) { case GeometryRenderMode.Billboard: case GeometryRenderMode.StretchedBillboard: //TODO: Combine into vector m_cacheMaterial.SetFloat(SID._SpeedScale, SpeedScale); m_cacheMaterial.SetFloat(SID._LengthScale, LengthScale - 1.0f); m_particleMesh = TCParticleGlobalManager.GlobalQuad; break; case GeometryRenderMode.TailStretchBillboard: m_cacheMaterial.SetFloat(SID._SpeedScale, SpeedScale); m_cacheMaterial.SetFloat(SID._LengthScale, LengthScale - 1.0f); m_particleMesh = m_tailStretchMesh; break; case GeometryRenderMode.Mesh: m_particleMesh = _mesh; break; } m_cacheMaterial.SetFloat(SID._BufferOffset, Emitter.Offset); m_cacheMaterial.SetFloat(SID._MaxParticles, Manager.MaxParticles); //TODO: How to do submeshes? m_argsData[0] = m_particleMesh.GetIndexCount(0); m_argsData[1] = (uint)SystemComp.ParticleCount; m_argsData[2] = 0; m_argsData[3] = 0; m_argsData[4] = 0; m_argsBuffer.SetData(m_argsData); //Reset flag for next frame isVisible = false; }
public void FillCommandBuffer(CommandBuffer cmd) { if (!ShouldRender()) { return; } InitProperties(); m_cacheMaterial.CopyPropertiesFromMaterial(_material); bool hasColourOverLife = colourGradientMode == ParticleColourGradientMode.OverLifetime; switch (RenderMode) { case GeometryRenderMode.Billboard: s_keywords[0] = "TC_BILLBOARD"; break; case GeometryRenderMode.StretchedBillboard: case GeometryRenderMode.TailStretchBillboard: s_keywords[0] = "TC_BILLBOARD_STRETCHED"; break; case GeometryRenderMode.Mesh: s_keywords[0] = "TC_MESH"; break; } s_keywords[1] = spriteSheetAnimation ? "TC_UV_SPRITE_ANIM" : "TC_UV_NORMAL"; m_cacheMaterial.shaderKeywords = s_keywords; if (TintColor != curTintColor) { curTintColor = TintColor; UpdateColourOverLifetime(); } m_cacheMaterial.SetBuffer("particlesRead", Manager.particles); m_cacheMaterial.SetTexture(s_colTex, colourOverLifetimeTexture); if (PartEmitter.DoSizeOverLifetime) { m_cacheMaterial.SetTexture(s_lifetimeTex, PartEmitter.SizeOverLifetimeTexture); } UpdateTailUv(); //Update render state if (m_prevRenderMode != RenderMode) { BuildBuffer(); m_prevRenderMode = RenderMode; } else if (RenderMode == GeometryRenderMode.Mesh && (Mesh != m_prevMesh || _material.shader != m_prevShader)) { m_prevMesh = Mesh; m_prevShader = _material.shader; BuildBuffer(); } Matrix4x4 m; switch (Manager.SimulationSpace) { case Space.Local: m = Matrix4x4.TRS(Transform.position, Transform.rotation, Vector3.one); break; case Space.Parent: m = Matrix4x4.TRS(ParentPosition, Transform.parent.rotation, Vector3.one); break; case Space.LocalWithScale: m = Matrix4x4.TRS(Transform.position, Transform.rotation, Transform.localScale); break; default: m = Matrix4x4.identity; break; } Matrix4x4 v = Camera.current.worldToCameraMatrix; m_cacheMaterial.SetMatrix(s_matrixM, m); m_cacheMaterial.SetMatrix(s_matrixV, v); m_cacheMaterial.SetFloat(s_maxSpeed, 1.0f / maxSpeed); m_cacheMaterial.SetFloat(s_colourSpeed, hasColourOverLife ? 0 : 1); float gl = glow + 1.0f; m_cacheMaterial.SetVector(s_glow, new Vector4(gl, gl, gl, 1.0f)); ComputeBuffer setPointsBuffer = null; switch (RenderMode) { case GeometryRenderMode.Point: case GeometryRenderMode.Billboard: case GeometryRenderMode.StretchedBillboard: setPointsBuffer = m_bufferPoints; break; case GeometryRenderMode.TailStretchBillboard: setPointsBuffer = m_bufferPointsTail; break; case GeometryRenderMode.Mesh: setPointsBuffer = m_meshPointsBuffer; break; } m_cacheMaterial.SetBuffer("bufPoints", setPointsBuffer); if (RenderMode == GeometryRenderMode.Mesh) { if (m_useNormals) { m_cacheMaterial.SetBuffer("bufNormals", m_normalsBuffer); } } if (isPixelSize) { var pixelMult = Mathf.Max(1.0f / Screen.width, 1.0f / Screen.height); if (Camera.current.orthographic) { pixelMult *= Camera.current.orthographicSize * 2.0f; } m_cacheMaterial.SetVector(s_pixelMult, new Vector4(pixelMult, Camera.current.orthographic ? 0.0f : 1.0f)); } else { m_cacheMaterial.SetVector(s_pixelMult, new Vector4(1.0f, 0.0f)); } if (spriteSheetAnimation) { m_cacheMaterial.SetVector("_SpriteAnimSize", new Vector4(spriteSheetColumns, spriteSheetRows, 1.0f / spriteSheetColumns, 1.0f / spriteSheetRows)); m_cacheMaterial.SetFloat("_Cycles", spriteSheetCycles); } m_cacheMaterial.SetVector("_LifeMinMax", new Vector4(PartEmitter.Energy.Min, PartEmitter.Energy.Max)); switch (RenderMode) { case GeometryRenderMode.StretchedBillboard: m_cacheMaterial.SetBuffer("stretchBuffer", m_stretchBuffer); m_cacheMaterial.SetFloat(s_speedScale, SpeedScale); m_cacheMaterial.SetFloat(s_lengthScale, LengthScale - 1.0f); m_cacheMaterial.SetFloat(s_billboardFlip, 1.0f); break; case GeometryRenderMode.TailStretchBillboard: m_cacheMaterial.SetBuffer("stretchBuffer", m_stretchBufferTail); m_cacheMaterial.SetFloat(s_speedScale, SpeedScale); m_cacheMaterial.SetFloat(s_lengthScale, LengthScale - 1.0f); m_cacheMaterial.SetFloat(s_billboardFlip, -1.0f); break; case GeometryRenderMode.Mesh: m_cacheMaterial.SetBuffer("uvs", m_uvsBuffer); break; } m_cacheMaterial.SetInt(s_bufferOffset, Manager.Offset); m_cacheMaterial.SetInt(s_maxParticles, Manager.MaxParticles); for (int i = 0; i < m_cacheMaterial.passCount; ++i) { RenderPass(i, cmd); } }