Using vertex colors and textures in OpenGL? - opengl

I am familiar with texture usage in OpenGL. I am also familiar with the coloring and interpolation of colors between vertices. Can the two be used in conjunction with one another? Does doing so tint the texture with the color supplied at each vertex? I am rendering an older game format which supplies both so I am trying to figure out if they both work in conjunction to create variations for the textures.
Cheers.

Yes you can do that. If you set the colour on a vertex to anything other than white, the texture that is applied will be filtered by the colour given. If different vertices on the same polygon have different colours, and there are textures, the colours will be interpolated exactly the same as for no textures.

Related

Efficiently draw polygons (one color per polygon) in OpenGL 3+

In an application I have to draw lots of disjoint polygons of variable lengths. Colours vary between polygons but all vertices in a single polygon will have the same colour. How can I draw them efficiently?
I started by drawing all polygons with the same colour. This was easy to do with glMultiDrawArrays and a colour uniform; for example (using GL_LINE_LOOP to keep things simple):
glUniform4f(shaderColourLocation, red, blue, green, alpha);
glMultiDrawArrays(GL_LINE_LOOP, pFirstIndices, pPolygonSizes, polygonCount);
This worked well with the data I have, but the only ways I can see to add per-polygon colours are:
break this down into multiple glDrawArrays calls, setting the colour each time (lots of extra API calls);
buffer per-vertex colour data (duplicates a lot of colour data);
buffer polygon indices and use a uniform array of colours (more complex, and still some redundant data).
Is there a better way to achieve per-polygon colours, while still using glMultiDrawArrays or something similar?
What you want to achieve (one color per polygon) is called flat shading.
You probably can do it width a shader by using the flat qualifier.
You also can take a look to glShadeModel parameter, by using GL_FLAT mode and smartly define the first vertex of your triangles you may avoid to duplicate data in your buffers.
You can find documentation in the OpenGl compatibility specs (p482 #507/953 ยง13.4).
Use instanced attributes.
Call
glVertexAttribDivisor(color_attrib_location, 1);
once when initializing your vertex arrays.
With this setting you will only need one copy of color value per point/line/polygon.
Also, you should use flat interpolation qualifier for this attribute in your shaders, but it's not necessary.

Draw multiple shapes in one vbo

I want to render multiple 3D cubes from one vbo. Each cube has a uniform color.
At this time, I create a vbo where each vertex has a color information.
Is it posible to upload only one color for a one shape (list of verticies)?
I'm also want to mix GL_TRIANGLES and GL_LINES in the glDrawElements-method of the same shader. Is it posible?
//Edit : I only have OpenGL 2.1. Later I want to build this project on Android.
//Edit 2:
I want to render a large count of cubes (up to 150.000). One cube has 24 verticies of geometry and color and 34 indices. Now my idea is to create some vbo's (maybe 50) and share out the cubes to the vbo's. I hope that this minimizes the overhead.
Drawing lots of cubes
Yes, if you want to draw a bunch of cubes, you can specify the color for each cube once.
Create a VBO containing the vertexes for one cube.
// cube = 36 vertexes with glDrawArrays(GL_TRIANGLES)
vbo1 = [v1] [v2] [v3] ... [v36]
Create another VBO with the view matrix and color for each cube, and use an attribute divisor of 1. (You can use the same vbo, but I would use a separate one.)
vbo2 = [cube 1 mat, color] [cube 2 mat, color] ... [cube N mat, color]
Call glDrawElementsInstanced() or glDrawArraysInstanced(). This will draw the cube over and over again.
Alternatively, you can use glUniform() for each cube, but this will limit the number of cubes you can draw. The above method will let you draw thousands, easily.
Mixing GL_TRIANGLES and GL_LINES
You will have to call glDraw????() once for each type of primitive. You can use the same shader for both times, if you like.
Regarding your questions :
Is it possible to upload only one color for one shape ?
Yes , you can use a uniform instead of a vertex attribute(ofc this means changes in more places). However, you will need to set the uniform for each shape, and have a different drawcall for each differently colored shape .
Is it possible to mix GL_TRIANGLES and GL_LINES in the glDrawElements ?
Yes and no. Yes , but you will need a new drawcall (which is obvious). You cannot do on the same drawcall some shapes with GL_TRIANGLES and some shapes with GL_LINES.
In pseudocode this will look like this :
draw shapes 1,2,10 from the vbo using color red and GL_TRIANGLES
draw shapes 3,4,6 from the vbo using color blue and GL_LINES
draw shapes 7,8,9 from the vb using color blue and GL_TRIANGLES
With OpenGL 2.1, I don't think there's a reasonable way of specifying the color only once per cube, and still draw everything in a single draw call.
The most direct approach is that, instead of having the color attribute in a VBO, you specify it directly before the draw call. Assuming that you're using generic vertex attributes, where you would currently have:
glEnableVertexAttribArray(colorLoc);
glVertexAttripPointer(colorLoc, ...);
you do this:
glDisableVertexAttribArray(colorLoc);
glVertexAttrib3f(colorLoc, r, g, b);
where glDisableVertexAttribArray() is only needed if the array was previously enabled for the location.
The big disadvantage is that you can only draw cubes with the same color in one draw call. In the extreme case, that's one draw call per cube. Of course if you have multiple cubes with the same color, you could still batch those into a single draw call.
You wonder whether this is more efficient than having a color for each vertex in the VBO? Impossible to say in general. You'll always get the same answer in cases like this: Try both, and benchmark. I'm skeptical that you will find it beneficial. In my experience, it's fairly rare for fetching vertex data to be a major performance bottleneck. So cutting out one attribute will likely no give you much of a gain. On the other hand, making many small draw calls absolutely can (and often will) hurt performance.
There is one option you can use that is sort of a hybrid. I'm not necessarily recommending it, but just in the interest of brainstorming. If you use a fairly limited number of colors, you can use a single scalar attribute in the VBO that encodes a "color index". Then in the vertex shader, you can use a texture lookup to translate the "color index" to the actual color.
The really good options are beyond OpenGL 2.1. #DietrichEpp nicely explained instanced rendering, which is an elegant solution for cases like this.
And no, you can not have lines and triangles in the same draw call. Even the most flexible draw calls in OpenGL 4.x, like glDrawElementsIndirect(), still take only one primitive type.

What is the best way to specify the colors of different squares while drawing a chess board?

What is the best way to specify the colors of different squares while drawing a chess board?
Suppose I want a 2 by 2 board with colors like this:
*-----*-----*
|black|white|
*-----*-----*
|white|black|
*-----*-----*
I can now have 9 vertices and draw the board with GL_QUADS primitive. As I understand filling a square with some color means specifying a color of each vertex with that color.
But filling every square with a different color means duplicating 5 vertices
*-----**----*
|black|white|
**-----**----**
|white|black|
*-----**----*
Is it the simplest way to do this? And is it actually allowed in OpenGL to have vertices with equal coordinates and different colors?
If you really want to draw a quad for each field, duplicating the vertices is the way to go. There are no problems with different vertices having the same coordinates. The GL's rasterization rules will make sure that there are a) no gaps at such shared edges and b) there is also no overdraw, so you will be fine.
However, you can also draw the whole field as one quad and use texturing. All you would need is a 2x2 sized texture with the black and white colors and can use the GL_NEAREST filtering mode so get a nice and sharp checkerboard pattern.
With that approach, you can also dynamically change the number of fields without changing the texture at all, just by using the GL_REPEAT mode and only changing the texcoords.
In modern shader based GL, you can also procedurally generate the checkerboard pattern directly in the fragment shader.

What is stereoscopic shader?

These days, I am making some shaders such that Phong, Gourard, even Toon Shader in GLSL.
I have a curious question, I want to make a stereoscopic shader which using 2 camera, and left camera takes red light and right camera takes cyan light can be implemented by using combined them in one camera, so It can be a stereoscopic shader. I think.
Do I think wrong or not? I want to implement in 3D object which consists of 2D primitives.
You'll probably need to render the scene twice, once for the left eye and once for the right eye. You can then blend the 2 together.
One way would be to render each eye into a different texture-backed FBO, and then combine those 2 textures into 1 either using a custom shader or even using additive blending, if you can render each eye with the correct colors to begin with. (If the left eye is truly only the red channel and the right is only the green and blue channels, an additive blend should do the right thing, I think.)
If you want to create an anaglyph imagage, using OpenGL lights to color the scene is stupid.
Either use the method descibed in the other answer, i.e. using FBOs to render the scene into textures, then combine the results in a shader, or by simply drawing them on two overlaid quads in glBlendFunc(GL_ONE, GL_ONE) mode with modulated colors. Or, in case of red-cyan anaglyph you can use glColorMask to select which color channels are going to be written to.

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.