Search Unity

Equirectangular background shader

Discussion in 'General Graphics' started by WarrenB, Oct 27, 2015.

  1. WarrenB

    WarrenB

    Joined:
    May 24, 2012
    Posts:
    21
    Does anyone know of a good way to use an equiractangular (or lat-lon) image as a background in Unity?

    https://www.google.com/search?q=equ...X&ved=0CB8QsARqFQoTCKL5z5zp4sgCFUd5JgodAycPdQ

    I really do want to use this format. I don't want a cubemap. I am aware that it won't be as fast. That doesn't concern me. I am only concerned with displaying this type of map, which is standard in the CG field, in Unity.

    Thanks for any help.

    Warren
     
  2. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    The easy way is to have Unity convert it into a cubemap for you: Select your texture, set the texture type to Cubemap, and mapping to Lat-Long. http://docs.unity3d.com/Manual/class-Cubemap.html

    Then make a new material and set it to use the skybox/cubemap shader and assign the new cubemap to it.

    Alternatively you can write your own skybox shader that takes a regular texture and assumes it's a lat-long.

    edit: Or use this one I wrote and see why people don't use equirectangular in real time (nasty seam). Cubemaps have special hardware level handling that deals with seams cleanly, where as there's no hardware handling of equirectangular so you can get weird seams like this. There are ways to fix it, but that's something someone else can deal with if you really don't want to use the cubemap conversion.
    Code (CSharp):
    1. Shader "Skybox/Equirectangular" {
    2. Properties {
    3.     _Tint ("Tint Color", Color) = (.5, .5, .5, .5)
    4.     [Gamma] _Exposure ("Exposure", Range(0, 8)) = 1.0
    5.     _Rotation ("Rotation", Range(0, 360)) = 0
    6.     [NoScaleOffset] _Tex ("Panorama (HDR)", 2D) = "grey" {}
    7. }
    8.  
    9. SubShader {
    10.     Tags { "Queue"="Background" "RenderType"="Background" "PreviewType"="Skybox" }
    11.     Cull Off ZWrite Off
    12.  
    13.     Pass {
    14.      
    15.         CGPROGRAM
    16.         #pragma vertex vert
    17.         #pragma fragment frag
    18.  
    19.         #include "UnityCG.cginc"
    20.  
    21.         sampler2D _Tex;
    22.         half4 _Tex_HDR;
    23.         half4 _Tint;
    24.         half _Exposure;
    25.         float _Rotation;
    26.  
    27.         float4 RotateAroundYInDegrees (float4 vertex, float degrees)
    28.         {
    29.             float alpha = degrees * UNITY_PI / 180.0;
    30.             float sina, cosa;
    31.             sincos(alpha, sina, cosa);
    32.             float2x2 m = float2x2(cosa, -sina, sina, cosa);
    33.             return float4(mul(m, vertex.xz), vertex.yw).xzyw;
    34.         }
    35.      
    36.         struct appdata_t {
    37.             float4 vertex : POSITION;
    38.         };
    39.  
    40.         struct v2f {
    41.             float4 vertex : SV_POSITION;
    42.             float3 texcoord : TEXCOORD0;
    43.         };
    44.  
    45.         v2f vert (appdata_t v)
    46.         {
    47.             v2f o;
    48.             o.vertex = mul(UNITY_MATRIX_MVP, RotateAroundYInDegrees(v.vertex, _Rotation));
    49.             o.texcoord = v.vertex.xyz;
    50.             return o;
    51.         }
    52.  
    53.         fixed4 frag (v2f i) : SV_Target
    54.         {
    55.             float3 dir = normalize(i.texcoord);
    56.             float2 longlat = float2(atan2(dir.x, dir.z) + UNITY_PI, acos(-dir.y));
    57.             float2 uv = longlat / float2(2.0 * UNITY_PI, UNITY_PI);
    58.             half4 tex = tex2D (_Tex, uv);
    59.             half3 c = DecodeHDR (tex, _Tex_HDR);
    60.             c = c * _Tint.rgb * unity_ColorSpaceDouble.rgb;
    61.             c *= _Exposure;
    62.  
    63.             return half4(c, 1);
    64.         }
    65.         ENDCG
    66.     }
    67. }  
    68.  
    69.  
    70. Fallback Off
    71.  
    72. }
    73.  
     
    Last edited: Oct 27, 2015
  3. WarrenB

    WarrenB

    Joined:
    May 24, 2012
    Posts:
    21
    Thank you bgolus!
     
  4. smvish

    smvish

    Joined:
    Jan 8, 2015
    Posts:
    6
    Hi I tried using this shader and it worked well when i use this in a new scene.
    i.e From scene1 i make a selection of image and in scene2 during update i create a new material with this shader code and the texture i create a new texture with the imported photosphere image.
    But later i use a button next to navigate to next image. i dont see the texture change in the skybox material
    why is this.

    newmaterial =newMaterial(Shader.Find("Skybox/Equirectangular"));
    newtexture=Resources.Load("img6",typeof(Texture))asTexture;
    newmaterial.SetTexture("_Tex",newtexture);

    GameObjectcamera=Camera.main.gameObject;
    Skyboxskybox=camera.GetComponent<Skybox>();
    skybox.material=newmaterial;

    Can you please let me know what the issue is.
     
  5. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    No idea, I've never tried to use the skybox component script and there's very little information on how it works. From the issues you're having you might need to toggle the skybox component off and on, or set the material to null before setting it to the new skybox. It could be that component, which has all it's functionality hidden in native code, only works once at runtime and never again, so you need to remove it and make a new one each time ... who knows.

    If I want to change the skybox I just change the RenderSettings.skybox directly.
     
  6. Eclectus

    Eclectus

    Joined:
    Oct 29, 2012
    Posts:
    20
    Thanks for the shader Ben - I think a way to deal with a vertical seam may be to set the source texture to "Wrap Mode" = "Repeat", as I didn't see any seams, but I may be missing something.

    Cheers
     
    Last edited: May 7, 2022
  7. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,342
    There’s a built in equirectangular skybox shader included with Unity these days. There’s no need to use this shader.

    The repeat wrap mode should be the default for any texture, and won’t solve the seam problem (though using clamp or mirror will make the seam worse). The “easy” solution to the seam is to disable Generate Mipmaps on the texture import settings, as the seam is caused by the sudden change in UVs causing the GPU to drop to the lowest mip level for a few pixels. That can be fixed with a more complicated shader, but generally mip maps aren’t needed for skyboxes.

    Cubemaps are still preferable, as they’re a more efficient use of texture memory than equirectangular maps.
     
    chadfranklin47 likes this.