I am trying to use one VBO to draw polygons separated from each other. When i draw the polygons, OpenGL cannot know where to start a new polygon and draws the polygons united.
How can i put a break point on VBO (or IBO) to tell OpenGL to start a fresh polygon.
Sorry it seems a newbie question, i searched for questions and tutorials but couldn't find the answer.
Thank you for your comments:)
I am trying to create a dxf viewer. Dxf files has polygons with solid hatch so i thought that it would be faster to use GL_POLYON rather than tessellation (i might have been wrong here).
My drawing function looks at each object and makes a draw call for every primitive in file. It looks that this type of approach is slow. So i decided to use one vertex array and one buffer for every uniqe type.
For lines, there is no need to know the endings since every line must have 2 vertices. But polygons may have different number of vertices and i should tell opengl where a new polygon begins.
void draw_scene(/*function variables*/){
Shader::shader_use();
glEnableClientState(GL_VERTEX_ARRAY);
unsigned long int i;
unsigned long int count = objects.size();
for(i = 0; i < objects.size(); i++){
glBindVertexArray(objects[i]->vao);
glDrawArrays(objects[i]->primitive_type, 0, objects[i]->vertice_count);
glBindVertexArray(0);
}
glDisableClientState(GL_VERTEX_ARRAY);
Shader::shader_close();
}
The above code hasn't been optimised yet. I want to draw the objects with same primitive type in one call. Thought that if could put them in one vertex buffer then i would be able to draw them in one call. So there will be one VAO for each type (points, lines etc).
In fact i don't know if there might be a better solution. Because even if i can put those in one buffer, then it would be hard to modify primitive vertices since they all would have been put in one array. Modifying one vertice would cause all vertices of same type to be re-read.
I also searched to bind multiple vao's at once to not to make too many draw calls. But i couldn't find a method.
Thank you very much for your help:)
Part of this was already covered in the comments.
Replacement of GL_POLYGON
The GL_POLYGON primitive type is deprecated, and not available in the OpenGL Core Profile. Fortunately it can easily be replace with GL_TRIANGLE_FAN. GL_TRIANGLE_FAN uses the same vertex order, so you can directly replace GL_POLYGON with GL_TRIANGLE_FAN, without changing anything else.
Only convex polygons can directly be drawn with GL_TRIANGLE_FAN without using any more elaborate triangulation. But the same was true for GL_POLYGON, so that's not a new restriction.
Drawing multiple polygons with a single draw call
There are a couple of approaches:
You can use glMultiDrawArrays(). Where glDrawArrays() takes one start index and one size, glMultiDrawArrays() takes an array of each. So it can be used to replace an arbitrary number of glDrawArrays() calls with a single call.
You can use primitive restart. The downside of this is that you need an index array, which may not have been necessary otherwise. Apart from that, it's straightforward. You enable it with:
glPrimitiveRestartIndex(0xffff);
glEnable(GL_PRIMITIVE_RESTART);
You can use any index you want as the restart index, but it's common policy to use the maximum possible index, which is 0xffff if you use indices of type GL_UNSIGNED_SHORT. If you use at least OpenGL 4.3, or OpenGL ES 3.0, you can also replace the above with:
glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
Then you set up an index array where you insert a 0xffff value at every position you want to start a new polygon, and bind the index array as usual. Then you can draw all the polygons with a single glDrawElements() call.
Related
Is the only solution grouping vertices into separate glDrawElements(GL_TRIANGLES, ...) and glDrawElements(GL_QUADS, ...) draw calls or is there a way of sending data describing no of polygon sides into geometry shader and sorting out type of polygon inside geometry shader?
https://i.stack.imgur.com/4Ee4e.jpg
What you see as my output console is output of my mesh structure. I have:
vector <float> vert_data;
unsigned int faces_no;
vector <unsigned int> indices_on_face;
vector <unsigned int> indices;
First is basicly exactly what is send to open-gl buffer: coordinates, normals, colors etc. Second one says how many faces are described in this data. Third says number of verticles that are in the polygon. It goes in order. Forth one are indices(glBufferData(GL_ELEMENT_ARRAY_BUFFER, ...)). So basicly I am looking for a way to send third one into geometry shader.
I know it is possible to order faces types using flag while importing from assimp but that would loose the faces order. And still wouldnt let me draw everything with single draw call, so I would have to create bunch of draw functions for every type of polygon:(
Maybe there would be possible something like: first change every indices_on_face[i] by adding all previous ones to it. Set first verticle number that is drawn inside geometry shader during draw call. Inside geometry shader compare current number of verticle with indices_on_face[i] that would tell when to generate polygon out of vertices. Does gl_VertexID hold number dependent from count of passed vertex, independent from indices?
How can I formulate a draw call that will fit it?
No, there is no way to do what you want. A primitive includes the count of vertices for each base primitive, and that doesn't get to change within a rendering command.
Also, a geometry shader would almost certainly slow down your rendering rather than speed it up, particularly compared to the standard solution: just send triangles. Break up any non-triangular polygons into triangles, so you can just send them all in a single draw call. I mean, the hardware is going to do that for you regardless, so you may as well do it yourself.
Most mesh exporters will have an option to do this for you. And in those cases where they don't, Open Asset Importer can do it for you at load time by passing the aiProcess_Triangulate flag to your loading function.
I have a vertex buffer of points which are to be the center of each circle (triangle fan). how do I take these, lets say draw 10 triangles around this point, then move onto the next point? I haven't been able to find any example code.
You have to glEnd() then glBegin() if you're using the old pipeline.
If you're issuing draw calls, you can use the primitive restart function, where an index can be designated as beginning a new primitive. All credit to datenwolf for pointing that out, I've clearly blanked it from my memory.
Personally however I still think that you're better off just using indexed triangles, and then you can re-use whatever vertices you want, whenever you want. It's simpler and the driver/hardware will thank you for it.
(in other words, don't use GL_TRIANGLE_FAN - just use GL_TRIANGLES. It's all the hardware draws anyway).
You can do this using primitive restart index. You set a special index value (usually the largest number representable by the type used for indexing). Then whenever this index is encountered in the index buffer a new primitive is started, as if multiple calls to glDraw… had been issued.
http://www.opengl.org/sdk/docs/man3/xhtml/glPrimitiveRestartIndex.xml
I'm new to graphics programming, and need to add on a rendering backend for a demo we're creating. I'm hoping you guys can point me in the right direction.
Short version: Is there any way to send OpenGL an array of data for distinct elements, without having to issue a draw command for each element distinctly?
Long version: We have a CUDA program (will eventually be OpenCL) which calculates a bunch of data for a bunch of objects for us. We then need to render these objects using, e.g., OpenGL.
The CUDA kernel can generate our vertices, and using OpenGL interop, it can shove these in an OpenGL VBO and not have to transfer the data back to host device memory. But the problem is we have a bunch (upwards of a million is our goal) distinct objects. It seems like our best bet here is allocating one VBO and putting every object's vertices into it. Then we can call glDrawArrays with offsets and lengths of each element inside that VBO.
However, each object may have a variable number of vertices (though the total vertices in the scene can be bounded.) I'd like to avoid having to transfer a list of start indices and lengths from CUDA -> CPU every frame, especially given that these draw commands are going right back to the GPU.
Is there any way to pack a buffer with data such that we can issue only one call to OpenGL to render the buffer, and it can render a number of distinct elements from that buffer?
(Hopefully I've also given enough info to avoid a XY problem here.)
One way would be to get away from understanding these as individual objects and making them a single large object drawn with a single draw call. The question is, what data is it that distinguishes the objects from each other, meaning what is it you change between the individual calls to glDrawArrays/glDrawElements?
If it is something simple, like a color, it would probably be easier to supply this an additional per-vertex attribute. This way you can render all objects as one single large object using a single draw call with the indiviudal sub-objects (which really only exist conceptually now) colored correctly. The memory cost of the additional attribute may be well worth it.
If it is something a little more complex (like a texture), you may still be able to index it using an additional per-vertex attribute, being either an index into a texture array (as texture arrays should be supported on CUDA/OpenCL-able hardware) or a texture coordinate into a particular subregion of a single large texture (a so-called texture atlas).
But if the difference between those objects is something more complex, as a different shader or something, you may really need to render individual objects and make individual draw calls. But you still don't need to neccessarily make a round-trip to the CPU. With the use of the ARB_draw_indirect extension (which is core since GL 4.0, I think, but may be supported on GL 3 hardware (and thus CUDA/CL-hardware), don't know) you can source the arguments to a glDrawArrays/glDrawElements call from an additional buffer (into which you can write with CUDA/CL like any other GL buffer). So you can assemble the offset-length-information of each individual object on the GPU and store them in a single buffer. Then you do your glDrawArraysIndirect loop offsetting into this single draw-indirect-buffer (with the offset between the individual objects now being constant).
But if the only reason for issuing multiple draw calls is that you want to render the objects as single GL_TRIANGLE_STRIPs or GL_TRIANGLE_FANs (or, god beware, GL_POLYGONs), you may want to reconsider just using a bunch of GL_TRIANGLES so that you can render all objects in a single draw call. The (maybe) time and memory savings from using triangle strips are likely to be outweight by the overhead of multiple draw calls, especially when rendering many small triangle strips. If you really want to use strips or fans, you may want to introduce degenerate triangles (by repeating vertices) to seprate them from each other, even when drawn with a single draw call. Or you may look into the glPrimitiveRestartIndex function introduced with GL 3.1.
Probably not optimal, but you could make a single glDrawArray on your whole buffer...
If you use GL_TRIANGLES, you can fill your buffer with zeroes, and write only the needed vertices in your kernel. This way "empty" regions of your buffer will be drawn as 0-area polygons ( = degenerate polygons -> not drawn at all )
If you use GL_TRIANGLE_STRIP, you can do the same, but you'll have to duplicate your first vertex in order to make a fake triangle between (0,0,0) and your mesh.
This can seem overkill, but :
- You'll have to be able to handle as many vertices anyway
- degenerate triangles use no fillrate, so they are almost free (the vertex shader is still computed, though)
A probably better solution would be to use glDrawElements instead : In you kernel, you also generate an index list for your whole buffer, which will be able to completely skip regions of your buffer.
I got code working which uses a VBO and an IBO: as I parse my geometry I build vertex and index arrays for triangles and then call glDrawElements with GL_TRIANGLES.
I read about being able to signal primitive restart in the index buffer, here, about halfway down the page. This is good, but I'm wondering if it's possible to forego the index buffer entirely, and just signal a primitive restart by sending in a specific vertex value (like have the first attribute zero value be infinity)?
Then I'd only need to send one buffer to the GPU before I draw with GL_TRIANGLE_FAN for instance to draw a set of convex polygons.
If you don't want to use index buffer then you can use glDrawArrays. It will render primitive from just the vertex buffer. Combine that with instancing and you'll be able to draw multiple triangle fans without index buffer.
But for performance reasons if your mesh triangles share vertices you should be using index buffer.
As clearly stated on that page:
It is technically legal to use this with non-indexed rendering. You should not do this, as it will not give you a useful result.
Primitive restart is for indexed rendering. There is no way to restart a primitive based on the value of a vertex attribute.
Basically what I'd like to do is make textured NGONS. I also want to use a tesselator (GLU) to make concave and multicontour objects.
I was wondering how the texture comes into play though. I think that the tesselator will return verticies so I will add these to my array, that's fine. But my vertex array will contain more than one polygon object so then how can I tell it when to bind the texture like in immediate mode? Right now I feel stuck with one call to bind.
How can this be done?
Thanks
If you're going to use glDrawArrays or glDrawElements, you'll have to draw your vertices in pieces, one piece per texture. The same texture is used for the entire call. (These calls are like a potentially more efficient version of submitting the same data by hand within glBegin and glEnd, and you can't change texture inside a glBegin...glEnd block, either.)
You could alternatively stick with glBegin and glEnd, and use glArrayElement to submit vertices whose attributes are taken out of the vertex arrays.