OpenGL glColorPointer repeat colors? - opengl

Imagine that you've got one of these guys:
(source: codesampler.com)
Aka GL_TRIANGLE_STRIP. If you wanna color it using different colors, you could use:
glColorPointer(4, GL_UNSIGNED_BYTE, 0, colorArray);
glEnableClientState(GL_COLOR_ARRAY);
Where each "item" in the color array matches a vertex point in the strip. But what if the colors just alternate between two different colors? Feels unnecessary to define a color for each vertex, if there's only two "real" different colors. So my question is if it's possible to define a colorArray with just two colors in it, and somehow make opengl alternate between those two when it's looping over the vertex array.
And yeah I'm a complete noob at opengl so maybe this is a stupid question...

You can do this by using OpenGL Color Index Mode. However, be aware that, in my experience, this actually is slower on most modern graphics card than just specifying each vertex color.
In color index mode, you send a separate color array, then each vertex specifies an index into the array, instead of a full rgb/rgba. It's more memory efficient, but not as optimized in most hardware drivers.

You could use a vertex shader to do this by sending in a boolean flag for each vertex describing what color to be. Really the simplest/fastest thing is probably just to submit the color for each vertex.
If opengl had the ability to have multiple vertex streams and indices that might work (but also would probably not be worth it).

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.

GLSL Shaders: blending, primitive-specific behavior, and discarding a vertex

Criteria: I’m using OpenGL with shaders (GLSL) and trying to stay with modern techniques (e.g., trying to stay away from deprecated concepts).
My questions, in a very general sense--see below for more detail—are as follows:
Do shaders allow you to do custom blending that help eliminate z-order transparency issues found when using GL_BLEND?
Is there a way for a shader to know what type of primitive is being drawn without “manually” passing it some sort of flag?
Is there a way for a shader to “ignore” or “discard” a vertex (especially when drawing points)?
Background: My application draws points connected with lines in an ortho projection (vertices have varying depth in the projection). I’ve only recently started using shaders in the project (trying to get away from deprecated concepts). I understand that standard blending has ordering issues with alpha testing and depth testing: basically, if a “translucent” pixel at a higher z level is drawn first (thus blending with whatever colors were already drawn to that pixel at a lower z level), and an opaque object is then drawn at that pixel but at a lower z level, depth testing prevents changing the pixel that was already drawn for the “higher” z level, thus causing blending issues. To overcome this, you need to draw opaque items first, then translucent items in ascending z order. My gut feeling is that shaders wouldn’t provide an (efficient) way to change this behavior—am I wrong?
Further, for speed and convenience, I pass information for each vertex (along with a couple of uniform variables) to the shaders and they use the information to find a subset of the vertices that need special attention. Without doing a similar set of logic in the app itself (and slowing things down) I can’t know a priori what subset of vericies that is. Thus I send all vertices to the shader. However, when I draw “points” I’d like the shader to ignore all the vertices that aren’t in the subset it determines. I think I can get the effect by setting alpha to zero and using an alpha function in the GL context that will prevent drawing anything with alpha less than, say, 0.01. However, is there a better or more “correct” glsl way for a shader to say “just ignore this vertex”?
Do shaders allow you to do custom blending that help eliminate z-order transparency issues found when using GL_BLEND?
Sort of. If you have access to GL 4.x-class hardware (Radeon HD 5xxx or better, or GeForce 4xx or better), then you can perform order-independent transparency. Earlier versions have techniques like depth peeling, but they're quite expensive.
The GL 4.x-class version uses essentially a series of "linked lists" of transparent samples, which you do a full-screen pass to resolve into the final sample color. It's not free of course, but it isn't as expensive as other OIT methods. How expensive it would be for your case is uncertain; it is proportional to how many overlapping pixels you have.
You still have to draw opaque stuff first, and you have to draw transparent stuff using special shader code.
Is there a way for a shader to know what type of primitive is being drawn without “manually” passing it some sort of flag?
No.
Is there a way for a shader to “ignore” or “discard” a vertex (especially when drawing points)?
No in general, but yes for points. A Geometry shader can conditionally emit vertices, thus allowing you to discard any vertex for arbitrary reasons.
Discarding a vertex in non-point primitives is possible, but it will also affect the interpretation of that primitive. The reason it's simple for points is because a vertex is a primitive, while a vertex in a triangle isn't a whole primitive. You can discard lines, but discarding a vertex within a line is... of dubious value.
That being said, your explanation for why you want to do this is of dubious merit. You want to update vertex data with essentially a boolean value that says "do stuff with me" or not to. That means that, every frame, you have to modify your data to say which points should be rendered and which shouldn't.
The simplest and most efficient way to do this is to simply not render with them. That is, arrange your data so that the only thing on the GPU are the points you want to render. Thus, there's no need to do anything special at all. If you're going to be constantly updating your vertex data, then you're already condemned to dealing with streaming vertex data. So you may as well stream it in a way that makes rendering efficient.

GLSL: How to access nearby vertex colors? (bilinear interpolation without uniforms)

I'm trying to make bilinear color interpolation on a quad, i succeeded with the help of my previous question on here, but it has bad performance because its requires me to repeat glBegin() and glEnd() and 4 times glUniform() before glBegin().
The question is: is it anyhow possible to apply bilinear color interpolation on a quad like this:
glBegin(GL_QUADS);
glColor4f(...); glVertexAttrib2f(uv, 0, 0); glTexCoord2f(...); glVertex3f(...);
glColor4f(...); glVertexAttrib2f(uv, 1, 0); glTexCoord2f(...); glVertex3f(...);
glColor4f(...); glVertexAttrib2f(uv, 1, 1); glTexCoord2f(...); glVertex3f(...);
glColor4f(...); glVertexAttrib2f(uv, 0, 1); glTexCoord2f(...); glVertex3f(...);
... // here can be any amount of quads without repeating glBegin()/glEnd()
glEnd();
To do this, i think i should somehow access the nearby vertex colors, but how? Or is there any other solutions for this?
I need this to work this way so i can easily switch between different interpolation shaders.
Any other solution that works with one glBegin() command is good too, but sending all corner colors per vertex isnt acceptable, unless thats the only solution here?
Edit: The example code uses immediate mode for clarity only. Even with vertex arrays/buffers the problem would be the same: i would have to split the rendering calls into 4 vertices chunks, which causes the whole speed drop here!
Long story short: You cannot do this with a vertex shader.
The interpolator (or rasterizer) is one of the components of the graphics pipeline that is not programmable. Given how the graphics pipe works, neither a vertex shader nor a fragment shader are allowed access to anything but their vertex (or fragment, respectively), for reasons of speed, simplicity, and parallelism.
The workaround is to use a texture lookup, which has already been noted in previous answers.
In newer versions of OpenGL (3.0 and up I believe?) there is now the concept of a geometry shader. Geometry shaders are more complicated to implement than the relatively simple vertex and fragment shaders, but geometry shaders are given topological information. That is, they execute on a primitive (triangle, line, quad, etc) rather than a single point. With that information, they could create additional geometry in order to resolve your alternate color interpolation method.
However, that's far more complicated than necessary. I'd stick with a 4 texel texture map and implement your logic in your fragment lookup.
Under the hood, OpenGL (and all the hardware that it drives) will do everything as triangles, so if you choose to blend colors via vertex interpolation, it will be triangular interpolation because the hardware doesn't work any other way.
If you want "quad" interpolation, you should put your colors into a texture, because in hardware a texture is always "quad" shaped.
If you really think it's the number of draws that cause your performance drop, you can try to use Instancing (Using glDrawArrayInstanced+glVertexAttribDivisor), available in GL 3.1 core.
An alternative might be point sprites, depending on your usage model (mostly, maximum size of your quads, and are they always perpendicular to the view). That's available since GL 2.0 core.
Linear interpolation with colours specified per vertex can be set up efficiently using glColorPointer. Similarly you should use glTexCoordPointer/glVertexAttribPointer/glVertexPointer to replace all those individual per-vertex calls with a single call referencing the data in an array. Then render all your quads with a single (or at most a handful of) glDrawArrays or glDrawElements call. You'll see a huge improvement from this even without VBOs (which just change where the arrays are stored).
You mention you want to change shaders (between ShaderA and ShaderB say) on a quad by quad basis. You should either:
Arrange things so you can batch all of the ShaderA quads together and all the ShaderB quads together and render all of each together with a single call. Changing shader is generally quite expensive so you want to minimise the number of changes.
or
Implement all the different shader logic you want in a single "unified" shader, but selected by another vertex attribute which selects between the different codepaths. Whether this is anywhere near as efficient as the batching approach (which is preferable) depends on whether or not each "tile" of SIMD shaders tends to have to run a mixture of paths or just one.

What color does a fragment get if there are two vertices at the very same position with two different colors?

I have a question concerning the OpenGL rendering pipeline.
I have recently been reading theory about the GLSL's Geometry Shader. I think I do understand the basics of how to emit new geometry and assign colors to the new vertices. I am, however, not sure what color a fragment would get if one of those new vertices would have the very same position as one coming in from the Vertex shader.
Consider this example:
I far as I understand it, I am able to handle a single vertex with the Vertex shader. I make some transformation and store the position in glPosition. It is furthermore possible to assign a color to that vertex, e.g. by storing it to glFrontColor. As an example, I give it the color red. If all channels have 32 bits, that would be 0xFFFFFFFF'00000000'00000000'00000000, right?.
Next, Geometry shader is involved. I want my geometry shader to emit some additional vertices. At least one of them is at the very same position as the original vertex coming in from the Vertex shader. However, it is assigned another color, e.g. green. That would be 0x00000000'FFFFFFFF'00000000'00000000, right?
Sooner or later, after every vertex has been dealt, the rasterization takes place. As I understand, both vertices are rasterized and will therefore become the very same fragment. So, there we go. What color will that particular fragment get? Is there some kind of automatic blending and the fragment becomes yellow? Or is red or rather green?
This question might be silly. But I am simply not clear on that and would appreciate if somebody could clarify that for me.
If there is no blending (which I assume), how could I possibly create a blending effect?
Assuming you're rendering points (which seems to be what you're describing), the two vertices with the different colors will result in two fragments (one for each vertex) at the same location. What final color will be written to the output depends on the Z values for each, the blending function set and the order in which they are processed (which is effectively random -- you can't count on either order unless you do some extra sync stuff, so you need to set your blend func/Z-culling such that it doesn't matter).
I think they will be Z-Fighting, if they have the exact same values for x y and z.
About blending:
This is separate from the programmable pipeline, so you don't have to do most of the work in the shaders for it.
First enable blending with glEnable(GL_BLEND),
then specify your desired blending function with glBlendFunc, most commonly glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA).
Now the vertices only need an alpha value set at gl_FragColor.a and their color will blend.