Vizualizing vertex picking of a mesh in OpenGL - c++

For fun I am trying to build a miniature Blender using (modern) OpenGL. As part of it I want the user to be able to pick vertices. Each time the user picks a vertex I want the vertex to turn red. My question has nothing to do with finding the intersecting vertex, but rather how one would visualize the picked vertex.
I have managed to paint the picked triangle (instead of the picked vertex) by using the following in my fragment shader:
if(gl_PrimitiveID==intersectingFace)
color=vec4(1.0f,0.0f,0.0f,1.0f);
where intersectingFace is a uniform that holds the index of the meshe's intersecting face.
In order to pick a vertex instead of a face I thought of loading a sphere mesh into my scene,scaling it down and translating its center to the position of the intersecting vertex. I was wondering whether there is a simpler solution that this one.

There is a built-in variable that tells you the index of the Vertex, rather than the the primitive: gl_VertexID.
gl_VertexID: the index of the vertex currently being processed. When
using non-indexed rendering, it is the effective index of the current
vertex (the number of vertices processed + the first​ value). For
indexed rendering, it is the index used to fetch this vertex from the
buffer.
Note: gl_VertexID will have the base vertex applied to it.
So rather than setting the intersecting face uniform value, like you are doing now, you can do the same with the vertex index and then compare it against gl_VertexID.

Related

Disambiguate "vertex" in "vertex shader"

https://www.khronos.org/opengl/wiki/Vertex_Shader says that "The vertex shader will be executed roughly once for every vertex in the stream."
If we are rendering a cube, vertex could refer to the 8 vertexes of the entire shape (meaning One). Or, it could refer to the 24 vertexes of the 6 squares with 4 corners each (meaning Two).
As I understand it, if a cube is being rendered, the 8 corners of the cube have to be converted into the coordinate system of the viewer. But also there are texture coordinates that have to be calculated based on the individual textures associate with each face of the cube.
So if "vertex" is intended by meaning One, then why are textures being supplied to a shader which is a per face concept? Or if "vertexes" are being fed to the shader by meaning two, does that mean that the coordinate transforms and projections are all being done redundantly? Or is something else going on? These guides seem to have an allergy to actually saying what is going on.
The page on Vertex Specification could be a bit more clear on this, but a vertex is just a single index in the set of vertex arrays as requested by a rendering operation.
That is, you render some number of vertices from your vertex arrays. You could be specifying these vertices as a range of indices from a given start index to an end index (glDrawArrays), or you could specify a set of indices in order to use (glDrawElements). Regardless of how you do it, you get one vertex for each datum specified by your rendering command. If you render 10 indices with indexed rendering, you get 10 vertices.
Each vertex is composed of data fetched from the active vertex arrays in the currently bound VAO. Given the index for that vertex, a value is fetched from each active array at that index. Each individual array feeds a vertex attribute, which is passed to the vertex shader.
A vertex shader operates on the attributes of a vertex (passed as in qualified variables).
The relationship between a "vertex" and your geometry's vertices is entirely up to you. Vertices usually include positions as part of their vertex attributes, but they usually also include other stuff. The only limitation is that the value fetched for each attribute of a particular vertex always uses the same vertex index.
How you live within those rules is up to you and your data.

How do I obtain the vertices of the current polygon inside a fragment shader?

I've got a shader to procedurally generate geometric shapes inside a quad. Essentially, you render a quad with this fragment shader active, and it calculates which fragments are on the border of the shape and discards everything else.
The problem is the dimensions of the quad. At the moment, I have to pass in the vertex data twice, once to the VBO and a second time as uniform variables to the shader, so it knows how big of a shape it's supposed to be creating.
Is there any way to only have to do this once, by having some way to get the coordinates of the top-left and bottom-right vertices of the current quad when I'm inside the fragment shader, so that I could simply give the vertex data to OpenGL once and have the shader calculate the largest shape that will fit inside the quad?
I think you probably want to use a geometry shader. Each vertex would consist of the position of a corner of the quad (a vector of 2-4 values) and the size of the quad (which could be a single value or upto 9 depending on how general you need the quad to be).
The geometry shader would generate the additional vertices for the quad and pass the size through to the fragment shader.
Depending on what exactly you're doing you may also be able to use point sprites and use the implicit coordinates that they have (gl_PointCoord). However, point sprites have a maximum size (which can be queried via GL_POINT_SIZE_RANGE and GL_POINT_SIZE_GRANULARITY).
You could pull the vertices yourself. You could create a Uniform Buffer or a Texture Buffer with the vertex data and just access this buffer in the fragment shader. In the vertex shader, in order to know what vertex to output you could just use the built-in variable gl_VertexID
I'd pass the top left and bottom right vertices of the quad as two extra input attributes for each vertex. The quads themselves get rendered as triangles.
In the vertex shader, declare two output attributes as flat (so they don't get interpolated) and copy the input attributes to these outputs.

Approach for writing a GLSL fragment shader with a solid color per triangle/face

I have vertex and triangle data which contains a color for each triangle (face), not for each vertex. i.e. A single vertex is shared by multiple faces, each face potentially a different color.
How should I approach this problem in GLSL to obtain a solid color assignment for each face being rendered? Calculating and assigning a "vertex color" buffer by averaging the colors of a vertex's neighboring polys is easy enough, but this of course produces a blurry result where the colors are interpolated in the fragment shader.
What I really need shouldn't be interpolated color values at all, I'll have about 40k triangles shaded with approx 15 possible solid colors once this is working as intended.
While you maybe could do this in high end GLSL, the right way to do solid shading is to make unique vertices for every triangle. This is a trivial loop. For every vertex, count how many triangles share it. That's how often you have to replicate it. Make sure your loop to do this is O(n). Then just set each vertex color or normal to that of the triangle. Again one straight loop. Do not bother to optimize for shared colors, it is not worth it.
Edit much later, because this is a popular answer:
To do flat per face shading you can interpolate the vertex position in world or view space. Then in the fragment shader compute ddx(dFdx) and ddy(dFdy) of this variable. Take the cross product of those two vectors and normalize it - you got a flat normal! No mesh changes or per vertex data needed at all.
OpenGL does not have "per-face" attributes. See:
How can I specify per-face colors when using indexed vertex arrays in OpenGL 3.x?
Here are a few possible options I see:
Ditch the index arrays and use separate vertices for each face like starmole suggested
Create an index array for each color used. Use materials instead of vertex colors and change the material after drawing the triangles from the index array for each color.
If the geometry allows it, you can make sure the last vertex specified by the index array has the correct vertex color for the face, and then use GL_FLAT shading, or have the fragment shader only use at the last vertex color.
In addition to the other answers, you could maybe employ the gl_PrimitiveID variable, that's an input to the fragment shader (don't know since which version) and is incremented implicitly for each triangle. You could then use this to lookup the color (either from a 40k buffer texture of colors or color indices into a 15 color color map, or just some direct computation from the primitive id). But don't ask me about the performance of this approach.

Using a different array for vertices and normals in glDrawElements (OpenGL/VBOs)

I'm currently programming a .obj loader in OpenGL. I store the vertex data in a VBO, then bind it using Vertex Attribs. Same for normals. Thing is, the normal data and vertex data aren't stored in the same order.
The indices I give to glDrawElements to render the mesh are used, I suppose, by OpenGL to get vertices in the vertex VBO and to get normals in the normals VBO.
Is there an opengl way, besides using glBegin/glVertex/glNormal/glEnd to tell glDrawElements to use an index for vertices and an other index for normals?
Thanks
There is no direct way to do this, although you could simulate it by indexing into a buffer texture (OpenGL 3.1 feature) inside a shader.
It is generally not advisable to do such a thing though. The OBJ format allows one normal to be referenced by several (in principle any number of) vertices at a time, so the usual thing to do is constructing a "complete" vertex including coordinates and normal and texcoords for each vertex (duplicating the respective data).
This ensures that
a) smooth shaded surfaces render correctly
b) hard edges render correctly
(the difference between the two being only several vertices sharing the same, identical normal)
You have to use the same index for position/normals/texture coords etc. It means that when loading the .obj, you must insert unique vertices and point your faces to them.
OpenGL treats a vertex as a single, long vector of
(position, normal, texcoord[0]…texcoord[n], attrib[0]…attrib[n])
and these long vectors are indexed. Your question falls into the same category like how to use shared vertices with multiple normals. And the canonical answer is, that those vertices are in fact not shared, because in the long term they are not identical.
So what you have to do is iterating over the index array of faces and construct the "long" vertices adding those into a (new) list with a uniquenes constraint; a (hash) map from the vertex → index serves this job. Something like this
next_uniq_index = 0
for f in faces:
for i in f.indices:
vpos = vertices[i.vertex]
norm = normals[i.normal]
texc = texcoords[i.texcoord]
vert = tuple(vpos, norm, texc)
key
if uniq_vertices.has_key(key):
uniq_faces_indices.append(uniq_vertices[key].index)
else:
uniq_vertices[key] = {vertex = key, index = next_uniq_index}
next_uniq_index = next_uniq_index + 1

Can I use a vertex shader to display a models normals?

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?
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...
You could approximate this by drawing the geometry twice. Once draw it as you normally would. The second time, draw the geometry as GL_POINTS, and attach a vertex shader which offsets each vertex position by the vertex normal.
This would result in your model having a set of points floating over the surface. Each point would show the direction of the normal from the vertex it corresponds to.
This isn't perfect, but might be sufficient, depending on what it is you're hoping to use it for.
UPDATE: AHA! And if you pass in a constant scaling factor to the vertex shader, and have your application interpolate that factor between 0 and 1 as time goes by, your points rendered by the vertex shader will animate over time, starting at the vertex they apply to, and then floating off in the direction of its normal.
It's probably possible to get more or less the right effect with a cleverly written vertex shader, but it'd be a lot of work. Since this is for debugging purposes anyway, it seems better to just draw a few lines; the performance hit will not be severe.