I am working on a 3D graphing calculator project where an XZ grid mesh is procedurally generated and the Y position of each vertex is dictated by an expression in terms of x and z. The issue is when the expression is x^2 + z^2, for example, all the triangles are facing towards the inside of the paraboloid and the triangles in the front do not show. Also when I try and make the mesh double-sided there is a lighting glitch and the whole mesh turns black. What I really need is a way to disable culling for this mesh.
No, this has nothing to do with culling. You simply can not render a single triangle that looks like two surfaces from two different angles. Disabling backface culling will just always render the triangle no matter from which side it’s viewed. However that doesn’t help if you actually want to have proper lighting. Every vertex has a vertex normal which specifies the surface front and angle. This normal is required for proper light calculation.
You essentially have those options:
- You simply can model your triangles two sided. That means you need your x-z plane twice.
- You could write a specialized two-pass shader where the first pass renders the front face normally (culling the backface) and have the second pass only rendering the backface (culling the front face) but manually invert the vertex normals in the shader for this pass.
- What’s also possible on newer devices is to use a geometry shader which could take in a triangle and emits two triangles (the proper front and back face).
- Another solution could be to use the “approximate partial derivative” functions ddx and ddy together with the cross product to calculate the flat surface normal inside the fragment shader to decide if the normal should be flipped or not. However this also limits the usecases and might cause issues for some edge cases.
The most flexible approach is the first one. Since it doesn’t depend on some special shader so you could use pretty much any shader you like. Of course it doubles your vertex and poly count. However this implicitly happens in the other cases as well at least from the rendering overhead’s perspective.
To address your title and your last sentence I’d like to add that culling is just the process of removing “things” based on some criteria. There are many different culling processes involved. First of all Unity does a CPU side frustum culling of gameobjects based on their AABB (Bounds). Many people who create meshes manually forget to call RecalculateBounds. That could mean Unity decides to not render an object (because its bounds is completely outisde the camera frustum) even parts of the mesh could potentially be seen. That’s why the bounds has to enclose the whole mesh.
Next we have the GPU performing also frustum culling. It simply discards all triangles which are not intersecting the camera frustum. The remaining triangles are clipped and rasterized to the screen.
Next we have the backface culling. A single triangle always has a front face and a back face. Which side is which depends on the winding order of the vertices on the screen. In Unity a clockwise winding oder is usually the front face and a counter clockwise order represents the backface. The main point why we do backface culling is, like i mentioned above, that we need lighting relevant data at each vertex to model a proper surface (most important the vertex normal). However this can only be done for one surface. When not using backface culling both sides would be treated equally. That means when the light comes from behind the surface (behind the front face, not facing the vertex normal) the face is in shade. Since the backface face the other direction the lighting would appear inverted.
Finally there might be “depth culling”. Though this is one of the latest stages and just involves a depth test against the depth buffer if the fragment that is processed should actually be rendered or not
So “culling” applies to many different thing and disabling any of them won’t fix your issue.