I’m working on 3D game and I converted my project to URP. Everything works fine expect sprites that previously were ‘Sprite/Diffuse’ so they were lit by 3D lights (kind of Doom style, 2D elements in 3D world, always facing you). But now ‘Sprite/Diffuse’ shader is not supported in URP, it converted my materials to use ‘Universal Render Pipeline/Simple Lit’ Shader which does not work with sprites, it’s for textures. There is ‘Universal Render Pipeline/2D/Sprite-Lit-Default’ but it’s only for using 2D Lights.
How do I make sprites littable by 3D lights again in URP?
As it stands right now you have to write your own sprite shader using the shader graph to create a sprite shader that interacts with regular 3d lights in a 3d world. It mostly works fine besides some problems with GPU instancing.
The main thing you need to do is the following:
To get the sprite set inside the sprite renderer you need a shader property called “_MainTex” (in the reference field, not the parameter name)
To get tiling and offset support for your texture you need to create a Vector4 parameter called “_MainTex_ST”, and use those values to modify the values inside a Tiling and offset node. (The naming ist just a convention, but the _ST suffix is important to automatically generate tiling and offset fields in your custom ShaderGUI using TextureScaleOffsetProperty()
Multiply VertexColor with your SampleTexture node to get the color set in the sprite renderer.
When you want to use GPU instancing there are some additional things to consider though. Here are some of the annoyances I found myself with it while writing one for our game:
(This is based of URP 7.4.3 on 2019.4.2f1)
The flip X and flip Y toggles on the sprite shader do not work as these actually flip the vertecies of the underlying quad the sprite renderer creats, but these are somehow lost when using gpu instancing. So in order to regain fliping you have to manually write it in your shader and add a seperate component to your sprites that modify the MaterialPropertyBlock. Inside the shader you need to add either two booleans or a Vector2 for the flipping. How you actually flip them can be achieved through two different means:
Do the same as the original sprite renderer and flip the vertex positions. Important here is that you need to enable double-sided rendering and that you also properly modify your normals.
Flip the texture by flipping the UV properly. This lets you keep double-sideed rendering disabled, but requires that you use “Full Rect” for your sprites. If you use tight, the mesh for the sprite will not fit your flipped texture.
A similar problem with the sprite renderer not being able to modify the mesh it is rendering on while gpu instancing is enabled is the color, as this actually sets the vertex colors of the mesh. This is also broken and just stays white. So again like with the flip, create a seperate Color parameter in your shader and update it through your extra component on your sprite using the MaterialPropertyBlock.
Lastly, if you use GPU instancing, for whatever reason the normal of the sprite mesh gets inverted. Meaning it points backwards, which in turn makes your whole sprite black. So simply flip it along all 3 axis. Little bonus about this would be if you used the INSTANCING_ON keyword to check in your shader if GPU instancing is enabled and either flip or not flip your normals based on it.