3D模型数据可视化

       前端后端一直都有个词叫数据可视化,大数据现在也在做可视化,目的是为了将复杂的数据以图形图像的形式表现出来,让我们对特征性数据一目了然。所以,这里强调一次 表达方式 的重要性(生活中也如此,祝你生活愉快)。
       我们在做图形渲染,分析模型,写Shader时,往往会针对某一类数据做特殊处理。那么要是能一眼看出来这部分数据在哪里,那该多方便。于是有了这篇最简单的 模型法线可视化 (世界空间坐标内)。

功能

       目前只有最简单的四个类型数据显示,后期别的类型的数据,读者完全可以自己添加,本文只是告之方法。

  1. 显示峭壁(ShowSteep)
  2. 显示法线X分量值(ShowNormalX)
  3. 显示法线Y分量值(ShowNormalY)
  4. 显示法线Z分量值(ShowNormalZ)

演示

       整体动态演示

3D数据可视化计算公式 3d模型可视化_Unity


       峭壁面显示(越白越陡峭)

3D数据可视化计算公式 3d模型可视化_Shader_02


       法线X分量显示(红色,跟unity坐标轴颜色一致)

3D数据可视化计算公式 3d模型可视化_数据_03


       法线Y分量显示(绿色,跟unity坐标轴颜色一致)

3D数据可视化计算公式 3d模型可视化_Shader_04


       法线Z分量显示(蓝色,跟unity坐标轴颜色一致)

3D数据可视化计算公式 3d模型可视化_数据_05


       法线显示(综合值,跟unity坐标轴颜色一致)

3D数据可视化计算公式 3d模型可视化_3D数据可视化计算公式_06

Shader源码

Shader "ShadersHub/ModelDataProfiler"
{
    Properties
    {
		SteepPower("SteepPower", Range(1, 20)) = 1
		NormalXPower("NormalXPower", Range(1, 20)) = 1
		NormalYPower("NormalYPower", Range(1, 20)) = 1
		NormalZPower("NormalZPower", Range(1, 20)) = 1
		
		[Space(10)]
		[Header(Debug)]
		[Toggle]ShowSteep("ShowSteep", float) = 0
		[Toggle]ShowNormalX("ShowNormalX", float) = 1
		[Toggle]ShowNormalY("ShowNormalY", float) = 1
		[Toggle]ShowNormalZ("ShowNormalZ", float) = 1
    }

    SubShader
    {
        Tags { "RenderType"="Opaque" }
        LOD 100

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

			float ShowSteep;
			float NormalXPower;
			float NormalYPower;
			float NormalZPower;

			float SteepPower;
			float ShowNormalX;
			float ShowNormalY;
			float ShowNormalZ;

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
            };

            struct v2f
            {
                float2 uv : TEXCOORD0;
                float4 vertex : SV_POSITION;
				float3 normal : NORMAL;
            };

            v2f vert (appdata v)
            {
                v2f o;

                o.vertex = UnityObjectToClipPos(v.vertex);
                o.uv = o.uv = v.uv;
				o.normal = normalize(mul( unity_ObjectToWorld, v.normal).xyz);

                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
				float steepness = atan(1/abs(i.normal.y));
				steepness = saturate(pow(steepness, SteepPower));

				if (ShowSteep){
					return float4(steepness, steepness, steepness, 1);
				}

				fixed3 color = fixed3((pow(abs(i.normal.x)* ShowNormalX, NormalXPower)), 0, 0)
							+ fixed3(0, (pow(abs(i.normal.y) * ShowNormalY, NormalYPower)), 0)
							+ fixed3(0, 0, (pow(abs(i.normal.z) * ShowNormalZ, NormalZPower)));

				return fixed4(color, 1);
            }
            ENDCG
        }
    }
}

Shader源码分析

       代码比较简单,主要强调两个函数的宏观意义:

  1. atan(y/x) 函数,返回弧度 [-PI/2, PI/2],图形学意义是将可变数值限定在两个极限值之间(无线逼近上线)。函数参考图像如下
  2. pow(x,n) 函数, 其中(n>1) ,图像学意义是,通过幂运算,使小数值更小,整数值更大。简而言之,使得小值更小,大值更大,突出两极分化。