I try to create a metal plate with holes. Instead of creating the holes for real I fake them with an opacityTexture. Unfortunately you can look inside of the plate with this method. Is there a way to make the plate look solid while using the opacityTexture?
If you donāt want to look through, set the alpha values to 1 for the holes, or donāt use an opacity texture and create the holes in the diffuse texture? Maybe a PG would help to understand.
I want to look through the plate but I donāt want to look inside of the plate. If you have a plate with 0.5cm thickness and stamp some holes in it you are not able to see the space between front and back (first image of my prev post). It should look like the second image of my prev post.
I created a pg: Babylon.js Playground. I think my problem should be clearer now. All vertical spaces should look solid. Is it possible to solve it with parallax mapping? I will give it a try.
some months past and I am still facing this problem without a solution that fits my needs. I know that there are always limitations but I want to find the best tradeoff between performance and quality.
CSG
Perfect result in terms of quality, but it takes a very long time to create the holes. Imagine a 100x100 cm plate with 1cm holes and 0.5cm offset. This leads to around 4.5k holes. CSG is slow and the plate gets a lot of faces due to the holes. A bigger plate or smaller holes make the problem even worse. This is not usable on my pc and smartphones will surely explode.
Parallax Occlusion
As far as I understand parallax occlusion places multiple layers of the texture above each other to create the illusion of depth. This wonāt work here because it is not just depth but a hole. So you should be able to look through the hole. Or is it still possible? Can we use parallax map with node material?
SPS or Thin Instances
I like your idea @JohnK but unfortunately there a two issues with this approach in my case. First I want to edit the mesh after creating the holes further (probably using csg) and second the plate is not just a regular box but a box with beveled corners and edges. I could imaging to create the outer part with the beveled corners and edges separately from the inner part which equals a box. But since I canāt csg the thin instances I canāt use this method.
Shader
I am very unexperienced with shaders so I wonder if it would be possible to create such an effect with it. I would love to know this.
Note: to avoid z-fighting between the face of the box and the top of the cylinder, the cylinder should be a little longer so that it protrudes a bit at the top and bottom
Draw the inside of the (uncapped) cylinder (cull front faces instead of back faces) with a material that disables z-testing (else the cylinder wonāt show up because of step 1):
You can see itās not ok, thereās an artifact because the cylinder is not clipped by the plane (because of z-test = false)
To overcome the problem, after step 2 draw again the cylinder from step 1 but with colorWrite = false and depthWrite = false but with z-testing = true. In effect, the hole in itself will be redrawn, which is pointless from a visual standpoint but is important for the stencil buffer: the stencil is enabled and a value (1) is written where the hole appears.
Now we can do step 3 but this time by enabling the stencil buffer so that we only draw where the stencil = 1:
We can see the cylinder corresponding to the leftmost hole is visible through the second hole because this cylinder is drawn where stencil=1, and stencil=1 for both holes. To fix the problem, you can use a different stencil value for each hole (1 and 2 for eg) that way they wonāt collide. In all generality, each hole should have its own stencil value, but we are limited to 255 different valuesā¦ In the PG below I have simply used 2 values and I have alternated between 1 and 2 between each hole. It does fix some artifacts but not everything, notably if you look at the plane at grazing anglesā¦
Last thing, to make it fast, use thin instances for the holes!
Thereās a way to make it work in all cases but itās slowerā¦
You can draw each hole one after the other and reset the stencil buffer to a 0 value between each draw. That way, the holes canāt āleakā one inside the other.
But to do this you must issue 2 draw calls per hole and you canāt use thin instances anymore (except for the first step as outlines above). So, in your case you get around 9000 draw calls which is too much: on my card (GTX 1080), Iām around 3-5 fpsā¦
But by reducing the number of holes drawn it works quite well:
Thank you very much. This solution is definitely the best one. I didnāt use stencil buffer before but your explanation makes it pretty clear.
Resetting the stencil buffer is not an option since the draw calls will kill all devices. But good to know that is would be possible to remove the artifacts. Anyway I think the best tradeoff is to have some artifacts but good performance.
@Evgeni_Popov , your post is really great and helpful. I am trying to translate your code to ThreeJS but I fail to achieve the effect as yours. Would you mind posting the code in ThreeJS too please?
I have posted my question in SO with some screen shots and code.