- Home /
Render transparent material without double occlusion
I would like to render an object that is semitransparent (in fact, the material itself is quite simple - just an unlit solid color with alpha), and I can achieve that, with this shader:
Shader "FlatMultiply" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
}
SubShader {
Tags { "RenderType" = "Transparent"
"Queue" = "Transparent" }
Pass { ColorMask 0 }
Pass {
Blend SrcAlpha OneMinusSrcAlpha
ColorMask RGB
Color [_Color]
}
}
}
However, when two objects with this shader go behind each other, the light is "double occluded" and it ends up more opaque. I don't want this. Rather, I would like the light to be only once-colored. How can I achieve this effect?
Computationally, I would try to find which pixels are touching my material, then render the background, then darken those pixels I found in the first pass, but I don't have the shader-fu necessary to pull this off. Anyone have any ideas?
EDIT: The AlphaVertexLitZ shader does the trick for the transparency problem (and I've incorporated the technique into the code segment above), but it is designed for a single object with a non-convex geometry. Is there a way for me to use this shader so that it applies to all objects with my material in the scene as a whole? I suppose I could achieve the effect I want by collecting all objects in the scene into one mesh and using this shader on it, but that will incur monstrous overhead, and would defeat the purpose of having separate objects. Can I specify that I want all objects to be rendered in the same pass in ShaderLab?
Need to clarify what you are after. 'the light is "double occluded"'?
I'm not sure how else to describe the effect. if the background is white and the object material color is 50% clear black, then looking at a single object, your see 50% gray; looking at two objects in the region where they overlap, you see 25% gray (darker). I want it to be 50% gray in this region too.
Hard to conceive of what use that'd be. But... from that standpoint of a shader, that's not possible. Depending on the other things that need to happen/not happen, however, you could just turn on writing Z on the shader. That's unusual for transparent shaders... but it might get you what you want...maybe.
I don't understand your position. I'm asking a very dumbed-down version of what has to be a common problem: if I have a complex object (say a person) and I want to make it uniformly half-transparent, I can't just set the alpha on all the faces, because then you will be able to see internal geometry of the person, in areas where the forward face of one polygon is occluded by the forward face of another. Ins$$anonymous$$d, the proper effect would need to render the person and the background separately (with no transparency), and then just overlay the two images with 50% alpha. This task must be done in the shader, as the script doesn't have the necessary render-time information (or at least, it would be a stretch to try to do it in script).
As for writing Z in the shader, I thought I was; I have intentionally left out a ZWrite Off
line above.
Here's a shader that does what I want, but applies only to a single object. I want this to work over all objects with my material in the scene as a whole (the objects themselves are convex, i.e. boxes, but there are many of them and they pass behind each other frequently).
I said turn ON writing Z, not OFF.
This would, in theory, keep it from rendering other transparent things "behind" the object in question. This requires that Unity sorts transparent objects by distance, rendering near objects first. (which it does) Of course that only works in the simple case.... because sorting is based on a single point (the pivot of the object in question) and the issues of batching which can mess up ones best laid plans.
But not sure that's going to be what you want either. I can't visualize what you want it to look like when two translucent objects overlap visually (vs. what it normally looks like).
$$anonymous$$aybe a mock up in photoshop?
Answer by digama · Mar 16, 2013 at 08:38 PM
A surprising solution that doesn't make any sense to me is that removing the "Queue"="Transparent"
tag or more generally setting the render queue <= 2500
solves the problem. From this question, I understand that this cutoff has something to do with the sort order of the objects, but this solution is not optimal to me, because I need it to render after some projectors, so it needs at least "Queue"="Overlay"
to work properly. Is there another way to force the sort order without changing the render queue?
The final code:
Shader "FlatMultiply" {
Properties {
_Color ("Main Color", Color) = (1,1,1,1)
}
SubShader {
Pass { ColorMask 0 }
Pass {
Blend SrcAlpha OneMinusSrcAlpha
Color [_Color]
}
}
}
Actually, this solution is even less optimal since now I may need to have other transparent objects in the scene, and so I think I may need to abandon surface shaders altogether and go to a fragment shader. The algorithm in my head is to render each transparent layer from back to front as usual, except that at the first instance of my special material, a flag is set, so that any layers of the same material in front will see the flag and not draw. This will render the objects of my material in the back with higher priority than the front, but as I mentioned earlier, this is acceptable to my application.
Answer by Kwajo7 · Sep 28, 2020 at 10:53 AM
I came here looking to make an effect where there's a transparent overlay on the screen wherever the player is occluded. My player object also uses multiple meshes, so a similar effect to this may be useful for the effect asked about in the question. I eventually figured it out, but for anyone else here for the same thing, I posted how I did it on a thread in the forums.
Your answer
Follow this Question
Related Questions
Cant get Alpha Channel to Work with Custom Shader 1 Answer
Add transparency to this shader? 0 Answers
Sorting issues within single transparent mesh 1 Answer
What does the "alpha is transparency" setting actually do? 1 Answer
Decal Alpha Blend 0 Answers