// Alan Zucconi // www.alanzucconi.com using UnityEngine; using System.Collections; using System.Collections.Generic; using System.Linq; [RequireComponent(typeof(Renderer))] public class Heatmap : MonoBehaviour { public Texture2D heatTex; public Shader heatShader; List heatPoints = new List(); Renderer meshRenderer; Material material; Transform trans; Renderer MeshRenderer { get { if (meshRenderer == null) meshRenderer = GetComponent(); return meshRenderer; } } Transform Trans { get { if (trans == null) trans = transform; return trans; } } void Start() { GenerateMeterial(); } void Update() { CommitToShaderProgram(); } /// /// 重新生成材质 /// private void GenerateMeterial() { /* * 开始时重新生成一下材质,Unity的 SetXXArray 有一个问题是,当第一次给数组赋值时,数组的最大尺寸就固定了 * 以后再赋值更大的数组时,将会被裁减 */ if (this.material != null) Destroy(this.material); this.material = new Material(heatShader); this.material.SetTexture("_HeatTex", heatTex); this.MeshRenderer.sharedMaterial = material; } /// /// 将参数信息提交到 Shader Program /// private void CommitToShaderProgram() { if (heatPoints.Count == 0) return; material.SetInt("_Points_Length", heatPoints.Count); material.SetVectorArray("_Points", heatPoints.Select((v) => new Vector4(v.point.x, v.point.y, v.point.z)).ToList()); material.SetVectorArray("_Properties", heatPoints.Select((v) => new Vector4(v.radius, v.intensity)).ToList()); } /// /// 向当前热力图中添加指定的点 /// /// 世界坐标系坐标 /// 热点半径 /// 热点强度 public void AddHeatPoint(Vector3 position, float radius, float intensity) { print(position); this.heatPoints.Add(new HeatPoint() { point = position, radius = radius, intensity = intensity }); GenerateMeterial(); CommitToShaderProgram(); } /// /// 向当前热力图中添加指定的点集 /// /// public void AddHeatPoints(IEnumerable points) { if (points == null) return; this.heatPoints.AddRange(points.Select((v) => new HeatPoint() { point = v.point, radius = v.radius, intensity = v.intensity })); GenerateMeterial(); CommitToShaderProgram(); } /// /// 根据指定的热点,设置热力图 /// /// public void SetHeatPoints(IEnumerable points) { if (points.Count() > this.heatPoints.Count) GenerateMeterial(); this.heatPoints.Clear(); this.heatPoints.AddRange(points.Select((v) => new HeatPoint() { point = v.point, radius = v.radius, intensity = v.intensity })); CommitToShaderProgram(); } public void Repaint() { CommitToShaderProgram(); } }