Calculating and Applying normals to a triangle mesh - opengl

I have a triangle mesh and I'm trying to calculate the normals so I can apply them when drawing the mesh. I'm using immediate mode (will probably change to vertex arrays when I get time to understand how they work) and drawing the mesh with GL_TRIANGLE_STRIP.
I am having trouble calculating the vertex normals. More precisely deciding which neighbouring vertices to use in the calculations and then deciding when to set those normals. Consider this:
1_2
|/| Supposedly a square where the numbers represent the vertex number in a
3 4 triangle strip.
I know you have to compute the cross product of 2 vectors belonging to a plane in order to get the plane normal. So in that example the top triangle's normal could be calculated by doing (2-1)x(3-1), and the second one by doing (2-4)x(3-4). How do you then apply the normals when drawing the triangle strip in immediate mode?
What I was doing was setting the first normal when vtx 1 is set, the second when vtx 4 is set, the third when vtx 5 is set, etc. This however gives issues as you obviously end up by having different normals for each of the vertices of a triangle (when they should all be the same). For instance, triangle |2,3,4| would only have vertex 4 with the correct normal (since for vertices 2 and 3 the normal would be the one of the first triangle).
So how should it be done? Is there a way, or do I need to change to GL_TRIANGLES? (I don't want to stop using immediate mode for now as I don't have time).

If I'm correct you're still only computing a normal per triangle? This is correct, but after that you should computed what the normal is per vertex. This is simply the normalized sum of all triangle normals that the specific vertex is attached to.
Once completed you can proceed with your immediate mode drawing, specifying a normal per vertex.

Related

Since OpenGL can perform built in backface culling, it must calculate vertex normals; can these be accessed instead of sending them as attributes?

Would like to understand this; it’s not quite clear why you have to upload normals but at the same time respect the winding order for normal calculation.
All vertices you give OpenGL within a rendering command are in a specific order. For array rendering, this means the order of the vertices in the array, as specified by the drawing command. For indexed rendering, it's the order of the indices in the range of index values you're rendering from. Instanced rendering defines that the vertices for each instance happens after the previous instance's vertices. And so forth.
The primitive assembly system for a triangle takes this sequence of vertices and breaks it up into triangles, depend on which kind of primitive you rendered. This means that each vertex output by the primitive assembly system has an order relative to the others for that triange; one vertex came first, then another, then the third.
Since triangles only have 3 vertices, there are two ways for the rasterizer to look at this order. The vertices can either wrap clockwise around the triangle or counter-clockwise, as seen in screen space. This is the triangle's winding order: the apparent order of the vertices, as seen from screen space.
It is the winding order which is used to determine how face culling works, not the normal. The GPU never calculates vertex normals. Or normals of any kind.

How to colour vertices as a grid (like wireframe mode) using shaders?

I've created a plane with six vertices per square that form a terrain.
I colour each vertex using the terrain height value in the pixel shader.
I'm looking for a way to colour pixels between vertexes black, while keeping everything else the same to create a grid effect. The same effect you get from wireframe mode, except for the diagonal line, and the transparent part should be the normal colour.
My terrain, and how it looks in wireframe mode:
How would one go about doing this in pixel shader, or otherwise?
See "Solid Wireframe" - NVIDIA paper from a few years ago.
The idea is basically this: include a geometry shader that generates barycentric coordinates as a varying for each vertex. In your fragment / pixel shader, check the value of the bary components. If they are below a certain threshold, you color the pixel however you'd like your wireframe to be colored. Otherwise, light it as you normally would.
Given a face with vertices A,B,C, you'd generate barycentric values of:
A: 1,0,0
B: 0,1,0
C: 0,0,1
In your fragment shader, see if any component of the bary for that fragment is less than, say, 0.1. If so, it means that it's close to one of the edges of the face. (Which component is below the threshold will also tell you which edge, if you want to get fancy.)
I'll see if I can find a link and update here in a few.
Note that the paper is also ~10 years old. There are ways to get bary coordinates without the geometry shader these days in some situations, and I'm sure there are other workarounds. (Geometry shaders have their place, but are not the greatest friend of performance.)
Also, while geom shaders come with a perf hit, they're significantly faster than a second pass to draw a wireframe. Drawing in wireframe mode in GL (or DX) carries a significant performance penalty because you're asking the rasterizer to simulate Bresenham's line algorithm. That's not how rasterizers work, and it is freaking slow.
This approach also solves any z-fighting issues that you may encounter with two passes.
If your mesh were a single triangle, you could skip the geometry shader and just pack the needed values into a vertex buffer. But, since vertices are shared between faces in any model other than a single triangle, things get a little complicated.
Or, for fun: do this as a post processing step. Look for high ddx()/ddy() (or dFdx()/dFdy(), depending on your API) values in your fragment shader. That also lets you make some interesting effects.
Given that you have a vertex buffer containing all the vertices of your grid, make an index buffer that utilizes the vertex buffer but instead of making groups of 3 for triangles, use pairs of 2 for line segments. This will be a Line List and should contain all the pairs that make up the squares of the grid. You could generate this list automatically in your program.
Rough algorithm for rendering:
Render your terrain as normal
Switch your primitive topology to Line List
Assign the new index buffer
Disable Depth Culling (or add a small height value to each point in the vertex shader so the grid appears above the terrain)
Render the Line List
This should produce the effect you are looking for of the terrain drawn and shaded with a square grid on top of it. You will need to put a switch (via a constant buffer) in your pixel shader that tells it when it is rendering the grid so it can draw the grid black instead of using the height values.

Dynamically create complementary triangles of a regular grid in OpenGL

I have created a regular grid which originates from a 2D image, i.e. each pixels has a vertex. There are two triangles per four pixels so that I have a triangle in the top right and in the bottom left. I use vertex and index buffers for that.
Now I dynamically remove triangles / faces at the border of two different kinds of vertices (according to my application) because else there would be distortions. I wrote a geometry shader which takes a triangle and outputs the triangle or nothing (see first picture). The shader recognizes if a triangle is "faulty" (has orange edges) and omits it.
Now this works fine, but I may lose some details because of my vertex geometry. I can add complementary triangles to the mesh (see second picture, new triangles with dashed orange line).
How do I accomplish this in OpenGL?
My first idea is to create one quad instead of two triangles, check for the four possible triangles cases and create those triangles dynamically in the geometry shader. But this might be slow; GL_QUADs are deprecated and alternatives might be slow too. What do you have in mind?
Here's my idea:
Put the whole grid in a buffer/texture.
Build four triangles for each four pixels. They cross each other, yes.
In the geometry shader you can tell if a triangle is "faulty" because it connects two wrong regions. Or, sampling form the texture, because the crossing triangle is valid, so this new one can be discarded.
EDIT: Another approach
Use the texture. Draw instanced with GL_POINTS. With some order and the help of the instanceID the shader knows where the point is.
For this point test the four possible triangles. If you instance top to down and left to right, only a point to the right and the two below are used for the four triangles. And you avoid repeating tests.
Emit only those you choose.

How should I use glNormal() for a vertex shared between a triangle and a quad?

Let there be a vertex which is part of a triangle, and of a quad.
To my best understanding, the normal of that vertex is the average of the normal of the quad and the normal of the triangle.
The triangle is drawn before the quad. When should I call glNormal and with what vector?
Should I call glNormal 2 times, each time with the same vector (the average normal vector)?
Should I call glNormal the last time the vertex is drawn, with the average normal vector?
To my best understanding, the normal of that vertex is the average of
the normal of the quad and the normal of the triangle.
Ideally, the normal vector should be orthogonal to the surface that you are rendering, on any point. However, the GL only supports rendering surfaces only as polygonal models (at least directly). So there are two principal possibilities:
The polygonal representation does exactly represent the object you want to visualize. A simple example would be a cube.
The polygonal represantation is just an (picewise linear) approximation of the surface you want to visualize. Think of smooth surfaces.
In case 1, you need one nomral per triangle (as the normal is unchaning for a flat surface defined by a triangle). However, this means that either for neighboring triangles who share an edge or corner, the normals will have to be different. From GL's point of view, each of the trianlges use different vertices, even if those vertices share the position in space. A vertex is the set of all attributes, not just the position. For the cube, that means that you will need not just 8 different vertices, but 24, so you have 3 at each corner.
In case 2, you do want to cover up the polygonal structure of the model as good as possible. One aspect of this is using smooth shading techniques. Averaging the normales of adjacent traingles at each vertex is one heuristic of doing so. In this case, neighboring primitives actually can share vertices, as the normal and the position of some corner point is the same for any triangle connected to it.
This heuristic has some drawbacks, especially if your surface does contain both smooth parts and "sharp edges" you want to preserve. There are some improved heuristics which try to detect sharp edges and splitting vertices to allow different normals for the connected triangles to not shooth such edges. But all such heuristics might fail in some cases - ideally, the normals are provided when the model is created in the first place.
The triangle is drawn before the quad. When should I call glNormal and
with what vector?
OpenGL is a state machine, meaning that things you set kepp that way until you channge them again - and setting normals is no exception. The second thing to note is that normals are a vertex attribute. So for every vertex, every arrtibute has always some value (but depending on the rest of your GL state, not all of these attributes are used when rendering).
Since you use the fixed-function GL, normals are builtin vertex attributes - so every vertex you issue in some way has some value as its normal attribute - in immediate mode rendering with glBegin()/End(), it will be the one you set with the most recent glNormal() call (or it will have the initial default value if you never called glNormal()).
So to answer you question:
YOu have to set that normal before you issue the glVertex() call for that particular vertex for the first time, and you have to re-issue that normal command for the second time drawing with "this" vertex (which technically is a different vertex anyway) if you did change it inbetween when specifying some other vertices.
To my best understanding, the normal of that vertex is the average of the normal of the quad and the normal of the triangle.
No. The normal of a plane is a vector pointing 'out of' the plane at a 90 degree angle. In OpenGL, this is used in shading calculations, and to support various effects, OpenGL lets you specify whatever normal you want instead of calculating it from the primitive. For flat lighting, the normal should be set to the mathematical definition of the normal for each primitive, while for smooth lighting, the normal should be set to the average normal of all primitives that share the vertex.
glNormal sets a value in OpenGL that is read whenever you call glVertex, and is persistent until you call glNormal again. So this code
glNormal3d(0,0,1)
glVertex3d(1,0,0)
glVertex3d(1,1,0)
glVertex3d(0,1,0)
glVertex3d(0,0,0)
specifies 4 vertices, each with a normal of (0,0,1).

How many vertices does a triangle fan use opengl

I am learning openGL, and i have come across triangle fans using vertex buffer objects. If given an array of vertices to render, how does openGL decide how many of those vertices must be used to construct a triangle fan. It seems like an arbitray number of the vertices could be used.
This can easily be explained by comparing Triangle Strips with Triangle Fans.
Triangle Strip
As you probably know, a Triangle Strip is a set connected triangles which share vertices, this allows for more efficient memory usage. (We save memory because we don't store all duplicated vertices)
Example of a Triangle Strip
Triangle Fan
On the other hand we have a Triangle Fan, this is also a set of connected triangles. Though all these triangles have one vertex in common, which is the central vertex. (The first vertex is always the center)
With that said we can take the same image above and change the order of the vertices. When that done the Triangle Fan would look like this. (Where A, is the first and central vertex)
Example of a Triangle Fan
In the image above the Triangle Fan will only work in the colored area, because of how the vertices need to be arranged according to be a Triangle Fan.
Visually, this is how a triangle fan works:
Each triangle shares the central vertex A, and re-uses the last vertex addressed. Thus after defining ABC each following triangle only requires 1 point (e.g. D, E, F).
Indices: A,B,C,D,E,F [Count: 6]
Triangles: (A,B,C)
(A) (C,D)
(A) (D,E)
(A) (E,F) [N=4] --> 4+2 = 6
Another way of thinking about this is that each triangle shares an edge radiating from a central vertex with the prior triangle; literally like a folding a paper fan.
You need N+2 vertices, where N is the number of triangles in your fan.
Look here: GL_TRIANGLE FAN Explanation
The more vertices you give to openGL, the more triangles you get. The first vertex will be common to all triangles. First triangle consists of the vertices 1, 2 and 3. Second triangle consists of 1, 3 and 4. And so on.
You get n - 2 triangles for n vertices.
That is specified by the command which you use to do the rendering. For example both drawArrays() and drawElements() have a count parameter which specifies the number of vertices to use.