Unity云图渲染效果
需求
根据有限元分析后处理结果(应力等),将云图效果在Unity中复现同样的效果
需要准备的数据
从有限元分析软件(Abaqus、Ansys等)将模型结点数据进行导出
实现原理
Step1 通过C#根据结点(相当于模型顶点)数据大小将数据转化由红到蓝颜色区间的颜色(采用HSV色彩模型以便于获取纯色彩),获得一个模型顶点的Color数组;
Step2 将颜色传入着色器进行处理(AppToVert、VertToFrag),并通过纹理映射的方式从纹理贴图中获取相应的颜色值。
代码展示
1、C#代码。
public class CloudMapRendering
{
public static Color[] CalculateModelVerticeColors(float[] physicsDatas)
{
colorDatas = new Color[physicsDatas.Length];
float[] hueColorH = new float[physicsDatas.Length];
float max = physicsDatas.GetMax();
//当有限元网格结点值全为0时,颜色全为蓝
if (max == 0)
{
for (int i = 0; i < physicsDatas.Length; i++)
{
colorDatas[i] = Color.blue;
}
return;
}
float min = physicsDatas.GetMin();
float range = max - min;
for (int i = 0; i < physicsDatas.Length; i++)
{
hueColorH[i] = 2.0f / 3 * (max - physicsDatas[i]) / range;
colorDatas[i] = Color.HSVToRGB(hueColorH[i], 1, 1);
}
return colorDatas;
}
}
public static class ArrayExtension
{
public static float GetMax(this float[] vs)
{
float max = 0;
for (int i = 0; i < vs.Length; i++)
{
if (vs[i] > max)
{
max = vs[i];
}
}
return max;
}
public static float GetMin(this float[] vs)
{
float min = 0;
for (int i = 0; i < vs.Length; i++)
{
if (vs[i] < min)
{
min = vs[i];
}
}
return min;
}
}
新建一个C#脚本挂在渲染模型上,调用上面的CalculateModelVerticeColors方法,并通过MeshFilter中的colors属性将计算值赋给colors属性。
2、着色器部分。
Shader "Custom/testCloudMapWireframeShader"
{
Properties
{
_Texture("Main Tex",2D) = ""{}
}
SubShader
{
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
struct a2v {
float4 vertex:POSITION;
fixed4 color : COLOR;
float4 texcoord:TEXCOORD0;
};
struct v2f {
float4 position:SV_POSITION;
float3 color:COLOR0;
float4 uv:TEXCOORD1;
};
sampler2D _Texture;
float4 _UVposition;
//由于着色器用RGB进行计算,因此先转换为HSV
float3 RGB2HSV(float3 c)
{
float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
float4 p = lerp(float4(c.bg, K.wz), float4(c.gb, K.xy), step(c.b, c.g));
float4 q = lerp(float4(p.xyw, c.r), float4(c.r, p.yzx), step(p.x, c.r));
float d = q.x - min(q.w, q.y);
float e = 1.0e-10;
return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
//根据HSV颜色值映射到对应的纹理坐标进行纹理采样
float3 ColorConvert(float3 originalHSVc)
{
return tex2D(_Texture, (1,(1 - originalHSVc.x) * 3) * step(2.0 / 3.0, originalHSVc.x) + (1,originalHSVc.x * 3 / 2) * step(originalHSVc.x, 2.0 / 3.0));
}
v2f vert(a2v v)
{
v2f f;
f.position = UnityObjectToClipPos(v.vertex);
f.color = v.color;
f.uv = v.texcoord;
return f;
}
fixed4 frag(v2f f) :SV_Target
{
float3 convertedColor = RGB2HSV(f.color);
f.color = ColorConvert(convertedColor);
return fixed4(f.color,1);
}
ENDCG
}
}
FallBack "Diffuse"
}
纹理贴图
一张常见的颜色梯度图(左红右蓝)
后记
笔者第一次写文章,有很多地方都没有表述清楚,大家有问题或者意见也欢迎评论。