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.
