Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

What is wrong with Unity's spherical mapping? How to fix it?

Discussion in 'Shaders' started by Gordon_G, Apr 24, 2015.

  1. Gordon_G

    Gordon_G

    Joined:
    Jun 4, 2013
    Posts:
    372
    Hi all, please excuse my Noobiness, but what is up with Unty's spherical mapping method?

    It seems the UV coordinates attached to Unity's sphere object must be all wrong, or something, and I find no documentation or online help that seems to address the issue.

    (setup: Unity 5.x Pro on OS X Mavericks)

    I'm trying to wrap an image of the earth on a Unity Sphere. I created a new material, select standard, and attach the NASA Earth map you can find everywhere - for example:

    earth-map-small.jpeg
    (but of course, at higher res)

    - to the albedo texture map, and below is the result. So, I dig and dig and dig and dig, for 2 days now, and the only thing I can find is a resource with shader code that implies that it will map correctly to a sphere.

    So I copy the code to create a custom shader, but it does exactly the same thing (probably no wonder: the code looks suspiciously like Unity's shader template code):

    Screen Shot 2015-04-24 at 5.47.55 PM.png Screen Shot 2015-04-24 at 5.47.28 PM.png

    Note how distorted north America looks, and Antarctica - there is definite pinching at the poles and a seam where there should be none.... leads me to believe there is something wrong with the object itself.

    I do not believe I am doing anything incorrectly, and I've been using 3d software for years, so while I am a noob to Unity, I can't help but believe there must be something fundamental going on that some one can help with - some undocumented bug or something major I am missing? Is Unity's bult-in sphere gameObject corrupted or something?

    Thanks for any help, links, or resource in advance!
     
  2. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    You'll need to apply the texture as a spherical map in your 3D program and bake it out to the UVs of a sphere. They are not directly compatible.
    At the moment, the image you have is not mapped to a sphere's UVs.


    Alternatively, this is some Unity 4 shader code to do equirectangular lookups on a texture...

    Code (csharp):
    1.  
    2. Shader "Custom/Equirectangular" {
    3.     Properties {
    4.         _Color ("Main Color", Color) = (1,1,1,1)
    5.         _MainTex ("Diffuse (RGB) Alpha (A)", 2D) = "gray" {}
    6.     }
    7.  
    8.     SubShader{
    9.         Pass {
    10.             Tags {"LightMode" = "Always"}
    11.  
    12.             CGPROGRAM
    13.                 #pragma vertex vert
    14.                 #pragma fragment frag
    15.                 #pragma fragmentoption ARB_precision_hint_fastest
    16.                 #pragma glsl
    17.                 #pragma target 3.0
    18.  
    19.                 #include "UnityCG.cginc"
    20.  
    21.                 struct appdata {
    22.                    float4 vertex : POSITION;
    23.                    float3 normal : NORMAL;
    24.                 };
    25.  
    26.                 struct v2f
    27.                 {
    28.                     float4    pos : SV_POSITION;
    29.                     float3    normal : TEXCOORD0;
    30.                 };
    31.  
    32.                 v2f vert (appdata v)
    33.                 {
    34.                     v2f o;
    35.                     o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
    36.                     o.normal = v.normal;
    37.                     return o;
    38.                 }
    39.  
    40.                 sampler2D _MainTex;
    41.  
    42.                 #define PI 3.141592653589793
    43.  
    44.                 inline float2 RadialCoords(float3 a_coords)
    45.                 {
    46.                     float3 a_coords_n = normalize(a_coords);
    47.                     float lon = atan2(a_coords_n.z, a_coords_n.x);
    48.                     float lat = acos(a_coords_n.y);
    49.                     float2 sphereCoords = float2(lon, lat) * (1.0 / PI);
    50.                     return float2(sphereCoords.x * 0.5 + 0.5, 1 - sphereCoords.y);
    51.                 }
    52.  
    53.                 float4 frag(v2f IN) : COLOR
    54.                 {
    55.                     float2 equiUV = RadialCoords(IN.normal);
    56.                     return tex2D(_MainTex, equiUV);
    57.                 }
    58.             ENDCG
    59.         }
    60.     }
    61.     FallBack "VertexLit"
    62. }
     
    Last edited: Apr 24, 2015
  3. rakkarage

    rakkarage

    Joined:
    Feb 3, 2014
    Posts:
    683
  4. Gordon_G

    Gordon_G

    Joined:
    Jun 4, 2013
    Posts:
    372
    Hey, many thanks rakkarage & Farfarer - both work.

    I thought that unity would have built this into their materials wrapping method for their sphere object. I just could find anything that said one had to created an unwrapped map.
     
  5. Farfarer

    Farfarer

    Joined:
    Aug 17, 2010
    Posts:
    2,249
    All meshes need UV maps. That's how you apply textures to specific areas of them (unless you're using something procedural).

    There's just not enough resolution in mesh (and so the resulting UV map) to capture an equirectangular map. It's not something Unity can do because it's not something anyone can do...
     
  6. Andrea_Marchetti

    Andrea_Marchetti

    Joined:
    Apr 23, 2017
    Posts:
    9
    Farfarer, thanks. I have a problem and I am not able to fix it. The code you wrote works perfectly, but I can't duplicate a texture over a sphere. If I edit the tiles number it doesn't change anything. How exactly should I edit it?
     
  7. ankitmahajan946

    ankitmahajan946

    Joined:
    Sep 5, 2018
    Posts:
    2
    image.png image2.png image2.png image.png I used the above shader and it works perfectly well but a grey line appears when I move the camera. i've attached an image of the same, is it possible to remove that line.. image.png
     
  8. ankitmahajan946

    ankitmahajan946

    Joined:
    Sep 5, 2018
    Posts:
    2
  9. Xevetor

    Xevetor

    Joined:
    Oct 14, 2017
    Posts:
    3
    Changing to Editor GUI didn't work for me

    Ok, solved it, I've just set the texture type back to Default, but disable the 'Generate Mip Map' under Advance.

    Btw, thanks for this shader, solved my warping issue with it.
     
    Last edited: Sep 26, 2018
    VirtualPierogi and bgolus like this.
  10. spaceowlpro

    spaceowlpro

    Joined:
    Nov 8, 2017
    Posts:
    12
    This thread helped me so much!! Thanks!

    I've been trying to add transparency to this so that the alpha of my Texture will be included when it's rendered. Can someone point me somewhere to read up on how to do that?

    Thanks!
    Kurt
     
    digitalmkt likes this.
  11. NuShrike

    NuShrike

    Joined:
    Aug 5, 2021
    Posts:
    2
    Thanks, this old post helped me map a NASA provided equirectangular Earth map to a Unity sphere. I made a Equirectangular version of 2020.3's standard Shader as a custom shader.

    Code (HLSL):
    1. float4 TexCoords(VertexInput v)
    2. {
    3.     /* equirectangular correction */
    4.     float3 R = v.normal;
    5.     if (v.uv0.x > 0.0)
    6.     {   // don't equirectangular-compensate at u of 0
    7.         float2 phiTheta = float2(atan2(R.z, R.x) / UNITY_TWO_PI + 0.5,
    8.                                  acos(-R.y) / UNITY_PI);
    9.         v.uv0 = phiTheta;
    10.     }
    11.     /* equirectangular correction */
    12.  
    13.     float4 texcoord;
    14.     texcoord.xy = TRANSFORM_TEX(v.uv0, _MainTex); // Always source from uv0
    15.     texcoord.zw = TRANSFORM_TEX(((_UVSec == 0) ? v.uv0 : v.uv1), _DetailAlbedoMap);
    16.  
    17.     return texcoord;
    18. }
    However originally, it had an ugly seam at u of 0. A fix seems to just not correct the existing uv when u is 0.
     
  12. KaneTheDev

    KaneTheDev

    Joined:
    Apr 21, 2022
    Posts:
    1
    Hi, I'm a total newbie in this shader scripting thing. I just wanna add lighting to this script. I would really appreciate if someone could help me out. I'm trying to add texture to a soccer ball.
    This is what it currently looks like in the scene.
    upload_2022-11-15_17-31-38.png
     
  13. Chakanshu

    Chakanshu

    Joined:
    Jul 29, 2020
    Posts:
    2
    I had the same issue with the Unity Skybox. In the inspector for the 360 panorama image, setting the "non-power of 2" option to "none" instead of the default "ToNearast" fixed the issue. No idea how or why, Also the option "non-power of 2" is disabled and stuck to "ToNearest", I changed the "Texture type" to "Editor GUI and Legacy GUI" and it changed the option to "none" and it stuck that way. Problem solved for Unity.

    fixed.png

    pole issue image.png settings of image.png