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

Texture2DArray slice only renders properly on one side

Discussion in 'Shaders' started by pixlweaver, Mar 17, 2018.

  1. pixlweaver

    pixlweaver

    Joined:
    Dec 21, 2012
    Posts:
    92
    I'm trying to experiment with Texture2DArrays, but now I've been stuck for the last couple days.

    Using the example from the documentation here.

    Code (CSharp):
    1. Shader "Example/Sample2DArrayTexture"
    2. {
    3.     Properties
    4.     {
    5.         _MyArr ("Tex", 2DArray) = "" {}
    6.         _SliceRange ("Slices", Range(0,16)) = 6
    7.         _UVScale ("UVScale", Float) = 1.0
    8.     }
    9.     SubShader
    10.     {
    11.         Pass
    12.         {
    13.             CGPROGRAM
    14.             #pragma vertex vert
    15.             #pragma fragment frag
    16.             // to use texture arrays we need to target DX10/OpenGLES3 which
    17.             // is shader model 3.5 minimum
    18.             #pragma target 3.5
    19.            
    20.             #include "UnityCG.cginc"
    21.  
    22.             struct v2f
    23.             {
    24.                 float3 uv : TEXCOORD0;
    25.                 float4 vertex : SV_POSITION;
    26.             };
    27.  
    28.             float _SliceRange;
    29.             float _UVScale;
    30.  
    31.             v2f vert (float4 vertex : POSITION)
    32.             {
    33.                 v2f o;
    34.                 o.vertex = mul(UNITY_MATRIX_MVP, vertex);
    35.                 o.uv.xy = (vertex.xy + 0.5) * _UVScale;
    36.                 o.uv.z = (vertex.z + 0.5) * _SliceRange;
    37.                 return o;
    38.             }
    39.            
    40.             UNITY_DECLARE_TEX2DARRAY(_MyArr);
    41.  
    42.             half4 frag (v2f i) : SV_Target
    43.             {
    44.                 return UNITY_SAMPLE_TEX2DARRAY(_MyArr, i.uv);
    45.             }
    46.             ENDCG
    47.         }
    48.     }
    49. }
    Here is the result of this shader example on a primitive cube:


    The x and y angles of the cube are stretching all the textures in the array, from 0 to the _SliceRange value. Only one side displays the texture slice properly.

    How do you get the texture slice to render properly on all sides?
     
  2. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,539
    I think you would have to calculate it as a tri-planar effect. Because a modification to make the front axis repeat properly would alter how the other axis repeat.

    https://gamedevelopment.tutsplus.co...ure-mapping-for-better-terrain--gamedev-13821

    Though this method implies 3 passes. But you could likely do what you need to in a single pass, just calculating the repeating for up-down/front-back/left-right, and lerp between those based on positive surface normal direction
     
  3. pixlweaver

    pixlweaver

    Joined:
    Dec 21, 2012
    Posts:
    92
    Thanks for the response Invertex! I should have also mentioned though that I did get the texture array to work in a triplanar shader, but that seems to be the only way I can get it to work. Triplanar is really neat but what if I wanted to use the shader on an object that needs to move/rotate at runtime? Whether the shader is using world or local coordinates, the triplanar textures don't look right on a moving object.

    Are Texture2DArrays intended only for triplanar?
     
  4. Invertex

    Invertex

    Joined:
    Nov 7, 2013
    Posts:
    1,539
    No, it's not that they are meant only for tri-planar, they are for anything. What matters is how calculations are done, and the tri-planar process is aiding you in properly transforming your calculations to the different axis of the cube.
     
  5. pixlweaver

    pixlweaver

    Joined:
    Dec 21, 2012
    Posts:
    92
    Is it possible to "bake" the triplanar coordinates so that the Texture2DArray slices stay with a moving object?
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,329
    Really you had the right idea from the start. You need a box and UVs with 3 components. The mistake you made was you assigned the UVs like you would for a 3D texture rather than an array. Each face should have your usual XY UVs with 0,0 in one corner and 1,1 in the opposite. The Z value should simply be a constant value for the entire face of the slice in the array you want to use. Then you don't need to do any kind of scaling in the shader.