- Home /
Hiding triangles on a mesh (via shader? script?)
I'm creating a set of polygon-based effects (scripts) that can be applied to objects with mesh-related components. One thing I would like to do is hide/show certain polygons (triangles), to create effects such as random flickering of polygons and ability to hide polys by clicking on them.
A simple method that can work is to simply reconstruct the Mesh.triangles array without the vertices of the triangle to be hidden. I'd have to rebuild the Mesh.normals array as well in that case. The problem is however that calling this repeatedly would require constantly changing and recalculating the mesh, which hardly seems to be suitable for real-time effects such as the aforementioned random flickering, and would also screw up MeshCollider and InteractiveCloth behavior.
I have very little (if any) knowledge of shaders, but I'm guessing they are probably a better approach than scripting. What kind of shader would I use, and what would I supply it? For random on/off I'm assuming I can determine this in the shader, but for hiding specific triangles, is it possible to pass into the shader an array of triangle indices (as a 2D texture maybe)?
Thanks for any help.
Are you using triangle fans or strips? In other words are the vertices shared by multiple triangles?
From what I know the problem is that in the vertex shader you just have one vertex - if that vertex was legitimately in one visible triangle and one hidden triangle then I can't think how you would do it. If the vertices are unique then it would be possible.
If I were you I would be setting the uv2 of the vertex to be a vertex index in the shader and use a 2D texture to control whether the vertex is visible or not - if the vertex is to be invisible then I would return a normal for that vertex that was the same as the current view direction (basically pointing it away from the camera and hence culled if back face culling is turned on).
But you have to do it at the vertex level (change all three vertices for a triangle at once) not at the triangle level. $$anonymous$$y Noobs Guide To Shaders has stuff one writing shaders if you are new to it.
Actually it might be too late to turn the normal on consideration. You would probably be best off indicating that it should be a transparent colour if the normal dot the view direction is beyond visible or discard the fragment in that case (though that can be expensive).
I'm not necessarily in control of that since I'd like to apply it to any given mesh. But since this is ultimately for a specific project I could have the artists do that. I could also in theory dynamically rebuild the mesh so that each vertex is used by only one triangle.
If all vertices are unique then the interpolation between the vertices of the triangle will yield a constant u (in uv2) - you can use that to lookup into a texture which now contains an rgba value to multiply your colour by. So you could make triangles fade out and fade in using that method (or change colour tint).
Answer by aldonaletto · Nov 07, 2012 at 10:46 PM
I would simply reverse the winding order of the desired triangles: since most shaders use Cull Back, triangles facing the opposite side (with reversed winding order) are invisible:
function RevTriangle(numTriangle: int){
var mesh : Mesh = GetComponent(MeshFilter).mesh;
var triIndex = numTriangle * 3;
// swap two vertex indexes in the tri:
var tmp: int = mesh.triangles[triIndex];
mesh.triangles[triIndex] = mesh.triangles[triIndex+1];
mesh.triangles[triIndex+1] = tmp;
}
This method is simple, but may produce weird results when the camera moves in such a direction that makes the "invisible" triangles face it. Another possible solution (not tested!) could be to null the triangle: set all 3 triangle vertices to the same vertex index, so that the resulting triangle have zero area:
function EmptyTriangle(numTriangle: int){
var mesh : Mesh = GetComponent(MeshFilter).mesh;
var triIndex = numTriangle * 3;
// make the three vertex equal to the first one:
mesh.triangles[triIndex+1] = mesh.triangles[triIndex];
mesh.triangles[triIndex+2] = mesh.triangles[triIndex];
}
I've not tested this alternative, but based solely in logic arguments it should work perfectly: all GPUs should handle correctly zero area triangles, since small far triangles eventually fall in this case.
Notice that none of the above alternatives change the vertices, uvs, normals etc. - only the desired triangles are affected, and even the triangle count remains the same, thus both are very fast.
I had thought of the reversal method but like you say it won't work with anything but a static camera and mesh.
The empty method is a great idea. I implemented it and it works. 2 things though: 1. Won't this still mess with $$anonymous$$eshCollider and InteractiveCloth components that use the geometry for computing physics, animation etc.? 2. Weird behavior in the editor - apparently after modifying the shared$$anonymous$$esh of a Skinned$$anonymous$$eshRenderer in runtime, the editor doesn't reload the original mesh from the assets library (I'm using beta 4). I have to restart the editor to get the intact model back.
AFAI$$anonymous$$, the $$anonymous$$eshCollider isn't updated automatically (we have to assign the modified mesh to collider.shared$$anonymous$$esh in order to update it) thus the hole in the mesh should not affect collisions. But things seem different with the InteractiveCloth: apparently, any change in the mesh may affect the behaviour of neighbor triangles. If this is true, only UV manipulation and transparent shaders could produce transparency without affecting other triangles, but this would require non-shared vertices.
Answer by mitaywalle · May 22, 2018 at 12:11 PM
Simplies way is to mark vertex indexes, that you want to hide, make their vertex Color.a = 0, then use Particle Standard Surface shader, in cutout mode, or make any cutout shader use vertex Color alpha for hide
Answer by DaveA · Nov 07, 2012 at 10:09 PM
Depending on how many triangles you have, you may want to construct submeshes, one per triangle (or group of them) you would be hiding, and then adjust the alpha (say) of the material corresponding to that submesh.
I did that originally but it's really only for very few triangles, not for animated skinned meshes.
Doesn't have anything to do with animation or skinned meshes. Any mesh can have submeshes, thus, multiple materials.
Answer by StephenWebb · Sep 27, 2019 at 11:46 AM
Use a mask with a cutout or transparent shader. I was going to write an envelopment system - using the normals of the "bottom most" mesh to cast a ray into the scene and if it came into contact with another face on a mesh within a certain distance (like a piece of clothing), it would hide the verts from which the ray was cast...but it then occurred to me that if the UVs are set up properly on your mesh, you should be able to provide a simple black/white mask in the opacity channel to cover areas of the mesh you want to hide...