Hello! I made this custom function in the shader graph but I seem to keep getting the following error:
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!
Ah, I see. It was just weird for me since in the shader graph, it’s called SamplerState, while in the scripts, it’s called sampler2D. I thought those were two different things. Thanks for the help!
@alexandral_unity 's comment and link is misleading here, unless you actually read the entire page all the way to the bottom.
SamplerState and sampler2Dare 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 notsampler2D 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 what a working Custom Function node looks like:
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.
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.
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…
I see in the HLSL reference there are 2 tex2D methods. It seems everyone in this thread is referencing tex2D(samplerState, UV)…I’m looking to use the tex2D that takes 4 arguments (sampler state, UV, dx, dy). is there a Direct3D 11 Unity macro or alternative .Sample() method that is equivalent to this tex2D (HLSL reference) - Select the mip level - Win32 apps | Microsoft Learn
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.
The parameters in the SAMPLE_TEXTURE2D_ARRAY_LOD call as I understand them are as follows:
Getting the instanced Texture2DArray
Using the given UnitySamplerState ss and accessing the SamplerState within it as .samplerstate
Using the given float2 uv coordinate
Getting the instanced index to specify the slice of the texture 2D array to use
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?