Search Unity

Question Strange artefact at one side of the spherically mapped material shader

Discussion in 'General Graphics' started by Deamonpog, Dec 21, 2022.

  1. Deamonpog

    Deamonpog

    Joined:
    Oct 8, 2013
    Posts:
    10
    I get this strange looking artefacts at the edge of my spherical mapping material ( at
    z = -1
    side of the sphere). My shader code is very simple as given below with comments.

    Code (CSharp):
    1.  
    2. Shader "Solar/MySphericalShader"
    3. {
    4.     Properties
    5.     {
    6.         _MainTex ("Texture", 2D) = "white" {}
    7.     }
    8.     SubShader
    9.     {
    10.         Tags
    11.         {
    12.             "Queue" = "Geometry"
    13.             "RenderType" = "Opaque"
    14.             "RenderPipeline"="UniversalPipeline"
    15.         }
    16.  
    17.         Pass
    18.         {
    19.             Tags
    20.             {
    21.                 "LightMode" = "UniversalForward"
    22.             }
    23.  
    24.             HLSLPROGRAM
    25.             #pragma vertex vert
    26.             #pragma fragment frag
    27.  
    28.             #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    29.  
    30.             struct appdata
    31.             {
    32.                 float4 positionOS : POSITION;
    33.                 float2 uv : TEXCOORD0;
    34.             };
    35.  
    36.             struct v2f
    37.             {
    38.                 float2 uv : TEXCOORD0;
    39.                 float4 positionCS : SV_POSITION;
    40.                 //float3 posWS : TEXCOORD1;
    41.             };
    42.  
    43.             CBUFFER_START(UnityPerMaterial)
    44.  
    45.                 sampler2D _MainTex;
    46.                 float4 _MainTex_ST;
    47.            
    48.             CBUFFER_END
    49.  
    50.             v2f vert (appdata v)
    51.             {
    52.                 v2f o;
    53.  
    54.                 // calculate position values
    55.                 VertexPositionInputs positionInputs = GetVertexPositionInputs(v.positionOS.xyz);
    56.  
    57.                 // gets the world space coordinate and normalize it
    58.                 float3 normPosWS = normalize(v.positionOS.xyz);
    59.  
    60.                 // v coordinate calculated to be in 0 to 1 range
    61.                 float pos_v = (normPosWS.y + 1.0f) / 2.0f;
    62.  
    63.                 float angle = atan2(normPosWS.x, normPosWS.z); // angle from north calculated using atan2
    64.                 // angle is between -pi to +pi range.
    65.                 // u coordinate calculated to be in 0 to 1 range
    66.                 float pos_u = (angle + PI) / (2.0f * PI);
    67.  
    68.                 o.uv = float2(pos_u , pos_v);
    69.            
    70.                 o.positionCS = positionInputs.positionCS;
    71.  
    72.                 return o;
    73.             }
    74.  
    75.             float4 frag (v2f i) : SV_TARGET
    76.             {
    77.                 float4 mainTexColor = tex2D(_MainTex, i.uv);
    78.                 return mainTexColor;
    79.             }
    80.             ENDHLSL
    81.         }
    82.     }
    83. }
    84.  

    upload_2022-12-21_4-18-12.png
     
    Last edited: Dec 21, 2022
  2. Glurth

    Glurth

    Joined:
    Dec 29, 2014
    Posts:
    109
    your V computation doesn't look quite right- I'd expect:

    u = atan2(x,z)/2pi (not sure why you ADD pi to the numerator in your version)
    v = 2 asin(y)/pi

    So V will map from your (normalized) pos.Y like this:
    upload_2022-12-21_13-40-17.png
     
    Deamonpog likes this.
  3. Deamonpog

    Deamonpog

    Joined:
    Oct 8, 2013
    Posts:
    10
    Thank you very much for the reply.

    I think this function you have given will scale up the texture near the middle of the image to be large and scale down the texture data in top and bottom of the image. I instead chose a function that linearly interpolates the [-1, +1] space of the texture image y-axis into [0, 1] space of the v-axis of uv map.

    I think that issue is with UV interpolation at the seam, I have found a fix for this which I will post shortly. Thank you :)
     
  4. Deamonpog

    Deamonpog

    Joined:
    Oct 8, 2013
    Posts:
    10
    After many investigations I found that the issue is with UV interpolation becoming problematic at the seam. When the rectangular coordinate system is mapped to a surface such a way that left edge must match with the right edge of the UVs the auto interpolation in the shader gets confused due to
    0+delta
    values being closer to
    1-delta
    values, where delta is some very small value (close to epsilon of the floating point representation).
    So, I found this paper by Marco Tarini : "Cylindrical and toroidal parameterizations without vertex seams" which explains a simple method for calculating the seam properly. They also have a webpage with some additional links including source code to their GLSL shader at this link.
    I will put a screenshot of their paper in here for your reference if anyone facing the same issue, in case the links are broken.

    upload_2022-12-22_1-33-31.png

    Image reference : Marco Tarini : "Cylindrical and toroidal parameterizations without vertex seams"