简体   繁体   English

如何分别使用着色器在Unity和Three.js中渲染法线贴图?

[英]How to render the normal map in Unity and Three.js with shader respectively?

I want to render the normal map in three.js and Unity,but i find the final output is different. 我想在Three.js和Unity中渲染法线贴图,但是我发现最终输出是不同的。

the Shader used in Unity as follows: 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
    }
}

} }

In three.js,i use the MeshNormalMaterial to render normal map,but it is different from rendered in Unity. 在three.js中,我使用MeshNormalMaterial渲染法线贴图,但是它与Unity中的渲染不同。

Unity output Unity输出 Unity输出

threejs output threejs输出 threejs输出

I think the problem is that you are transforming the normal using the unity_ObjectToWorld matrix, which also includes the scale. 我认为问题在于您正在使用unity_ObjectToWorld矩阵来变换法线,该矩阵还包括比例尺。 This can result in scaled or sheared normals, which might be what's happening considering how much darker the Unity version looks. 考虑到Unity版本看起来暗了多少,这可能导致法线缩放或剪切。 My advice is to instead use the built-in function included in UnityCG.cginc: 我的建议是改为使用UnityCG.cginc中包含的内置函数:

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

The normal should ideally be normalized in the fragment function too, since the hardware interpolators won't guarantee that your values stay normalized. 理想情况下,也应该在片段函数中对法线进行规范化,因为硬件插值器无法保证您的值保持规范化。 Also, your shader has a bunch of extra stuff in it which isn't really needed - you can remove the following lines: 另外,您的着色器中还包含很多不必要的东西-您可以删除以下几行:

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

EDIT: Notice also that it seems like MeshNormalMaterial renders normals in view-space and not in world-space. 编辑:还请注意,MeshNormalMaterial似乎在视图空间而非世界空间中渲染法线。 This is how you transform a world normal into view space: 这是将世界法线转换为视图空间的方式:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM