Projector Render Order

We’re using a combination of multiply and alpha blended projectors. This works well for what we’re trying to do, but now we’re having a problem with the projectors rendering in the wrong order. The alpha blended projectors are for adding detail to the environment and the multiply projectors are for blob shadows. The multiply projectors should be rendered after the alpha blended projectors, but I can’t find a good way to force this.

Doesn’t look like changing the shader queue order makes a difference.

Any ideas?

You know way more than I do about shaders Shawn, but have you tried changing the Offset values?

Offset shouldn’t matter if there are no Z writes involved.

Don’t think that would make much of a difference. Projectors only sample depth, they shouldn’t be writing to it. So the projectors really aren’t aware of the other’s depth. Though I don’t think depth is really the issue here. I need both of the projectors to render in the same place, but if the blob shadow renders first, there’s no (fixed function) way for the alpha blended projector shader to detect that and only show through the darkening of the multiply projector.

D’oh :wink:

I took a quick look at the standard “FX/Projector Multiply” shader and besides the Queue the Offset was the only other thing I saw in there that might make a difference… but you’re right, there’s no need for it to even be there.

Pretty sure there’s a reason for the offset, might be related to DirectX. I forget… but yeah, not going to be the solution to this problem.

Yeah, right now all projectors effectively render themselves in Geometry+501 render queue.

I guess it would make sense to make them actually pay attention to the Queue tag in the shader they use, right?

I would almost expect a render order property in the inspector, much like the camera’s depth property. That would make sense to more people and allow artists to input values as desired without having to touch the shaders. We’ll want control over the render order of all of the alphablended projectors and needing a unique shader for each queue setting will be a pain.

So I assume this means that there’s no workaround in the current version of Unity?

I just want to chime in here because I think this is really important: Material.renderQueue needs to be serialized and exposed in the inspector. It would be incredibly useful because nobody would have to write any code (shaderlab or otherwise) to change Render Queues for any material ever. Assuming that Projectors are changed so that they respect Render Queues in the first place.

Agreed, this would be wonderful!

I guess this is still true for the latest Unity version?

I would actually like to have my projector material using “ZTest off” and render all my geometries (except the floor) after projector has done rendering. This is to avoid some z-buffer flickering issues that result from the geometries vs. projector. I tried setting projector’s render queue in the shader, as well as with Material.renderQueue, but without any luck. Of course I could set the render queue value for my geometries > Geometry+501, but I would much rather do it with projector than changing it for the geometries. Any ideas if there is a way to control the projector render queue?

Anyone know if this has ever changed? Just googling around and I have the exact same problem. I was hoping this:

would fix my problem, but it’s a no go.

I’m using a crude workaround by turning them on-off to have them correctly reordered. When projector is turned on it goes on top. When a projector is to be turned on, but it should be at the bottom of the stack, or in the middle - those above it have to be turned off and on to reposition them again above it.

Hi Peter. Your solution looks to be the most promising. How do I implement it ? Is this just about calling GameObject.SetActive or set Component.enabled in a certain order, or is it about having their ‘Start’ function be called in a certain order, in which case I would guess I need some coroutine mechanism…

This can be achieved by setting the renderQueue of the projector material like this:

myRendererGameObject.GetComponent<Projector>().material.renderQueue = 2999;

Ben