I'm currently using a VBO for the texture coordinates, normals and the vertices of a (3DS) model I'm drawing with "glDrawArrays(GL_TRIANGLES, …);". For debugging I want to (temporarily) show the normals when drawing my model. Do I have to use immediate mode to draw each line from vert to vert+normal -OR- stuff another VBO with vert and vert+normal to draw all the normals… -OR- is there a way for the vertex shader to use the vertex and normal data already passed in when drawing the model to compute the V+N used when drawing the normals?
R – use a vertex shader to display a models normals
openglshadervertex
Related Solutions
For a cube with 8 vertices, there would be 6 * 6 = 36 normals (since each surface renders with two triangles).
Correct me if wrong, but I only see 6 normals, one per face. All vertices on that face will use the same normal.
With indexed drawing I can only pass 8, one for each vertex. This does not allow me to pass surface normals, only averaged vertex normals.
Here's where your reasoning fails. You do not just pass vertex locations to the shader, you pass a whole bunch of vertex attributes that make the vertex unique.
So if you use the same vertex location 6 times (which you'll often do), but with a different normal each time (actually two triangles will share the same data), you actually should send all the data for that vertex 6x, including duplicates of the location.
That being said, you don't need 36, you need 4*6=24
unique attributes. You have to send all vertices for each face separately because the normals differ and per face you have to differ between 4 positions. You could also see it as 8*3 because you have 8 positions that have to be replicated to handle 3 different normals.
So you'll end up with something like:
GLFloat positions[] = { 0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
...}
GLFloat normals[] = { 1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f,
1.0f, 0.0f, 0.0f,
... }
Note that while within normals
and positions
there is repetition, but that the combination of both at the same position is unique.
Short version: You can't!
Long version: Even if the vertex shader is moving the vertices, it only knows the updated position of the current vertex – to calculate new face normals, it would have to know the updated position of all the neighbor vertices, and so far, WebGL doesn't allow that.
Although the vertex shader does calculate normals, they're all based on the original normals, which are passed to the vertex shader along with the original vertex positions. Those calculations are mostly just the standard normal-related things required for the fragment shader, such as accounting for light position, transformations, and so on, and they all assume that the vertices are going to hold still relative to each other in object space.
It's relatively easy to update normals with the CPU and pass those to the vertex shader, but if you must do it in the vertex shader, there are some sneaky ways to fake it, such as using bump maps; and if the vertices are being moved based on any kind of parametric computation, you can generate some neighbors on the fly and check the normal between them, which is definitely cheating.
Sources:
Best Answer
No, it is not possible to draw additional lines from a vertex shader.
A vertex shader is not about creating geometry, it is about doing per vertex computation. Using vertex shaders, when you say
glDrawArrays(GL_TRIANGLES,0,3)
, this is what specifies exactly what you will draw, i.e. 1 triangle. Once processing reaches the vertex shader, you can only alter the properties of the vertices of that triangle, not modify in any way, shape or form, the topology and/or count of the geometry.What you're looking for is what OpenGL 3.2 defines as a geometry shader, that allows to output arbitrary geometry count/topology out of a shader. Note however that this is only supported through OpenGL 3.2, that not many cards/drivers support right now (it's been out for a few months now).
However, I must point out that showing normals (in most engines that support some kind of debugging) is usually done with the traditional line rendering, with an additional vertex buffer that gets filled in with the proper positions (P, P+C*N) for each mesh position, where C is a constant that represents the length you want to use to show the normals. It is not that complex to write...