OpenGL Transform Feedback

官网链接

使用TransFrom Feedback捕获图元数据,必须注意的几点:

  • 必须在链接着色器之前设置要捕获的输出变量:glTransformFeedbackVaryings

  • 顶点着色器、细分着色器、几何着色器的输出变量都可以被捕获,但只有最后一个顶点处理着色器的输出能被捕获。

    开始捕获时捕获类型的设置:glBeginTransformFeedback
    If a Geometry Shader is active, then it is the primitive type output by the GS.
    当有几何着色器时,捕获类型是几何着色器的输出
    If a Tessellation Evaluation Shader is active, then it is the primitive type generated by the tessellation process.
    当有细分着色器时,捕获类型由细分着色器产生。
    If neither of those are available, then it is the mode​ parameter of the command used to render.
    没有几何着色器和细分着色器时,捕获类型就是渲染命令使用的类型。

  • 捕获的是图元数据,图元的顶点数据会自动排好序,可以直接用于Feedback rendering

  • GL_TRANSFORM_FEEDBACK_BUFFER 的绑定:

    glBindBuffer并不会影响transform feedback的状态,必须要由glBindBufferBase或者glBindBufferRange进行绑定。由于影响的是 transform beedback的状态,所以绑定buffer之前,要先绑定transform feedback object。
    The GL_TRANSFORM_FEEDBACK_BUFFER buffer binding point may be passed to glBindBuffer,but will not directly
    affect transform feedback state. Instead, the indexed GL_TRANSFORM_FEEDBACK_BUFFER bindings must be used
    through a call to glBindBufferBase or glBindBufferRange. This will affect the generic GL_TRANSFORM_FEEDBACK_BUFFER binding.

程序示例:

顶点着色器:

#version 440 core

layout(location = 0) in vec4 VsInPos;
layout(location = 1) in vec4 VsInColor;

out vec4 color;

void main()
{
	gl_Position = VsInPos;
	color = VsInColor;
}

细分控制着色器:

#version 440 core

layout(vertices = 3) out;

in vec4 color[];

out vec4 TCcolor[];

void main()
{
	gl_TessLevelInner[0] = 2.0;

	gl_TessLevelOuter[0] = 2.0;
	gl_TessLevelOuter[1] = 2.0;
	gl_TessLevelOuter[2] = 2.0;

	gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
	TCcolor[gl_InvocationID] = color[gl_InvocationID];		
}

细分计算着色器:

#version 440 core

layout(triangles, equal_spacing, cw) in;

layout (binding = 0, offset = 0) uniform atomic_uint TessCoord;

in vec4 TCcolor[];

flat out vec4 color;
 
void main()
{
	atomicCounterIncrement(TessCoord);

	float u = gl_TessCoord.x;
	float v = gl_TessCoord.y;
	float w = gl_TessCoord.z;
	
	gl_Position = u * gl_in[0].gl_Position + v * gl_in[1].gl_Position + w * gl_in[2].gl_Position;	
	color = TCcolor[0]*u + TCcolor[1]*v + TCcolor[2]*w;
}

片段着色器:

#version 440 core

out vec4 FragColor;

flat in vec4 color;

void main()
{
	FragColor = color;
}
void init()
{
	ShaderInfo si[] = {
		{ GL_VERTEX_SHADER, "tess_tfb.v"},
		{GL_TESS_CONTROL_SHADER, "tess_tfb.tesc"},
		{GL_TESS_EVALUATION_SHADER, "tess_tfb.tese"},
		{ GL_FRAGMENT_SHADER, "tess_tfb.g"},
		{GL_NONE, ""}
	};
	program = LoadShaders(si);

	static const char * varyings = "gl_Position";
	glTransformFeedbackVaryings(program, 1, &varyings, GL_INTERLEAVED_ATTRIBS);
	glLinkProgram(program);
	glUseProgram(program);

    glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);
	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vert), vert, GL_STATIC_DRAW);

	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
	glEnableVertexAttribArray(0);

	glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(sizeof(float)*2*4));
	glEnableVertexAttribArray(1);
	glBindVertexArray(0);

	// Create the atomic counter buffer
	glGenBuffers(1, &atomic_counter_buffer);
	glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomic_counter_buffer);
	glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_COPY);

	glGenTransformFeedbacks(1, &tfb);
	glBindTransformFeedback(GL_TRANSFORM_FEEDBACK,tfb);

	glGenBuffers(1, &tfb_buffer);
	glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tfb_buffer);
	glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1024 * sizeof(float), NULL, GL_DYNAMIC_READ);
	glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfb_buffer);
	glGenQueries(1, &tfb_queriy);

	glClearColor(0.1, 0.1, 0.1, 1.0);
}

void display()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glUseProgram(program);
	glPatchParameteri(GL_PATCH_VERTICES, 3);
	// Reset atomic counter
	if (output==false)
	{
		GLuint * data;
		glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomic_counter_buffer);
		data = (GLuint *)glMapBuffer(GL_ATOMIC_COUNTER_BUFFER, GL_WRITE_ONLY);
		data[0] = 0;
		glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
	}
		
	glBindVertexArray(vao);
	glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);	
	glBeginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, tfb_queriy);
	glBeginTransformFeedback(GL_TRIANGLES);
	glDrawArrays(GL_PATCHES, 0, 6);
	glEndTransformFeedback();
	glEndQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);

	static bool output = false;
	if (output == false)
	{
		GLuint * data;
		data = (GLuint *)glMapBuffer(GL_ATOMIC_COUNTER_BUFFER, GL_READ_ONLY);

		cout << "coordCount:" << *data << endl;		
		glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
			
		GLint triangleCount;
		glGetQueryObjectiv(tfb_queriy, GL_QUERY_RESULT, &triangleCount);
		cout <<"Triangle: " << triangleCount << endl;

		vmath::vec4* tfb_coord = (vmath::vec4*)glMapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
		for (int i = 0; i < triangleCount*3; i++)
		{
			int index = 4 * i;
			cout << (*tfb_coord)[index+0] << " " << (*tfb_coord)[index+1] << " " << (*tfb_coord)[index+2] << endl;
		}
		glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
		output = true;
	}

	glutSwapBuffers();
}

在这里插入图片描述

coordCount是14,是由于绘制的是两个面片,共用的边上的顶点计算了两次。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值