Low polygon cone - smooth tip shading

If you divide the cylinder into an 8-sided prism, calculating the normals of the vertices based on their position ("smooth shading"), it looks pretty good.

If you divide the cone into an 8-sided pyramid, calculating the normals based on their position, you get stuck at the tip of the cone (technically the top of the cone, but let me call it the tip to avoid confusion with the mesh vertices).

8-sided cylinder vs cone

For each triangular face, you want to combine normals along both edges. But since only one normal can be specified at each vertex of the triangle, you can match one edge or the other, but not both. You can compromise by choosing the normal tip, which is the middle of the two edges, but now none of your edges looks good. Below is detailed information on what the average normal for each vertex of the vertex looks like.

face detail with tip averaging

In an ideal world, a GPU can rasterize a real quad, not just triangles. Then we could indicate each face with a degenerate quad, which would allow us to indicate a different normal for two adjacent edges of each triangle. But all we have to work with is triangles ... We can cut the cone into several โ€œpilesโ€, so that edge breaks are visible only at the tip of the cone, and not along everything, but there will still be a tip!

Does anyone have any tricks for smooth low poly cones?

+4
geometry directx 3d opengl mesh
Mar 07 '13 at 23:00
source share
2 answers

Yes, this, of course, is the restriction of triangles. I think that by showing the problem when you are approaching a cone from a cylinder, the problem becomes clear:

enter image description here

Here are some things you could try ...

  • Use the boxes (as @WhitAngl says). To hell with the new OpenGL, in any case it is used for ATVs.

  • Tessellate is a bit more even. Setting the normal on the tip to the common vector up removes any sharp edges, although it looks a bit strange against the unlit side. Unfortunately, this contradicts your question name, low polygonal cone.

    enter image description here

  • After making sure that your cone is centered around the beginning of the object space (or procedurally generates it in the vertex shader), use the position of the fragment to generate normal ...

    in vec2 coneSlope; //normal x/z magnitude and y in vec3 objectSpaceFragPos; uniform mat3 normalMatrix; void main() { vec3 osNormal = vec3(normalize(objectSpaceFragPos.xz) * coneSlope.x, coneSlope.y); vec3 esNormal = normalMatrix * osNormal; ... } 

    There may be some bizarre tricks you can do to reduce fragment shader operations. Then there is the whole balance of tessellation more versus more expensive shaders.

A cone is a fairly simple object, and although I like the challenge, in practice I don't see this to be a problem if you don't want a lot of cones. In this case, you can get into geometric shaders or instances. Even better, you could draw the cones using squares and racist implicit cones in the fragment shader. If the cones are all on the plane, you can try the normal display or even the parallax display.

+2
Dec 17 '13 at 17:02
source share

I struggled with cones in modern OpenGL (i.e. shaders) made up of triangles, but then I found a surprisingly simple solution! I would say that this is much better and simpler than what is proposed in the currently accepted answer.

I have an array of triangles (obviously, each has 3 vertices) that form the surface of the cone. I was not interested in the lower face (circular base), as it is really simple. Throughout my work, I use the following simple vertex structure:

  • position: vec3 (was automatically converted to vec4 as a shader by adding 1.0f as the last element)

  • normal_vector: vec3 (stored as vec3 in shaders, as it was used to calculate the point product with the light flux)

  • color: vec3 (I did not use transparency)

In my vertex shader, I only converted vertex positions (multiplying by the projection matrix and models), and also converted normal vectors (multiplying by the converted inverse model matrices). Then, the transformed positions, normal vectors and non-transformed colors were transferred to the fragment shader, where I calculated the point product of the direction of light and the normal vector and multiplied this number by color.

Let me start with what I did and found unsatisfactory:

Attempt # 1 . Each face of the cone (triangle) used a constant normal vector, i.e. all vertices of the same triangle had the same normal vector. It was simple, but did not achieve smooth lighting, each face had a constant color, because all fragments of the triangle had the same normal vector. Wrong.

Attempt # 2 : I calculated the normal vector for each vertex separately. It was easy for vertices on a circular cone base, but what should be used for the cone tip? I used the normal vector of the entire triangle (i.e. the same value as in attempt #). Well, that was better, because I had smooth lighting in the part closer to the base of the cone, but was not smooth near the tip. Wrong.

But then I found a solution:

Attempt # 3 : I did everything as in attempt # 2, except I assigned a normal vector at the vertices of the cone, equal to zero vector vec3 (0.0f, 0.0f, 0.0 ). This is the key to the trick! Then this zero normal vector is transferred to the fragment shader (i.e., between vertices and shader fragments, it is automatically interpolated with normal vectors of two other vertices). Of course, then you need to normalize the vector in the shader (!) Of the shader , because it does not have a constant size of 1 (which I need for a point product). Therefore, I normalize it - of course, this is impossible for the very end of the cone, where the normal vector has a size of zero. But it works for everyone else. What is it.

One important thing to remember is that either you can normalize the normal vector in the fragment shader. Of course, you get an error if you try to normalize a zero-size vector in C ++. So, if you need normalization before entering the fragment shader, for some reason, make sure that you exclude normal vectors of size 0 (for example, the tip of the cone or you get an error).

This ensures smooth shading of the cone at all points except the cone point itself. But this point is not important (who cares about one pixel ...), or you can deal with it in a special way. Another advantage is that you can even use a very simple shader. The only change is to normalize the normal vectors in the fragment shader, and not in the vertex shader or even earlier.

smooth cone example here

+6
May 12 '16 at 13:01
source share



All Articles