I am trying to figure out how to create this rendering scenario below, but I’m not sure exactly how to go about it…
Object A- Solid object
Object B- Transparent object
Object C- Background geo
If the transparent object B travels behind object A it would act by default as expected. But if it travels in front of object A it would “subtractively render” to show through that object A, revealing whatever is behind it. (All objects would have collision so there would be no intersecting)
Would this mean a custom shader, or could this be achieved with layers alone? Any suggestions would be appreciated. Thank you.
BAM!!! I did it. I didn’t try it myself the other day because I was a bit busy, but here you go:
It possible to force Unity to fake object ordering, if each object is its own separate camera and you put the cameras in sequence you want the objects ordered.
With my example there are three cameras at the same transform. They are under a parent, and I’m treating the parent as if its one camera. These are the camera settings:
Camera 1
Depth: 0 (it’s drawn first)
Clear Flag: Solid Color (it fills the background with a color)
Culling Mask: Camera 1 (will rendering everything with “Camera 1” layer)
Camera 2
Depth: 1 (it’s drawn second)
Clear Flag: Don’t Clear (it doesn’t remove anything from the depth and color buffer that was drawn previously by Camera 1)
Culling Mask: Camera 2
Camera 3
Depth: 2 (it’s drawn last)
Clear Flag: Don’t Clear (it doesn’t remove anything from the depth and color buffer that was drawn previously)
Culling Mask: Camera 3
Then…
Set object C under the “Camera 1” layer, B under “Camera 2”, and A under “Camera 3”. |
I tried using the Transparent/Diffuse shader that came with Unity for object B, but it seems that those shaders purposely don’t write to the depth buffer. Instead, use the following shader:
Shader "Subtractive"
{
SubShader
{
Pass
{
// use a pixel blend, so that it takes from the color from the buffer
Blend SrcAlpha OneMinusSrcAlpha
// pixel blending only works with lighting, so turn it on
Lighting On
// make sure the depth gets written in
ZWrite On
// set the material color to invisible
Material
{
Diffuse (0,0,0,0)
}
}
}
}
The clear flag settings will make sure cameras create a composite image instead of completely overwriting one another. The camera ordering forces a rendering order of C, B, A; B will definitely get prior access to the buffers before A. The shader will make sure B writes to the depth duffer but does not write to the color buffer in a way that changes it.
I hope that’s the solution you’re looking for! Cheers!
Just like to add that it’s also possible with one camera and using the renderQueue property of the material. The Depthmask shader on the wiki does a quite similar job.
The only issue i know is that it’s difficult to get this to work with Unity terrain shader and the default skybox is masked as well since the skybox is drawn quite late in the renderorder to avoid overdraw. This can be fixed by using a custom skybox or i guess by using multiple cameras but haven’t tested it.
The floor, the player and everything else is my C. There’s a big sphere (my B) over the player which you can spot in the center. All the walls in the bottom are my A.