Set 3d texture into Internal-DeferredShading shader

I am modifying lighting in the Deferred pipeline and I would like to set a constant-for-all-lights 3d texture sampler into the Internal-DeferredShading shader, how do I do this?

Normaly in Unity you have a shader and a material associated with it, so that you can set the texture you want in the material. But there is no material when you override the standard lighting shader.

Alternatively with CommandBuffer-s you have SetGlobalTexture(). But the later only works with RenderTargets.

Is there a way to pass a 3d texture to the overriden lighting texture?

Have a script that calls Shader.SetGlobalTexture() on Awake() somewhere in the scene.

1 Like

Wow, really simple, and works, thanks!

Hey, what if I want to change that texture every time a different light is drawn? Is there a way to do this? Is there a method in MonoBehaviour I can override?

If you’re using deferred, you could use command buffers and custom lights instead of overriding existing Unity lights. There’s no event to hook per light.

ic, thanks for your reply.

I am currently setting floats with CommandBuffer.SetGlobalFloat() and then in the shader I have a branch like this:

if (_num > 2)
res = tex3D(sampler0, …);
else if (_num > 1)
res = tex3D(sampler1, …);
…

The CommandBuffer I use is attached to each light into LightEvent.AfterShadowMap, however, there is a problem: lights that don’t cast shadows don’t execute the buffer. In fact ANY event I tried for point lights without shadows gets the buffer ignored. Is there any way to ensure the buffer gets executed?

edit: Nope, I’m wrong.

That won’t do what you expect. By the time the lights are actually rendered the value of that float will simply be the value set by the last light to have it’s shadow maps rendered.

Unity’s deferred pipeline (and in fact almost every rendering path and game engine) runs roughly like this:
1. Render all shadow maps
2. Render deferred gbuffers
3. Render all deferred lights
4. Render transparent stuff
5. Render image effects

There’s some stuff that can happen in between and before some steps, like you can have image effects that run before transparent stuff and of course there’s the command buffers, but generally those are to modify or add to what’s already being rendered. Like a command buffer for lights are for injecting stuff into the shadow maps, or potentially copying the shadow maps for use elsewhere.
However because all of the events that command buffers can hook onto for lights are for shadows, and those all render prior to actually rendering the lighting into the scene, a global float you set on each light will just override the value over and over.

When I said “use command buffers and custom lights” I really did mean custom lights. It would require 100% custom code, including rendering out the shadow maps if you want your lights to cast shadows. There are a handful of examples of this on the forum, and in the documentation.

Here’s Unity’s manual for Command Buffer which includes examples for custom light types:

Here’s someone who implemented a custom shadow system and released the code:

And then there’s Valve’s The Lab renderer, which is a custom forward light and shadow setup:

I might be wrong, but could you go and check Frame Debugger for the actuall order? From what it shows, the shadow maps are rendered inbetween lights (which always confuses me as changing render targets is expensive, as far as I know, but, at the same time, this might have been done to save on memmory requirenments). Anyway, my experiments show that you are right, it’s a shame that they don’t have a more flexible CommandBuffer system.

I will not implement my own lights though, it’s too difficult to implement, to maintain across Unity versions AND to make work with custom plugins like Alloy. I will just have to be less efficient with my shader algorithm.

P.S. Thanks for the links btw.

Interesting, either I’m miss-remembering how it used to work or they changed it since I stopped working with deferred (I’ve been working on VR projects for the last two years so exclusively using forward rendering). You’re right that it does render the shadows between each light so your technique should work, at least for those lights with shadows.

For forward it absolutely does do all shadow maps first.