Как отрисовать карту нормалей в Unity и Three.js с шейдером соответственно? - PullRequest
0 голосов
/ 31 января 2019

Я хочу визуализировать карту нормалей в three.js и Unity, но я нахожу, что окончательный результат отличается.

шейдер, используемый в Unity следующим образом:

Shader "Unlit/normal"
{
Properties
{
    _MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
    Tags { "RenderType"="Opaque" }
    LOD 100

    Pass
    {
        CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        // make fog work
        #pragma multi_compile_fog

        #include "UnityCG.cginc"

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

        struct v2f
        {
            float2 uv : TEXCOORD0;
            UNITY_FOG_COORDS(1)
            float4 vertex : SV_POSITION;
            fixed4 color : COLOR;
        };

        sampler2D _MainTex;
        float4 _MainTex_ST;

        v2f vert (appdata v)
        {
            v2f o;
            o.vertex = mul(UNITY_MATRIX_MVP, v.vertex);
            o.color.xyz = mul(_Object2World, v.normal)*0.5+0.5 ;
            o.color.w = 1.0f;
            return o;
        }

        fixed4 frag (v2f i) : SV_Target
        {

            return i.color; //output normal
        }
        ENDCG
    }
}

}

В three.js я использую MeshNormalMaterial для рендеринга карты нормалей, но она отличается от отрисовки в Unity.

Вывод Unity Unity output

три выхода threejs output

1 Ответ

0 голосов
/ 03 февраля 2019

Я думаю, что проблема в том, что вы преобразовываете нормаль, используя матрицу unity_ObjectToWorld, которая также включает масштаб.Это может привести к изменению масштаба или сдвигу нормалей, что может быть тем, что происходит, учитывая, насколько темнее выглядит версия Unity.Вместо этого я советую использовать встроенную функцию, включенную в UnityCG.cginc:

o.color.rgb = UnityObjectToWorldNormal(v.normal);

Нормальное значение в идеале должно быть нормализовано и в функции фрагмента, поскольку аппаратные интерполяторы не гарантируют, что ваши значения останутсянормализуется.Кроме того, в вашем шейдере есть куча дополнительных вещей, которые на самом деле не нужны - вы можете удалить следующие строки:

#pragma multi_compile_fog
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
sampler2D _MainTex;
float4 _MainTex_ST;

РЕДАКТИРОВАТЬ: обратите внимание также, что кажется, что MeshNormalMaterial отображает нормали в пространстве видаа не в мировом пространстве.Вот как вы преобразуете нормальный мир в пространство вида:

float3 viewNormal = normalize(mul((float3x3)UNITY_MATRIX_V, worldNormal));
...