My goal right now is to sample a light texture in urp (in a material used by a 2d sprite renderer) relative to the pivot position of an object as opposed to the fragment position. To get the "pivotUV" I have something like this in my vertex function: Code (CSharp): float4 pivotPositionCS = TransformObjectToHClip(float3(0,0,0)); float4 normalizedPivotPositionCS = pivotPositionCS / pivotPositionCS.w; o.pivotUV = ComputeScreenPos(normalizedPivotPositionCS).xy; However, when I output that value in my fragment function like Code (CSharp): return(SAMPLE_TEXTURE2D(_ShapeLightTexture0, sampler_ShapeLightTexture0, i.pivotUV)); Everything works as expected with some cases, but other instances seem to end up having their output tied together and are sampling relative to the world space coordinate (0,0,0) as opposed to the object-space coordinate (0,0,0). I took a look at the frame debugger and the objects that are drawing incorrectly are the ones that are getting batched together in a "Draw Dynamic" call. This makes some sense after reading about how unity implements dynamic batching: What's the best way for me to achieve what I want? I can't actually think of a way to make this work that doesn't involve disabling batching. If there's a way to make the shader aware of if it's being batched, I could pass in the world-space coordinate of it's origin point, but then if I understand correctly, that would require enabling gpu instancing which would ultimately disable any batching. Is there any way to make my shader aware of when it's being batched so that I can transform my (0,0,0) point to world-space when it's batching draw calls?
Related: https://forum.unity.com/threads/how-to-get-ui-image-screen-bounds-in-a-shader.1053821/#post-6914888
hey @bgolus thanks for pointing me at that thread, looks like that would easily solve my problem of passing data down to my shader. However it seems like there's no way to make the shader aware of when it's being batched (tbh I'm not fully confident this is a sensible question)?
The shader has no knowledge of if it’s being used on a batched mesh or not, no. That’s sort of the whole point of batching is to be able to render “multiple” objects as a single mesh without having to do anything special to the shader. That is of course assuming the shader doesn’t need to know the object space transform of the individual objects that are now combined into a single mesh with the transform matrix set to “nothing” (more specifically an identity matrix, which has no rotation, scale, or translation). To use the above technique you have to have the shader and your code assume you’re always baking the relevant data into the vertices.
okay so now I"m just asking for my own education, but doesn't it still make sense for a shader to be able to be "batch-aware"? If a shader was aware that it was being batched, it would still behave uniformly. Seems like it would work well with a multi_compile directive?
Unity certainly could have added a multi compile to special case out when something was being batched, but they built the whole batching system to not need it, so they didn’t. None of Unity’s official shaders require it knowing the object’s position, and generally you want to have as few multi compiles as possible as they can quickly increase the number of variants required (each new multi compile doubles the number of variants) so there usually has to be a darn good reason for it.