Tessellation with Transform Feedback

Right now I want to generate a mesh with a tessellation shader and have that go into a different program/vertex/tessellation shader…

I got the mesh generating just fine with the tessellation shader, which outputs ‘quads’. I’m having issues with the transform feedback aspect though so I can’t even start the second pass yet…

The initialization looks like:


	//Transform feedback output buffer
	glGenBuffers(1, &TransformFeedbackBuffer);
	glBindBuffer(GL_ARRAY_BUFFER, TransformFeedbackBuffer);
	glBufferData(GL_ARRAY_BUFFER, 4096*3*4, 0, GL_STATIC_DRAW);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glBindBuffer(GL_ARRAY_BUFFER, 0);

	//transform feedback object
	glGenTransformFeedbacks(1, &TransformFeedbackObject);
	glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, TransformFeedbackObject);	
	glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, TransformFeedbackBuffer);
	glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);

And in the render loop:


		// enable / disable wireframe
		glPolygonMode( GL_FRONT_AND_BACK, wireframe ? GL_LINE : GL_FILL);printGLError();
		
		glEnable(GL_RASTERIZER_DISCARD);printGLError(); 
		//set up the program
		glUseProgram(program);printGLError();
				
		glBindBufferBase( GL_UNIFORM_BUFFER , 1, ubo);printGLError();
		glBufferData(GL_UNIFORM_BUFFER, sizeof(TessellationParams), &tessellationParameters, GL_STREAM_DRAW);printGLError();

		GLint numfeedbackwritten;

		glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, TransformFeedbackObject);printGLError();
		glBeginTransformFeedback(GL_TRIANGLES);printGLError();
		{
			glBindBuffer(GL_ARRAY_BUFFER, vbo);
			glEnableVertexAttribArray(0);
			glPatchParameteri( GL_PATCH_VERTICES, 1);

			//draw a single patch
			GLuint queryObject;
			glGenQueries(1, &queryObject);printGLError();

			glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, queryObject);printGLError();
				glDrawArrays( GL_PATCHES, 0, 1);printGLError();
			glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);printGLError();


			glGetQueryObjectiv(queryObject, GL_QUERY_RESULT, &numfeedbackwritten);
			printf("Tris drawn to feedback buffer: %d
", numfeedbackwritten);

			glDisableVertexAttribArray(0);
			glBindBuffer(GL_ARRAY_BUFFER, 0);
		}
		glEndTransformFeedback();printGLError();
		glDisable(GL_RASTERIZER_DISCARD);printGLError();

The printGLError() says Invalid Operation on the glDrawArrays call… Also, I’m not sure how to render it to the screen afterwards. I think this is right?


		glUseProgram(0);
		glBindBuffer(GL_ARRAY_BUFFER, TransformFeedbackBuffer);printGLError();
		glEnableVertexAttribArray(0);

		GLuint queryObject2;
		glGenQueries(1, &queryObject2);printGLError();

		glBeginQuery(GL_PRIMITIVES_GENERATED, queryObject2);
			glDrawArrays( GL_TRIANGLES, 0, numfeedbackwritten);printGLError();
		glEndQuery(GL_PRIMITIVES_GENERATED);

		glGetQueryObjectiv(queryObject2, GL_QUERY_RESULT, &numfeedbackwritten);
		printf("Tris drawn to display: %d
", numfeedbackwritten);

But it’s hard to tell since I’m getting no tris being drawn in either case. I think glDrawTransformFeedback should work too…

Is this setup even possible? The feedback says it only works on points, lines and tris, and the tess shader I want to have it as a quad input (but triangle output).

So after messing around with this a lot, I managed to get it working. There was a ton wrong, highlighted in bold below (I don’t know how to bold things that are in CODE tags). I ended up using a second set of passthrough shaders because it was easier to set what I wanted. Basically I was missing vertexAttribPointer calls that I thought were bound to the buffer before.

Initialization is modified:

//Transform feedback output buffer
glGenBuffers(1, &TransformFeedbackBuffer);
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, TransformFeedbackBuffer);
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 10000044, 0, GL_STATIC_DRAW);
glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, TransformFeedbackBuffer, 0, 10000044);
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);

Render is modified:

  //first pass, render vertices to transform feedback buffer
  glEnable(GL_RASTERIZER_DISCARD); 
  glUseProgram(program);
  		
  glBindBufferBase( GL_UNIFORM_BUFFER , 1, ubo); //uniforms
  glBufferData(GL_UNIFORM_BUFFER, sizeof(TessellationParams), &tessellationParameters, GL_STREAM_DRAW);

  glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, TransformFeedbackObject);
  glBeginTransformFeedback(GL_TRIANGLES);
  
  glBindBuffer(GL_ARRAY_BUFFER, vbo);
  glEnableVertexAttribArray(0);
  [b]glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);[/b]
  glPatchParameteri( GL_PATCH_VERTICES, 1);
  glDrawArrays( GL_PATCHES, 0, 1);
  				
  glDisableVertexAttribArray(0); //cleanup
  glBindBuffer(GL_ARRAY_BUFFER, 0);
  glEndTransformFeedback();
  glDisable(GL_RASTERIZER_DISCARD);
  [b]glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0);[/b]
  
  //second pass
  [b]glUseProgram(program2);[/b]
  glBindBuffer(GL_ARRAY_BUFFER, TransformFeedbackBuffer);
  glEnableVertexAttribArray(0);
  [b]glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);[/b]
  [b]glPatchParameteri(GL_PATCH_VERTICES, 3);[/b]
  [b]glDrawTransformFeedback(GL_PATCHES, TransformFeedbackObject)[/b];

Hi, I am working on tessellation with transform feedback these days too. But right now, I still can not get it working. In my code, I use tessellation shader to generate a sphere object from a single input vertex, this works fine. Then I want to obtain the vertices and normals of the sphere generated by the tessellation via transform feedback. Right now, all I get in the transform feedback buffer is the input vertex without tessellation. Do you have any idea, what is wrong? Thanks in advance. Sorry for my poor English. Here is my tessellation shader:
vertex shader:

layout(location=0) in vec4 vertex;
out vec4 vPosition;
void main() {   
	vPosition = vertex;
}

tessellation control shader:

#version 420
#extension GL_ARB_tessellation_shader : enable

layout( vertices=1) out;
in vec4 vPosition[];
out vec4 tcPosition[];
uniform float innerTessFactor;
uniform float outerTessFactor;


void main() {
   
    tcPosition[gl_InvocationID] = vPosition[gl_InvocationID];  

    gl_TessLevelOuter[0] = outerTessFactor;
    gl_TessLevelOuter[1] = outerTessFactor;
    gl_TessLevelOuter[2] = outerTessFactor;
    gl_TessLevelOuter[3] = outerTessFactor;

    gl_TessLevelInner[0] = innerTessFactor;
    gl_TessLevelInner[1] = innerTessFactor;
}

tessellation evaluation shader:

#version 420 compatibility
#extension GL_ARB_tessellation_shader : enable
#extension GL_ARB_shading_language_include : enable

layout(quads,fractional_odd_spacing,ccw) in;
uniform mat4 MVP;
uniform mat4 ModelView;
out vec3 normal;
out vec3 vertex;
out vec4 position;
in vec4 tcPosition[];

out gl_PerVertex {
    vec4  gl_Position;
};

void main() {

    position = tcPosition[0];
    
    position.y = cos(gl_TessCoord.x * 3.1415927);
    position.x = sin(gl_TessCoord.y * 3.1415927 * 2.0)*sin(gl_TessCoord.x * 3.1415927);
    position.z = cos(gl_TessCoord.y * 3.1415927 * 2.0)*sin(gl_TessCoord.x * 3.1415927);
    normal = normalize(position).xyz;

    gl_Position = MVP * position;
    normal = (ModelView * vec4(normal,0.0)).xyz;
    vertex = vec3(ModelView * position);
}