基于贴花的热力图呈现方法参考

该文章展示了在Unity3D中实现热力图的方法,包括使用可序列化的类存储数据,以及创建和更新热力图的C#脚本。脚本涉及到了DecalProjector组件来显示热力图,并使用自定义Shader进行颜色渲染。热力图的数据由PosVal数组表示,颜色过渡通过PercentColor类控制。
摘要由CSDN通过智能技术生成

首先是热力图信息类:

using System;
using UnityEngine;

[Serializable]
public class HeatMapInfo
{
	public Rect rect = Rect.zero;
	public float pixelDensity = 1;
	public float valBase = 0;
	public float valRange = 1;
	public PercentColor[] ribbon;//色带
	public Color colorMulti = Color.white;
	public float influence = 100;//点影响范围
	public PosVal[] posVals;
}

[Serializable]
public class PercentColor
{
	public float percent = 0;
	public Color color = Color.clear;
	public PercentColor(float percent, Color color)
	{
		this.percent = percent;
		this.color = color;
	}
}

[Serializable]
public class PosVal
{
	public Vector3 pos;
	public float val;
	public PosVal(Vector3 pos, float val)
	{
		this.pos = pos;
		this.val = val;
	}
}

然后是热力图的实现代码:

using UnityEngine;
using UnityEngine.Rendering.Universal;

public class HeatMap : MonoBehaviour
{
	static public HeatMap instance;

	void Awake()
	{
		instance = this;
	}

	[SerializeField]
	DecalProjector decalProjector;

	void Start()
	{
		SceneLoader.instance.AddActBeforeActiveNewScene(CancelHeatMap);
	}

	HeatMapInfo info;
	public void SetHeatMap(HeatMapInfo info)
	{
		this.info = info;
		if (this.info == null) return;
		//
		decalProjector.gameObject.SetActive(true);
		decalProjector.pivot = new Vector3(this.info.rect.x + this.info.rect.width * 0.5f, this.info.rect.y + this.info.rect.height * 0.5f, 0);
		decalProjector.size = new Vector3(this.info.rect.width, this.info.rect.height, 2000);
		Texture2D tex2D = GetHeatMap(this.info);
		decalProjector.material.SetTexture("_MainTex", tex2D);
		decalProjector.material.SetColor("_Color", this.info.colorMulti);
	}

	public void CancelHeatMap()
	{
		info = null;
		decalProjector.gameObject.SetActive(false);
	}

	public void UpdateHeadMap(PosVal[] posVals)
	{
		if (info == null) return;

		info.posVals = posVals;
		Texture2D tex2D = GetHeatMap(this.info);
		decalProjector.material.SetTexture("_MainTex", tex2D);
	}

	public Texture2D GetHeatMap(HeatMapInfo info)
	{
		float pixelDensity = info.pixelDensity * 0.05f;
		int texW = (int)(info.rect.width * pixelDensity);
		int texH = (int)(info.rect.height * pixelDensity);
		Texture2D texHeatMap = new Texture2D(texW, texH);
		//
		float unitU = 1.0f / texW;
		float unitV = 1.0f / texH;
		Vector2 pos = new Vector2();
		float influence = info.influence;
		PercentColor[] ribbon = info.ribbon;
		Color colorOutHot = ribbon[ribbon.Length - 1].color;
		float sqrtInfluence = influence * influence;
		for (int i = 0; i < texW; i++)
		{
			pos.x = unitU * i * info.rect.width + info.rect.x;
			for (int j = 0; j < texH; j++)
			{
				Color color = colorOutHot;
				pos.y = unitV * j * info.rect.height + info.rect.y;
				foreach (PosVal pv in info.posVals)
				{
					float sqrtDist = (pos - new Vector2(pv.pos.x, pv.pos.z)).sqrMagnitude;
					if (sqrtDist > sqrtInfluence) continue;
					//
					float pointDensity = (pv.val - info.valBase) / (info.valRange);
					pointDensity = Mathf.Clamp01(pointDensity);

					float dist = Mathf.Sqrt(sqrtDist);
					float pe = dist / influence;
					float percent = pe + (1 - pe) * (1 - pointDensity);
					Color ribbonColor = Color.black;
					if (Mathf.Approximately(percent, 0))
					{
						ribbonColor = ribbon[0].color;
					}
					else if (Mathf.Approximately(percent, 1))
					{
						ribbonColor = ribbon[ribbon.Length - 1].color;
					}
					else
					{
						for (int k = 1; k < ribbon.Length; k++)
						{
							if (percent < ribbon[k].percent)
							{
								float p = (percent - ribbon[k - 1].percent) / (ribbon[k].percent - ribbon[k - 1].percent);
								ribbonColor = Color.Lerp(ribbon[k - 1].color, ribbon[k].color, p);
								break;
							}
						}
					}
					color += ribbonColor * (1 - pe);
				}
				texHeatMap.SetPixel(i, j, color);
			}
		}

		texHeatMap.Apply();
		return texHeatMap;
	}
}

最后是贴花Shader

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
你可以使用Unity中的Shader来实现贴花效果。以下是一个简单的贴花Shader示例代码: ```csharp Shader "Custom/Decal" { Properties { _MainTex ("Base Texture", 2D) = "white" {} _DecalTex ("Decal Texture", 2D) = "white" {} _Color ("Color", Color) = (1,1,1,1) _Opacity ("Opacity", Range(0,1)) = 1 _Tiling ("Tiling", Range(1,10)) = 1 } SubShader { Tags { "RenderType"="Opaque" } LOD 100 CGPROGRAM #pragma surface surf Lambert sampler2D _MainTex; sampler2D _DecalTex; fixed4 _Color; float _Opacity; float _Tiling; struct Input { float2 uv_MainTex; float2 uv_DecalTex; }; void surf (Input IN, inout SurfaceOutput o) { fixed4 mainColor = tex2D(_MainTex, IN.uv_MainTex); fixed4 decalColor = tex2D(_DecalTex, IN.uv_DecalTex * _Tiling); // Apply decal color with opacity fixed4 finalColor = lerp(mainColor, decalColor * _Color, decalColor.a * _Opacity); o.Albedo = finalColor.rgb * finalColor.a; o.Alpha = finalColor.a; } ENDCG } FallBack "Diffuse" } ``` 你可以将这段代码保存为一个名为"Decal.shader"的文件,然后将其拖放到Unity项目中的一个合适文件夹中。接下来,您可以将此Shader应用于您的对象上的材质。创建一个新材质,将其Shader属性设置为"Custom/Decal",然后将您的贴花纹理和基础纹理分别赋值给"_DecalTex"和"_MainTex"属性。 请注意,此示例代码仅提供了一个基本的贴花效果,您可以根据自己的需求进行修改和扩展。同时也可以在Unity的Shader文档中了解更多关于Shader的知识。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值