Problems with drawing vertex coordinates gained from transform feedback

Hello there, again…

Ever since I have been able to get my vertex coordinates from transform feedback function, I have been fiddling with a ways to draw my vertices with the help of said coordinates and input coordinates but without success.

The problem is that I am unable to render my vertices onto the screen which have been through transform feedback, while being able to render vertices which did not pass through Transform Feedback.

Hence the lack of sufficient examples and documentation on Transform Feedback drawing and all, I have been unable to find suitable solution to my problem.

Maybe I am doing something wrong in my code ?

main.cpp

int main()
{
	Window Window(width, height, "FRTI ENGINE", false);						   // Clear color rgba
	glClearColor(1.0, 1.0, 1.0, 1.0);	
	
	campos.x = 0;
	campos.y = 0;
	campos.z = NULL;

	float zoom = 1.0;


	float multiplier = 0.5;
	int depth = 1;


	glm::vec2 stemstart;
	glm::vec2 stemend;

	stemstart.x =0.f;
	stemstart.y =0.f;

	stemend.x = 0.f;
	stemend.y = 5.0;
		

	//ShaderProgram render;
	//Shader vertex(GL_VERTEX_SHADER, "Source/Fractals/TREE/Shaders/fractal.vert");
	//Shader fragment(GL_FRAGMENT_SHADER, "Source/Fractals/TREE/Shaders/tree.frag");
	//Shader geometry(GL_GEOMETRY_SHADER, "Source/Fractals/TREE/Shaders/fractal.geom");


	//render.attachshader(vertex);
	//render.attachshader(geometry);
	//render.attachshader(fragment);
	//
	//render.linkProgram();

	Shader vertextransform(GL_VERTEX_SHADER, "Source/Fractals/TREE/Shaders/fractal.vert");
	Shader geometrytransform(GL_GEOMETRY_SHADER, "Source/Fractals/TREE/Shaders/fractal.geom");
	
	Shader vertex (GL_VERTEX_SHADER, "Source/Fractals/TREE/Shaders/tree.vert");
	Shader fragment(GL_FRAGMENT_SHADER, "Source/Fractals/TREE/Shaders/tree.frag");


	ShaderProgram transform;
	transform.attachshader(vertextransform);
	transform.attachshader(geometrytransform);
	transform.attachshader(fragment);

	const GLchar* feedbackVaryings[] = { "branchpos" };
	glTransformFeedbackVaryings(transform.getID(), 1, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
	transform.linkProgram();
	
	
	Uniform geom(transform);
	geom.LocUni("angle");
	geom.LocUni("multiplier");
	geom.LocUni("mvp");



	ShaderProgram render;
	render.attachshader(vertex);
	render.attachshader(fragment);

	render.linkProgram();

	Uniform ren(render);
	ren.LocUni("mvp");

	GLuint VAO;
	glGenVertexArrays(1, &VAO);
	glBindVertexArray(VAO);


			glm::vec2 trunk[2]
		{
			stemstart,
			stemend,
		};


	GLuint VBO;

		glGenBuffers(1, &VBO);
		glBindBuffer(GL_ARRAY_BUFFER, VBO);
		glBufferData(GL_ARRAY_BUFFER,4*sizeof(trunk), trunk, GL_DYNAMIC_DRAW);
		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
		glEnableVertexAttribArray(0);

	

	//UnderConstruction



	
	
	GLuint TBO;
	glGenBuffers(1, &TBO);
	glBindBuffer(GL_ARRAY_BUFFER, TBO);
	glBufferData(GL_ARRAY_BUFFER,  4*sizeof(trunk), nullptr, GL_DYNAMIC_COPY);
	//glDrawArrays(GL_LINE_STRIP, 0, 4);
	
	// loop
	while (!Window.closed())
	{

		//ReadShaders.enable();

		Window.clear();
		//WorldShader.use();

//controls
		if (Window.KeyPressed(GLFW_KEY_Q))
		{
			CAMangle += 0.01;
		}
		if (Window.KeyPressed(GLFW_KEY_E))
		{
			CAMangle -= 0.01;

		}
		if (Window.KeyPressed(GLFW_KEY_W))
		{
			campos.y -= 0.5 / zoom;
			if (Window.KeyPressed(GLFW_KEY_LEFT_SHIFT))
			{
				campos.y -= 1.0 / zoom;
			}
		}
		if (Window.KeyPressed(GLFW_KEY_S))
		{
			campos.y += 0.5 / zoom;
			if (Window.KeyPressed(GLFW_KEY_LEFT_SHIFT))
			{
				campos.y += 1.0 / zoom;
			}
		}
		if (Window.KeyPressed(GLFW_KEY_A))
		{
			campos.x += 0.5 / zoom;
			if (Window.KeyPressed(GLFW_KEY_LEFT_SHIFT))
			{
				campos.x += 1.0 / zoom;
			}
		}
		if (Window.KeyPressed(GLFW_KEY_D))
		{
			campos.x -= 0.5 / zoom;
			if (Window.KeyPressed(GLFW_KEY_LEFT_SHIFT))
			{
				campos.x -= 1.0 / zoom;
			}

		}
		if (Window.KeyPressed(GLFW_KEY_P))
		{
			zoom += 0.01*zoom;
			if (zoom >= DBL_MAX)
			{
				zoom = DBL_MAX;
			}
		}
		if (Window.KeyPressed(GLFW_KEY_O))
		{
			zoom -= 0.01*zoom;
			if (zoom < 0)
			{
				zoom = 0;
			}
		}
		if (Window.KeyPressed(GLFW_KEY_M))
		{
			++bangle;
		}
		if (Window.KeyPressed(GLFW_KEY_R))
		{
			depth++;
		}
		//Camera
		glm::mat4 ortho = glm::ortho(-20.f, 20.f, -20.f, 20.f); //setting custom coordinate space
		glm::mat4 translate = glm::translate(glm::mat4(1.0f), campos);
		glm::mat4 rotate = glm::rotate(glm::mat4(1.0f), CAMangle, glm::vec3(0.0, 0.0, 1.0));
		glm::mat4 scale = glm::scale(glm::mat4(1.0f), glm::vec3(zoom, zoom, 0));
		glm::mat4 unionmatrix = ortho * translate * rotate * scale; //lumping together all needed transformation matrices
		// Coloring
		 //using  shading program



		transform.engage();//drawing of branches(failure) 

		glUniformMatrix4fv(geom.Uni("mvp"), 1, GL_FALSE, glm::value_ptr(unionmatrix));
		glUniform1f(geom.Uni("angle"), bangle);
		glUniform1f(geom.Uni("multiplier"), multiplier);

		//glBindVertexArray(VAO);
	
		glEnable(GL_RASTERIZER_DISCARD);
		glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, TBO);
		glBeginTransformFeedback(GL_LINES);
		glDrawArrays(GL_LINE_STRIP, 0, 4);
		glEndTransformFeedback();
		glDisable(GL_RASTERIZER_DISCARD);

		//glDrawTransformFeedback(GL_LINE_STRIP, TBO);
		//glClear(GL_DEPTH_BUFFER_BIT || GL_COLOR_BUFFER_BIT);
	


		render.engage(); //drawing trunk of the tree(success);

		glUniformMatrix4fv(ren.Uni("mvp"), 1, GL_FALSE, glm::value_ptr(unionmatrix));

		//glBindVertexArray(VAO);
		glDrawArrays(GL_LINE_STRIP, 0, 2); //drawing the stem of the tree.

		

		Window.update();

	
	glm::vec2 feedback[4]; //   hence we need both branches x and y coordinates so array equals 4
		glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 2*sizeof(feedback), feedback);
		std::cout << feedback[1].x << " " << feedback[1].y << " || " << feedback[3].x << " " << feedback[3].y << std::endl;
		
		
		//ReadShaders.disable();
	}
	glDeleteProgram(transform.getID());
	glDeleteShader(vertextransform.getID());
	glDeleteShader(geometrytransform.getID());
	
	glDeleteBuffers(1, &TBO);
	glDeleteBuffers(1, &VBO);
	glDeleteVertexArrays(1, &VAO);
	
	return 0;
}

And thank you for all the previous help @GClements and @Dark_Photon.

So what’s the problem? In your previous post, you indicated that you were able to get the desired data. At which point, rendering should be no different than with any other data. It’s just an array of numbers.

Check that you’ve restored any state which was changed for the previous program. Also ensure you aren’t applying model/view/projection transformations to the vertex coordinates twice.

1 Like

The problem is that I can not draw my transform feedback object inside the loop. Hence i have been defining my objects outside the loop not inside the loop.

I am trying to Draw my transform feedback object with the glSubBufferData();, but without success.

// inside loop main.cpp

		glEnable(GL_RASTERIZER_DISCARD);
		glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, TBO);
		glBeginTransformFeedback(GL_LINES);
		glDrawArrays(GL_LINE_STRIP, 0, 4);
		glEndTransformFeedback();
		glDisable(GL_RASTERIZER_DISCARD);
		
		//GLuint VTFBO;
		glm::vec2 feedback[4];
		
		//glClear(GL_DEPTH_BUFFER_BIT || GL_COLOR_BUFFER_BIT);
		glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 2*sizeof(feedback), feedback);
		glBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 2 * sizeof(feedback), feedback);
		//glDrawArrays(GL_LINE_STRIP, 0, 4);
		//glDrawTransformFeedback(GL_LINE_STRIP, VTFBO);
		//glDrawArrays(GL_LINE_STRIP, 0, 4);
		Window.update();

	
	 //   hence we need both branches x and y coordinates so array equals 4
		
		std::cout << feedback[1].x << " " << feedback[1].y << " || " << feedback[3].x << " " << feedback[3].y << std::endl;

I don’t see any code where you have tried to render from the feedback data. I don’t see that you have changed the buffers you read vertex data from to those which were written by the feedback operation.

Also, if you’re doing TF, why are you reading from the feedback buffer to the CPU? And why are you immediately re-uploading that data to the feedback buffer?

I am sorry for overall newbieness.

“I don’t see any code where you have tried to render from the feedback data”

I see what you are saying, but how should i try to render from TF data?

Should I make separate Buffer Object for drawing feedback inside the loop which looks like a bad Idea in my eyes.

Or Should I make separate Buffer and Array Object for drawing feedback outside the loop which looks like a better Idea in my eyes.

And if really I do not know how can I make the buffer which specializes in drawing from transform feedback output.

“Also, if you’re doing TF, why are you reading from the feedback buffer to the CPU? And why are you immediately re-uploading that data to the feedback buffer?”
Then please how may I then read my feedback buffer to the GPU which to me looks more efficient.

Bind the buffer containing the TF output to GL_ARRAY_BUFFER then use glVertexAttribPointer() to set up the attribute arrays to source from those buffers

You have one set of buffers containing the original vertex attribute data which is read when rendering with TF enabled. You have another set of buffers to which TF writes, which are then used as the vertex attribute data in order to render the result of TF.

If you use a Transform Feedback Object (glGenTransformFeedbacks, glBindTransformFeedback), you can render the result of a TF operation using glDrawTransformFeedback(). This still requires setting up the attribute arrays with glVertexAttrib* etc, but it uses the vertex count stored in the TFO which avoids a GPU-CPU-GPU round trip for the count.

Your feedback buffer is already on the GPU. That’s the point of buffers; they’re blocks of memory which can be efficiently read and written by the GPU (i.e. either they’re GPU memory, or they’re both CPU and GPU memory which the implementation will automatically synchronise).

To render the results of TF, you don’t copy the TF data, you just use the TF output buffer(s) as the input buffer(s) for the rendering operation.

1 Like

Thank you for considerable help I was able to draw the object from vertices but,

Problem is that it does not change angle between midbranches when I press m (which is the key to change it) but other mvp transformations work fine.

I saw that my branch rendering is done in render shader program hence changing glDrawArray() vertex number changes how the object is drawn (1 branch or 2 branches);

new main.cpp inside loop;

		transform.engage();// 

		glUniformMatrix4fv(geom.Uni("mvp"), 1, GL_FALSE, glm::value_ptr(unionmatrix));
		glUniform1f(geom.Uni("angle"), bangle);
		glUniform1f(geom.Uni("multiplier"), multiplier);

		//glBindVertexArray(VAO);


		
		glEnable(GL_RASTERIZER_DISCARD);
		glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, TBO);
		glBeginTransformFeedback(GL_LINES);
		glDrawArrays(GL_LINE_STRIP, 0, 4);
		glEndTransformFeedback();
		glDisable(GL_RASTERIZER_DISCARD);
		glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, TFO);
		glm::vec2 feedback[4];
		glGetBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 2 * sizeof(feedback), feedback);
		//glBufferSubData(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 2 * sizeof(feedback), feedback);
		glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
		glDrawTransformFeedback(GL_LINE_STRIP, TFO);


		//GLuint VTFBO
		
		//glClear(GL_DEPTH_BUFFER_BIT || GL_COLOR_BUFFER_BIT);

		
	render.engage(); //drawing trunk of the tree(success); NOW IT DRAWS THE BRANCHES
	//
		glUniformMatrix4fv(ren.Uni("mvp"), 1, GL_FALSE, glm::value_ptr(unionmatrix));
	//	glUniform1f(geom.Uni("angle"), bangle);
	//	glUniform1f(geom.Uni("multiplier"), multiplier);
		//glBindVertexArray(VAO);
		glDrawArrays(GL_LINE_STRIP, 0, 2);
		Window.update();

	
	 //   hence we need both branches x and y coordinates so array equals 4
		
		//std::cout << feedback[1].x << " " << feedback[1].y << " || " << feedback[3].x << " " << feedback[3].y << std::endl;
		
		
		//ReadShaders.disable();

new main.cpp outside loop

	GLuint TBO;
	glGenBuffers(1, &TBO);
	glBindBuffer(GL_ARRAY_BUFFER, TBO);
	glBufferData(GL_ARRAY_BUFFER,  4*sizeof(trunk), nullptr, GL_DYNAMIC_COPY);
	//glBufferData(GL_ARRAY_BUFFER, 4 * sizeof(trunk), nullptr, GL_DYNAMIC_DRAW);
	
	GLuint TFO;
	glGenTransformFeedbacks(1, &TFO);
	///glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, TFO);
	//glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);