Go to bottom

OpenGL transform feedback mistakes

category: code [glöplog]
I have a problem with the transform feedback in OpenGL. I try to write 3 cubes into an Transformfeedback buffer, but the result is wrong... Thats my code:

Code: struct VERTEX { float position[4]; float normal[3]; float id; }; int v_draw_Count = 3 * 12 * 3; //3 cubes * 12 triangles * 3 vert. per triangle GLsizeiptr bufferSize = myReturner.v_draw_Count*sizeof(VERTEX); GLuint tempVAO, tempFB; glGenBuffers(1, &tempFB); glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tempFB); glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bufferSize, NULL, GL_DYNAMIC_DRAW); glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tempFB); glEnable(GL_RASTERIZER_DISCARD); useProgram("roomX"); //a function from my lib. glBeginTransformFeedback(GL_TRIANGLES); drawObjectInstanced("cube& quot;, GL_TRIANGLES, 3); //also a function from my lib. glFlush(); glEndTransformFeedback(); glDisable(GL_RASTERIZER_DISCARD); glGenVertexArrays(1, &tempVAO); glBindVertexArray(tempVAO); glBindBuffer(GL_ARRAY_BUFFER, tempFB); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glEnable VertexAttribArray(2); glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(VERTEX), (const GLvoid *)offsetof(VERTEX, position)); glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(VERTEX), (const GLvoid *)offsetof(VERTEX, normal)); glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeof(VERTEX), (const GLvoid *)offsetof(VERTEX, id)); glBindVertexArray(0); glDeleteBuffers(1, &tempFB);

The output is the following:

when I change the stride in the glVertexAttribPointer lines to the following:
Code: glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 16, (const GLvoid *)offsetof(VERTEX, position)); //...

than at least the positions look right, but the normals and the ids are still wrong. And the 16 doesn't make any sense to me, because the number is the number of bytes, right? My question is, do I have a conceptional error in my code? Or are my values for stride and pointer or anything else wrong? Thanks in advance for your help :)
added on the 2015-04-16 12:30:03 by Micha Micha
1) You do not need the glFlush() call.
2) You haven't specifically mentioned which GL version and profile you are using, but I would suggest moving the glBindVertexArray() call before the draw call (assuming that's what the drawObjectInstanced() stufdf does).
3) Please show us the vertex shader source code. Especially the hard-coded VAA indices in the glVertexAttribPointer() calls are fishy.
4) Make sure the compiler has not inserted padding between members of the VERTEX structure.

We'll carry on from there..
added on the 2015-04-16 17:06:48 by kbi kbi
Oh, yeah, and also the glTransformFeedbackVaryings() call would be a nice-to-have here.
added on the 2015-04-16 17:07:59 by kbi kbi
Thanks for your reply.
1) Ok, cutted this out ;)
2) I'm using OpenGL version 4.5. The drawObjectInstanced-method in my library binds the vertex array calls the right draw-function (glDrawElementsInstanced or glDrawArraysInstanced, based on the Object).

3) ok, here is the "room"-shader:
Code: #version 410 precision highp float; layout (location = 0) in vec4 vertexs; layout (location = 1) in vec3 normals; layout (location = 0) out vec4 rVertex; layout (location = 1) out vec3 rNormal; layout (location = 2) out float rID; void main(void) { rVertex = vertexs; rVertex.xyz = rVertex.xyz * vec3(0.25) + vec3((gl_InstanceID-1)*0.2); rNormal = normals; rID = gl_InstanceID; }

4) How do I do that? I use Visual Studio 2013... Didn't know, it can do that :D

and the glTransformFeedbackVaryings() call:

Code: std::vector<const char*> shdFeedbacks; shdFeedbacks.push_back("rVertex"); shdFeedbacks.push_b ack("rNormal"); shdFeedbacks.push_back("rID"); //... glTra nsformFeedbackVaryings(tempProgram, 3, shdFeedbacks.data(), GL_INTERLEAVED_ATTRIBS);

I had to fake the last code a little bit, because it does that automatically. But with this shader, it would look like this. And the compiling of the shader doesn't throw any error...
added on the 2015-04-16 20:30:22 by Micha Micha
void glVertexAttribPointer( GLuint index,
GLint size,
GLenum type,
GLboolean normalized,
GLsizei stride,
const GLvoid * pointer);

Reads to me as if you are doing it wrong... Please try this and tell me if it works:
#define sizeofm(type, member) sizeof(((type *)0)->member)

glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeofm(VERTEX, position), (const GLvoid *)offsetof(VERTEX, position));
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeofm(VERTEX, normal), (const GLvoid *)offsetof(VERTEX, normal));
glVertexAttribPointer(2, 1, GL_FLOAT, GL_FALSE, sizeofm(VERTEX, id), (const GLvoid *)offsetof(VERTEX, id));

Then 16 was correct for being size of position (float[4]) :)
added on the 2015-04-16 21:52:58 by Danzig Danzig
No, my c++ code was completetly correct, the shader was just wrong. I was wrong in thinking, that the gltransformfeedbackvaryings call would be enough for OpenGL, to connect the output of the shader to the Buffer. I'll write an answer to this problem in a moment.
But first to your suggestion: I think, when I'm using buffers with interleaved Attributes, the parameter stride should be the difference from one element of this attribute to the next element of this attribute. Which is for all attributes the same. The pointer is in this case the pointer to the first element of this attribute, which is the same as the "logical" stride...

But it works, and the shader was wrong. I'll post the complete shader code in a second...
added on the 2015-04-16 22:02:06 by Micha Micha
Code: #version 440 precision highp float; layout (location = 0) in vec4 vertexs; layout (location = 1) in vec3 normals; layout (xfb_buffer = 0, xfb_stride = 32) out; out data { layout (xfb_buffer = 0, xfb_offset = 0) vec4 rVertex; layout (xfb_buffer = 0, xfb_offset = 16) vec3 rNormal; layout (xfb_buffer = 0, xfb_offset = 28) float rID; } OUT; void main(void) { OUT.rVertex = vertexs; OUT.rVertex.xyz = OUT.rVertex.xyz * vec3(0.25) + vec3((gl_InstanceID-1)*0.2); OUT.rNormal = normals; OUT.rID = gl_InstanceID; }

Yes, I need version 440, if anybody has an solution for an smaller version, you are welcome to post :)
Here is the result:
added on the 2015-04-16 22:05:43 by Micha Micha
If, at one point, another newbie comes to this post, here are two good readings:

https://www.opengl.org/wiki/Transform_Feedback For the layout-params in GLSL
https://www.opengl.org/sdk/docs/man/html/glVertexAttribPointer.xhtml manpage for glVertexAttribPointer
And thanks for your help. Even if the error was in another direction, it helped much!
added on the 2015-04-16 22:16:51 by Micha Micha
xfb_buffer, xfb_offset, or xfb_stride layout qualifiers require GLSL4.4 or later.
If you remove xfb_* layout qualifiers from your shader and use glTransformFeedbackVaryings, your code might work in OpenGL3.

Tips from
OpenGL 4.5 Core Profile Specification Output Variables
When no xfb_buffer, xfb_offset, or xfb_stride layout qualifiers are
specified, the set of variables to record is specified with the command
void TransformFeedbackVaryings( uint program,
sizei count, const char * const *varyings,
enum bufferMode );

The state set by TransformFeedbackVaryings or using transform feedback
layout qualifiers has no effect on the execution of the program until program is
subsequently linked. When LinkProgram is called, the program is linked so that
the values of the specified outputs for the vertices of each primitive generated by
the GL are written to one or more buffer objects.

If the shader used to record output variables for transform feedback varyings
uses the xfb_buffer, xfb_offset, or xfb_stride layout qualifiers, the values
specified by TransformFeedbackVaryings are ignored, and the set of variables
captured for transform feedback is instead derived from the specified layout
added on the 2015-04-17 09:24:24 by tomohiro tomohiro
Ok, but that would be like my first attempt, and there was still an error in that...
added on the 2015-04-18 09:06:31 by Micha Micha


Go to top