360 viewer in unity, texture appears warped in the top and bottom

前端 未结 3 1466
别那么骄傲
别那么骄傲 2020-12-10 08:44

I am making a 360 viewer in unity, to view a 360 photo I used to have a cubemap attached to a skybox, and it worked great. But the weight of the cubemaps forced me to switch

相关标签:
3条回答
  • 2020-12-10 09:16

    The shader you choose does not handle equirectangular distortion very well. At the poles (top and bottom) of the sphere much image information has to be mapped on very small space which leads to the artifacts you are seeing.

    You can write a specialized shader to improve the coordinate mapping from your equirectangular image onto the sphere. At the Unity forums a specialized shader has been posted.

    Shader "Custom/Equirectangular" {
        Properties {
            _Color ("Main Color", Color) = (1,1,1,1)
            _MainTex ("Diffuse (RGB) Alpha (A)", 2D) = "gray" {}
        }
    
        SubShader{
            Pass {
                Tags {"LightMode" = "Always"}
    
                CGPROGRAM
                    #pragma vertex vert
                    #pragma fragment frag
                    #pragma fragmentoption ARB_precision_hint_fastest
                    #pragma glsl
                    #pragma target 3.0
    
                    #include "UnityCG.cginc"
    
                    struct appdata {
                       float4 vertex : POSITION;
                       float3 normal : NORMAL;
                    };
    
                    struct v2f
                    {
                        float4    pos : SV_POSITION;
                        float3    normal : TEXCOORD0;
                    };
    
                    v2f vert (appdata v)
                    {
                        v2f o;
                        o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
                        o.normal = v.normal;
                        return o;
                    }
    
                    sampler2D _MainTex;
    
                    #define PI 3.141592653589793
    
                    inline float2 RadialCoords(float3 a_coords)
                    {
                        float3 a_coords_n = normalize(a_coords);
                        float lon = atan2(a_coords_n.z, a_coords_n.x);
                        float lat = acos(a_coords_n.y);
                        float2 sphereCoords = float2(lon, lat) * (1.0 / PI);
                        return float2(sphereCoords.x * 0.5 + 0.5, 1 - sphereCoords.y);
                    }
    
                    float4 frag(v2f IN) : COLOR
                    {
                        float2 equiUV = RadialCoords(IN.normal);
                        return tex2D(_MainTex, equiUV);
                    }
                ENDCG
            }
        }
        FallBack "VertexLit"
    }
    

    Again, it's not my own code but I tested it on android devices and as a standalone PC version. It results in very smooth poles.

    Please note: This shader does not flip normals of your sphere. So if you want your camera to sit inside the sphere you have to invert its normals with a 3d program or with the shader. Try adding Cull Front after line 9 above and the shader will apply its texture to the "wrong" side of the model.

    0 讨论(0)
  • 2020-12-10 09:19

    I'm a beginner and I had to do a lot just to understand this thread. This is what worked for me. I just combined the answers and put it in one script. I'm pretty sure I will forget this in a few weeks time, so putting it here for posterity.

    Shader "Custom/Equirectangular" {
        Properties {
            _Color ("Main Color", Color) = (1,1,1,1)
            _MainTex ("Diffuse (RGB) Alpha (A)", 2D) = "gray" {}
        }
    
        SubShader{
            Pass {
                Tags {"LightMode" = "Always"}
                Cull Front
    
                CGPROGRAM
                    #pragma vertex vert
                    #pragma fragment frag
                    #pragma fragmentoption ARB_precision_hint_fastest
                    #pragma glsl
                    #pragma target 3.0
    
                    #include "UnityCG.cginc"
    
                    struct appdata {
                       float4 vertex : POSITION;
                       float3 normal : NORMAL;
                    };
    
                    struct v2f
                    {
                        float4    pos : SV_POSITION;
                        float3    normal : TEXCOORD0;
                    };
    
                    v2f vert (appdata v)
                    {
                        v2f o;
                        o.pos = UnityObjectToClipPos(v.vertex);
                        o.normal = v.normal;
                        return o;
                    }
    
                    sampler2D _MainTex;
    
                    #define PI 3.141592653589793
    
                    inline float2 RadialCoords(float3 a_coords)
                    {
                        float3 a_coords_n = normalize(a_coords);
                        float lon = atan2(a_coords_n.z, a_coords_n.x);
                        float lat = acos(a_coords_n.y);
                        float2 sphereCoords = float2(lon, lat) * (1.0 / PI);
                        return float2(1 - (sphereCoords.x * 0.5 + 0.5), 1 - sphereCoords.y);
                    }
    
                    float4 frag(v2f IN) : COLOR
                    {
                        float2 equiUV = RadialCoords(IN.normal);
                        return tex2D(_MainTex, equiUV);
                    }
                ENDCG
            }
        }
        FallBack "VertexLit"
    }
    
    0 讨论(0)
  • 2020-12-10 09:22

    This is another shader code.

    'Shader "Flip Normals" {
              Properties {
                 _MainTex ("Base (RGB)", 2D) = "white" {}
             }
              SubShader {
    
                Tags { "RenderType" = "Opaque" }
    
                Cull Front
    
                CGPROGRAM
    
                #pragma surface surf Lambert vertex:vert
                sampler2D _MainTex;
    
                 struct Input {
                     float2 uv_MainTex;
                     float4 color : COLOR;
                 };
    
    
                void vert(inout appdata_full v)
                {
                    v.normal.xyz = v.normal * -1;
                }
    
                void surf (Input IN, inout SurfaceOutput o) {
                          fixed3 result = tex2D(_MainTex, IN.uv_MainTex);
                     o.Albedo = result.rgb;
                     o.Alpha = 1;
                }
    
                ENDCG
    
              }
    
              Fallback "Diffuse"
         }`
    
    0 讨论(0)
提交回复
热议问题