Search Unity

  1. Get all the Unite Berlin 2018 news on the blog.
    Dismiss Notice
  2. Unity 2018.2 has arrived! Read about it here.
    Dismiss Notice
  3. Improve your Unity skills with a certified instructor in a private, interactive classroom. Learn more.
    Dismiss Notice
  4. ARCore is out of developer preview! Read about it here.
    Dismiss Notice
  5. Magic Leap’s Lumin SDK Technical Preview for Unity lets you get started creating content for Magic Leap One™. Find more information on our blog!
    Dismiss Notice
  6. Want to see the most recent patch releases? Take a peek at the patch release page.
    Dismiss Notice

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

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

  1. tokamac


    Jun 4, 2013
    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:

    (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


    Aug 17, 2010
    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):
    2. Shader "Custom/Equirectangular" {
    3.     Properties {
    4.         _Color ("Main Color", Color) = (1,1,1,1)
    5.         _MainTex ("Diffuse (RGB) Alpha (A)", 2D) = "gray" {}
    6.     }
    8.     SubShader{
    9.         Pass {
    10.             Tags {"LightMode" = "Always"}
    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
    19.                 #include "UnityCG.cginc"
    21.                 struct appdata {
    22.                    float4 vertex : POSITION;
    23.                    float3 normal : NORMAL;
    24.                 };
    26.                 struct v2f
    27.                 {
    28.                     float4    pos : SV_POSITION;
    29.                     float3    normal : TEXCOORD0;
    30.                 };
    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.                 }
    40.                 sampler2D _MainTex;
    42.                 #define PI 3.141592653589793
    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.                 }
    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


    Feb 3, 2014
  4. tokamac


    Jun 4, 2013
    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


    Aug 17, 2010
    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


    Apr 23, 2017
    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?