Transform feedback without a framebuffer? - opengl

I'm interested in using a vertex shader to process a buffer without producing any rendered output. Here's the relevant snippet:
glUseProgram(program);
GLuint tfOutputBuffer;
glGenBuffers(1, &tfOutputBuffer);
glBindBuffer(GL_ARRAY_BUFFER, tfOutputBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(double)*4*3, NULL, GL_STATIC_READ);
glEnable(GL_RASTERIZER_DISCARD_EXT);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfOutputBuffer);
glBeginTransformFeedbackEXT(GL_TRIANGLES);
glBindBuffer(GL_ARRAY_BUFFER, positionBuffer);
glEnableVertexAttribArray(positionAttribute);
glVertexAttribPointer(positionAttribute, 4, GL_FLOAT, GL_FALSE, sizeof(double)*4, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementBuffer);
glDrawElements(GL_TRIANGLES, 1, GL_UNSIGNED_INT, 0);
This works fine up until the glDrawElements() call, which results in GL_INVALID_FRAMEBUFFER_OPERATION. And glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); returns GL_FRAMEBUFFER_UNDEFINED.
I presume this is because my GL context does not have a default framebuffer, and I have not bound another FBO. But, since I don't care about the rendered output and I've enabled GL_RASTERIZER_DISCARD_EXT, I thought a framebuffer shouldn't be necessary.
So, is there a way to use transform feedback without a framebuffer, or do I need to generate and bind a framebuffer even though I don't care about its contents?

This is actually perfectly valid behavior, as-per the specification.
OpenGL 4.4 Core Specification - 9.4.4 Effects of Framebuffer Completeness on Framebuffer Operations
A GL_INVALID_FRAMEBUFFER_OPERATION error is generated by attempts to render to or read from a framebuffer which is not framebuffer complete. This error is generated regardless of whether fragments are actually read from or written to the framebuffer. For example, it is generated when a rendering command is called and the framebuffer is incomplete, even if GL_RASTERIZER_DISCARD is enabled.
What you need to do to work around this is create an FBO with a 1 pixel color attachment and bind that. You must have a complete FBO bound or you get GL_INVALID_FRAMEBUFFER_OPERATION and one of the rules for completeness is that at least 1 complete image is attached.
OpenGL 4.3 actually allows you to skirt around this issue by defining an FBO with no attachments of any sort (see: GL_ARB_framebuffer_no_attachments). However, because you are using the EXT form of FBOs and Transform Feedback, I doubt you have a 4.3 implementation.

Related

Is a compiled shader compulsory in OpenGl 4?

I have an OpenGL 4.1 code using VAO and VBOs. Generation of buffer and array objects happens properly, however as soon as I want to draw my vertices, I get an INVALID OPERATION (code 1282) error. One of the possible explanations is that "the shader is not compiled".Hence my question: Is it a MUST to write & compile my own vertex and fragment shaders, or can I do without ?
As reference, my code:
Preparing:
glGenVertexArrays(1, vaoID); // Create new VAO
glBindVertexArray(vaoID);
glGenBuffers(1, vboID); // Create new VBO
glBindBuffer(GL_ARRAY_BUFFER, vboID); // Bind vbo1 as current vertex buffer
glBufferData(GL_ARRAY_BUFFER, sizeOfVertices, vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, floatsPerPosition, GL_FLOAT, GL_FALSE, 0, 0);
glGenBuffers(1, eboID);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, eboID);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeOfIndices, indices, GL_STATIC_DRAW);
// reset bindings for VAO, VBO and EBO
glBindVertexArray(0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
Rendering:
glBindVertexArray(vaoID); // No Error
glDrawArrays(GL_TRIANGLES, 0, 6); // Generates Error 1282
glBindVertexArray(0);
In a core OpenGL profile, since 3.2, the use of a program object is not optional.
However, the only shader stage that is manditory is the vertex shader. The use of a fragment shader is optional, but of course, it would only be useful for depth or stencil operations (since it would not generate fragment colors).
In a compatibility OpenGL profile, you can render using the fixed-function pipeline, but you cannot use user-defined vertex attributes. You have to use the fixed-function attributes, set up with glVertexPointer, glColorPointer, etc. Note that NVIDIA plays fast-and-loose with the spec in this regard, mapping user-defined attributes to fixed-function ones.
According to the OpenGL specification, a shader must always be used when rendering geometry. When you have no shader enabled, the result of the draw call is undefined.
However, from what I can tell this is a bit more murky in practice. At least most NVidia and Intel drivers seem to come with a kind of "default shader" enabled by default, which inhibits the undefined behaviour.
These shaders have pre-specified vertex attribute input indices (for instance, NVidia uses 0 for vertices, 4 for vertex colours, etc), and implement what you could consider a default pipeline.
Please note here that while these default shaders exist, their implementation can vary significantly between vendors, or might not exist at all for specific vendors or driver versions.
So you should therefore always use a shader when drawing geometry in OpenGL 4.

Is it necessary to bind all VBOs (and textures) each frame?

I'm following basic tutorial on OpenGL 3.0. What is not clear to me why/if I have to bind, enable and unbind/disable all vertex buffers and textures each frame.
To me it seems too much gl**** calls which I guess have some overhead. For example here you see each frame several blocks like:
// do this for each mesh in scene
// vertexes
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glVertexAttribPointer( 0, 3, GL_FLOAT,GL_FALSE,0,(void*)0);
// normals
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, normal_buffer );
glVertexAttribPointer( 1, 3, GL_FLOAT,GL_FALSE,0,(void*)0);
// UVs
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, uv_buffer );
glVertexAttribPointer( 2, 2, GL_FLOAT,GL_FALSE,0,(void*)0);
// ...
glDrawArrays(GL_TRIANGLES, 0, nVerts );
// ...
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
imagine you have not just one but 100 different meshes each with it's own VBOs for vertexes,normas,UVs. Should I really do this procedure each frame for each of them? Sure I can encapsulate that complexity into some function/objects, but I worry about overheads of this gl**** function calls.
Is it not possible some part of this machinery to move from per frame loop into scene setup ?
Also I read that VAO is a way how to pack corresponding VBOs for one object together. And that binding VAO automatically binds corresponding VBOs. So I was thinking that maybe one VAO for each mesh (not instance) is how it should be done - but according to this answer it does not seems so?
First things first: Your concerns about GL call overhead have been addressed with the introduction of Vertex Array Objects (see #Criss answer). However the real problem with your train of thought is, that you equate VBOs with geometry meshes, i.e. give each geometry its own VBO.
That's not how you should see and use VBOs. VBOs are chunks of memory and you can put the data of several objects into a single VBO; you don't have to draw the whole thing, you can limit draw calls to subsets of a VBO. And you can coalesce geometries with similar or even identical drawing setup and draw them all at once with a single draw call. Either by having the right vertex index list, or by use of instancing.
When it comes to the binding state of textures… well, yeah, that's a bit more annoying. You really have to do the whole binding dance when switching textures. That's why in general you sort geometry by texture/shader before drawing, so that the amount of texture switches is minimized.
The last 3 or 4 generations of GPUs (as of late 2016) do support bindless textures though, where you can access textures through a 64 bit handle (effectively the address of the relevant data structure in some address space) in the shader. However bindless textures did not yet make it into the core OpenGL standard and you have to use vendor extensions to make use of it.
Another interesting approach (popularized by Id Tech 4) is virtual textures. You can allocate sparsely populated texture objects that are huge in their addressable size, but only part of them actually populated with data. During program execution you determine which areas of the texture are required and swap in the required data on demand.
You should use vertex array object (generated by glGenVertexArrays). Thanks to it you don't have to perform those calls everytime. Vertex buffer object stores:
Calls to glEnableVertexAttribArray or glDisableVertexAttribArray.
Vertex attribute configurations via glVertexAttribPointer.
Vertex buffer objects associated with vertex attributes by calls to
glVertexAttribPointer.
Maybe this will be better tutorial.
So that you can generate vao object, then bind it, perform the calls and unbind. Now in drawing loop you just have to bind vao.
Example:
glUseProgram(shaderId);
glBindVertexArray(vaoId);
glDrawArrays(GL_TRIANGLES, 0, 3);
glBindVertexArray(0);
glUseProgram(0);

Rendering to TBO

I need to render to Buffer texture. Why TBO? TBO can be mapped easily as CUDA resource for graphic interop. It can also store byte sized data, which is what I need. I was trying to find related info in GL specs. Here it is stated that:
Buffer Textures work like 1D texture, only they have a single image,
identified by mipmap level​ 0.
But when I try to attach TBO to FBO I am always getting "Missing attachment" error when checking completeness, which leads me to a conclusion that GL_TEXTURE_BUFFER is not supported as FBO attachment.
Two questions:
Is it true?
Is the only alternative here to write to SSBO
More detailed info:
I am getting
GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
When I am trying to attach the TBO to the framebuffer.There is no point to attach the whole code here as it is both heavily abstracted API and belive me,I am pretty experienced in using OpenGL and framebuffers.Attaching a regular GL_TEXTURE_2D works great.
Here is the chunk of the TBO creation and the attachment stage:
GLuint tbo;
GLuint tboTex;
glGenBuffers(1, &tbo);
glBindBuffer(GL_TEXTURE_BUFFER, tbo);
glBufferData(GL_TEXTURE_BUFFER, viewportWidth * viewportHeight * 4, NULL, GL_DYNAMIC_DRAW);
glBindBuffer(GL_TEXTURE_BUFFER, 0);
glGenTextures(1, &tboTex);
glBindTexture(GL_TEXTURE_BUFFER, tboTex);
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA8, tbo);
glBindTexture(GL_TEXTURE_BUFFER, 0);
Then attach to FBO:
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tboTex, 0);
///also tried:
/// glFramebufferTexture1D
/// glFramebufferTexture2D
Buffer textures cannot be attached to FBOs:
GL_INVALID_OPERATION is generated by[sic] if texture is a buffer texture.
A good reminder for why you should always check your OpenGL errors.
Is the only alternative here to write to SSBO
If your goal is to use a rendering operation to write stuff to a buffer object, you could also use Image Load/Store operations with buffer textures. But if your hardware could handle that, then it should handle SSBOs too.
You could also try to use geometry shaders and transform feedback operations to write whatever you're trying to write.
However:
It can also store byte sized data
Images can store "byte sized data" as well. The image format GL_R8UI represents a single-channel, 8-bit unsigned integer.
That doesn't resolve any CUDA-interop issues, but rendering to bytes is very possible.

glDrawRangeElements of GL_TRIANGLE_STRIP not working properly (using glMapBuffer)

I am trying to render points from a VBO and a Element Buffer Object with glDrawRangeElements.
The VBO and EBO are instanciated like this:
glGenBuffers(1, &vertex_buffer);
glGenBuffers(1, &index_buffer);
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size, NULL, GL_STREAM_DRAW);
glVertexAttribPointer(0,3,GL_FLOAT, GL_FALSE, 0, (char*)(NULL));
glEnableVertexAttribArray(0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, index_buffer_size, NULL, GL_STREAM_DRAW);
as you can see they do not have any "static" data.
I use glMapBuffer to populate the buffers and then I render them with glDrawRangeElements.
Problem:
Concretly, what I want to do is to make a terrain with Continuous LOD.
The code I use and posted majorly comes from Ranger Mk2 by Andras Balogh.
My problem is this: when I want to render the triangle strip, there seems to be a point on the 3 points of a triangle which is somewhere where it should not be.
For example,
this is what I get in wireframe mode -> http://i.stack.imgur.com/lCPqR.jpg
and this is what I get in point mode (Note the column that stretches up which is the points that are not well placed) -> http://i.stack.imgur.com/CF04p.jpg
Before you ask me to go to the post named "Rendering with glDrawRangeElements() not working properly", I wanted to let you know that I already went there.
Code:
So here is the render process:
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(4, GL_FLOAT, 0, 0);
glEnableVertexAttribArray(0);
glDrawRangeElements(GL_TRIANGLE_STRIP, 0, va_index, ia_index, GL_UNSIGNED_INT, BUFFER_OFFSET(0));
glDisableClientState(GL_VERTEX_ARRAY);
and just before I do this (pre_render function):
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer);
vertex_array = (v4f*)(glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY));
index_array = (u32*)(glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY));
//[...] Populate the buffers
glUnmapBuffer(GL_ARRAY_BUFFER);
glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER);
PS: When I render the terrain like this:
glBegin(GL_TRIANGLE_STRIP);
printf("%u %u\n", va_index, ia_index);
for(u32 i = 0; i < va_index; ++i){
//if(i <= va_index)
glVertex4fv(&vertex_array[i].x);
}
glEnd();
strangely it works (part of the triangles are not rendered though but that is another problem).
So my question is how can I make glDrawRangeElements function properly?
If you need any more information please ask, I will be glad to answer.
Edit: I use Qt Creator as IDE, with Mingw 4.8 on Windows 7. My Graphic card supports Opengl 4.4 (from Nvidia).
Not sure if this is causing your problem, but I notice that you have a mixture of API calls for built-in vertex attributes and generic vertex attributes.
Calls like glVertexAttribPointer, glEnableVertexAttribArray and glDisableVertexAttribArray are used for generic vertex attributes.
Calls like glVertexPointer, glEnableClientState and glDisableClientState are used for built-in vertex attributes.
You need to decide which approach you want to use, and then use a consistent set of API calls for that approach. If you use the fixed rendering pipeline, you need to use the built-in attributes. If you write your own shaders with the compatibility profile, you can use either. If you use the core profile, you need to use generic vertex attributes.
This call also looks suspicious, since it specifies a size of 3, where the rest of your code suggests that you're using positions with 4 coordinates:
glVertexAttribPointer(0,3,GL_FLOAT, GL_FALSE, 0, (char*)(NULL));

glInterleavedArrays() generates GL_INVALID_FRAMEBUFFER_OPERATION

When I trying to use glInterleavedArrays() I always get "GL_INVALID_FRAMEBUFFER_OPERATION" error.
GLuint bufid;
glGenBuffers(1, &bufid);
glBindBuffer(GL_ARRAY_BUFFER, bufid);
glInterleavedArrays(GL_C4F_N3F_V3F, 0, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
What's wrong with this code?
Update
glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) and glCheckFramebufferStatus(GL_READ_FRAMEBUFFER ) both returns GL_FRAMEBUFFER_COMPLETE.
Are you sure this is because of the interleaved array? There are tons of reasons for invalid framebuffer operations. But this seems to be an unlikely cause.
Even if the framebuffer is complete it can still generate invalid operations, like enabling stencil without a stencil buffer.
You can replicate interleaved arrays with regular ones quite easily. Does the error persist?