Search Unity

  1. Unity 6 Preview is now available. To find out what's new, have a look at our Unity 6 Preview blog post.
    Dismiss Notice
  2. Unity is excited to announce that we will be collaborating with TheXPlace for a summer game jam from June 13 - June 19. Learn more.
    Dismiss Notice

Resolved LWRP Custom Function with tex2dlod

Discussion in 'Shader Graph' started by Vyzier, May 8, 2019.

  1. Vyzier

    Vyzier

    Joined:
    Feb 22, 2015
    Posts:
    21
    Hello! I made this custom function in the shader graph but I seem to keep getting the following error:
    upload_2019-5-8_13-15-6.png

    I've tried both float4(uv, 0, 0) and float4(uv.x, uv.y, 0, 0) but I still keep getting the same error. I'm not quite sure what the problem is. Any help will be greatly appreciated!
     
  2. alexandral_unity

    alexandral_unity

    Unity Technologies

    Joined:
    Jun 18, 2018
    Posts:
    163
    Vyzier likes this.
  3. Vyzier

    Vyzier

    Joined:
    Feb 22, 2015
    Posts:
    21
  4. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,374
    @alexandral_unity 's comment and link is misleading here, unless you actually read the entire page all the way to the bottom.

    SamplerState
    and sampler2D are different things. A SamplerState is a Direct3D 11 thing and is the sampler state alone (i.e.: filtering & wrapping settings), and you need a separate Texture2D (which is the texture object by itself) to sample from. Where as sampler2D is a Direct3D 9 thing and is the sampler state and texture combined. When you use a sampler2D, you need to call tex2D(sampler2D, uv). When you use SamplerState, you need to call Texture2D.Sample(SampleState, uv). You cannot use tex2D() with a SamplerState or Texture2D, and you cannot use .Sample() without a Texture2D and SamplerState.

    Shader Graph is written with D3D11 in mind, so it uses Texture2D and SamplerState objects and not sampler2D objects, so you cannot call tex2D() and have it work.*

    * BIG ASTERIKS HERE, because it can work if you were compiling directly to OpenGL ES 2.0. And, in fact, if you were to use .Sample() and try to build to an OpenGL ES 2.0 target it would fail because that API does not support separate SamplerState and Texture2D objects, so it needs to use sampler2D and tex2D().

    So the real answer is you shouldn't use either. Instead you should be using the macros Unity provides for the SRPs which handles all of that weirdness for you.

    fixed4 color = SAMPLE_TEXTURE2D(Texture2D, SamplerState, uv);

    Or in your case instead of tex2Dlod or .SampleLevel use SAMPLE_TEXTURE2D_LOD.

    Here's a full list of all of these kinds of macros that the SRPs use:
    https://github.com/Unity-Technologi...r-pipelines.core/ShaderLibrary/API/D3D11.hlsl

    Here's what a working Custom Function node looks like:
    upload_2019-5-8_13-51-16.png

    One oddity to be aware of, notice it is working even without a sampler state defined. In this case the sampler state used is not the one defined by the texture asset, but a new unique "bilinear repeat" sampler state. The shader does actually define a SamplerState for each texture property, and that is what gets used by their Sample Texture 2D nodes when no override is supplied, but currently there is no way to access that sampler state in a generic way using a Custom Function node. This doesn't really cause any issues, it's just something to be aware of. Plus, if you use multiples of the "same" Custom Function node in your Shader Graph without a connected Sampler State node, each one will use a unique SamplerState, each using up one of the max of 16 total allowed per shader.
     
  5. Pancar

    Pancar

    Joined:
    Mar 11, 2013
    Posts:
    24
    I'm want to use SAMPLE_TEXTURE2D_LOD with URP-mobile , have you any advice?
     
  6. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,374
    Either use the existing Sample Texture 2D LOD Node, or use the above Shader Graph Custom Function example as is. Unity should hopefully translate that to the appropriate SamplerState-less version needed for mobile. If you're aiming for OpenGLES 2.0, you can't use it, period. Otherwise report it as a bug.
     
  7. Pancar

    Pancar

    Joined:
    Mar 11, 2013
    Posts:
    24
    upload_2020-1-28_10-44-4.png upload_2020-1-28_10-44-4.png

    I'm using with Custom Function,it's working on Editor but when i'm testing on android , i can't see the object.
    My graphic api is OpenGLES3.
     
  8. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,374
    Yep, no idea. As far as I know that should work, but I've never played with mobile Shader Graph / SRP stuff.
     
  9. imaewyn

    imaewyn

    Joined:
    Apr 23, 2016
    Posts:
    211
    Hello. What if I use 2dArrays? There is only two macros
    UNITY_SAMPLE_TEX2DARRAY(name,uv)
    UNITY_SAMPLE_TEX2DARRAY_LOD(name,uv,lod)
    Both of them don't use samplers state..
     
  10. DMGregory

    DMGregory

    Joined:
    Jul 31, 2013
    Posts:
    4
    Looking at the file here, we can find the following macros for you to use:

    Code (CSharp):
    1. #define SAMPLE_TEXTURE2D_ARRAY(textureName, samplerName, coord2, index)                  textureName.Sample(samplerName, float3(coord2, index))
    2. #define SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod)         textureName.SampleLevel(samplerName, float3(coord2, index), lod)
    3. #define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias)       textureName.SampleBias(samplerName, float3(coord2, index), bias)
    4. #define SAMPLE_TEXTURE2D_ARRAY_GRAD(textureName, samplerName, coord2, index, dpdx, dpdy) textureName.SampleGrad(samplerName, float3(coord2, index), dpdx, dpdy)
     
  11. mmcveigh33

    mmcveigh33

    Joined:
    May 23, 2019
    Posts:
    3
  12. bgolus

    bgolus

    Joined:
    Dec 7, 2012
    Posts:
    12,374
    tex2D(tex, uv, dx, dy)
    is an override that is equivalent to
    tex2Dgrad(tex, uv, dx, dy)
    . The DX11 equivalent is
    tex.SampleGrad(s, uv, dx, dy)
     
  13. AustinMclEctro

    AustinMclEctro

    Joined:
    May 3, 2017
    Posts:
    16
    Can we talk about how to use
    SAMPLE_TEXTURE2D_ARRAY_LOD(textureName, samplerName, coord2, index, lod) textureName.SampleLevel(samplerName, float3(coord2, index), lod)
    exactly in a Custom Function shader graph node, provided with an hlsl file?

    I am also attempting to instance the Texture2DArray.

    So, in my hlsl file:

    Code (HLSL):
    1.  
    2. #pragma target 3.5
    3. UNITY_INSTANCING_BUFFER_START(HeightmapProps)
    4.     UNITY_DEFINE_INSTANCED_PROP(Texture2DArray, _Heightmaps)
    5.     UNITY_DEFINE_INSTANCED_PROP(int, _HeightmapIndices)
    6. UNITY_INSTANCING_BUFFER_END(HeightmapProps)
    7.  
    8. void GetHeight_float(float2 uv, UnitySamplerState ss, out float4 rgbaOut)
    9. {
    10.     rgbaOut = SAMPLE_TEXTURE2D_ARRAY_LOD(UNITY_ACCESS_INSTANCED_PROP(HeightmapProps, _Heightmaps), ss.samplerstate, uv, UNITY_ACCESS_INSTANCED_PROP(HeightmapProps, _HeightmapIndices), 0);
    11. }
    12.  
    The parameters in the
    SAMPLE_TEXTURE2D_ARRAY_LOD
    call as I understand them are as follows:
    1. Getting the instanced Texture2DArray
    2. Using the given UnitySamplerState ss and accessing the SamplerState within it as .samplerstate
    3. Using the given float2 uv coordinate
    4. Getting the instanced index to specify the slice of the texture 2D array to use
    5. Using 0 as the lod
    This compiles, but fails at runtime with the error:
    Shader error in 'Shader Graphs/InstancingTestShader': sampler array index must be a literal expression at Assets/Scenes/Test/TestInstancingScene/HeightmapInstancing.hlsl(20) (on d3d11)


    Should I be using the sampler state differently? Or, how should I be using the instanced _HeightmapIndices array exactly?
     
    hurleybird likes this.