【问题标题】:360 viewer in unity, texture appears warped in the top and bottom统一的 360 度查看器,纹理在顶部和底部出现扭曲
【发布时间】:2016-05-07 12:02:03
【问题描述】:

我正在统一制作一个 360 查看器,为了查看 360 照片,我曾经将立方体贴图附加到天空盒,效果很好。但是立方体贴图的重量迫使我切换到纹理。

所有 360 查看器教程都说只需放置一个带有着色器的球体,然后将相机放入其中。当我这样做时,效果不是很好,因为当我看向顶部或底部时,我看到图像像这样扭曲:(椅子应该看起来很正常)

当我使用天空盒时没有发生这种情况。

有人知道为什么会这样吗?

非常感谢!

【问题讨论】:

    标签: unity3d textures shader google-cardboard photosphere


    【解决方案1】:

    您选择的着色器不能很好地处理等距矩形失真。在球体的两极(顶部和底部),许多图像信息必须映射到非常小的空间上,这会导致您看到的伪影。

    您可以编写一个专门的着色​​器来改进从 equirectangular 图像到球体的坐标映射。在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"
    }
    

    同样,这不是我自己的代码,但我在 Android 设备上和作为独立 PC 版本上对其进行了测试。它会产生非常光滑的两极。

    请注意:此着色器不会翻转球体的法线。因此,如果您希望您的相机位于内部球体,则必须使用 3d 程序或着色器反转其法线。尝试在上面第 9 行之后添加Cull Front,着色器会将其纹理应用到模型的“错误”一侧。

    【讨论】:

    • 谢谢,我结束 p 所做的是创建一个有很多顶点的大 3d 球体,然后纹理很棒。在那之前我已经看过一个着色器解决方案,所以我相信这很棒!
    • 我遇到了和 OP 完全相同的问题,但是这个着色器(上图)根本不渲染。我的意思是它没有给出错误,但它呈现清晰(不可见)。在 iPhone 上,使用 GVR。
    • @Ali 你的球体法线很可能有问题。请参阅上面我编辑的答案。
    • @miracula 谢谢,添加Cull Front 解决了这个问题。在 iOS 上的 GVR 中完美运行。
    • 看起来很完美,但是 x 轴是倒置的! (图片垂直翻转)如何解决?
    【解决方案2】:

    我是一个初学者,为了理解这个线程我不得不做很多事情。这对我有用。我只是将答案合并到一个脚本中。我很确定我会在几周后忘记这一点,所以把它放在这里以供后代使用。

    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"
    }
    

    【讨论】:

      【解决方案3】:

      这是另一个着色器代码。

      '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"
           }`
      

      【讨论】:

        猜你喜欢
        • 2017-09-20
        • 2021-02-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多