OpenGL 3.x变换反馈GL_SEPARATE_ATTRIBS模式分离VBO配置问题
在macOS OpenGL 3.x中用变换反馈分离输出坐标和颜色到独立VBO
完全可以实现你的需求,你遇到的编译/链接错误是因为接口块的绑定配置和变换反馈的设置步骤有误,以下是正确的实现流程:
1. 修正着色器接口块写法
着色器中必须为输出接口块指定binding布局限定符,绑定值对应后续VBO的变换反馈缓冲绑定点。注意不要在变量名后加多余的点,示例顶点着色器:
#version 150 core // 对应macOS OpenGL 3.2 Core Profile layout(location = 0) in vec3 coords_in; layout(location = 1) in vec3 colors_in; // 坐标输出块,绑定到变换反馈缓冲点0 layout(binding = 0) out BlockCoords { vec3 coords_out; }; // 颜色输出块,绑定到变换反馈缓冲点1 layout(binding = 1) out BlockColors { vec3 colors_out; }; void main() { // 示例:生成两倍顶点,复制并偏移原顶点 if (gl_VertexID % 2 == 0) { coords_out = coords_in; colors_out = colors_in; } else { coords_out = coords_in + vec3(0.1, 0.1, 0.0); colors_out = colors_in * 0.8; } }
2. 设置变换反馈模式与缓冲绑定
- 必须使用
GL_SEPARATE_ATTRIBS模式替代之前的GL_INTERLEAVED_ATTRIBS,因为要将数据输出到独立VBO。 - 创建两个VBO并分配足够内存(至少为源顶点数的2倍对应数据大小),再绑定到对应的变换反馈缓冲点:
// 创建并初始化坐标VBO GLuint coords_vbo; glGenBuffers(1, &coords_vbo); glBindBuffer(GL_ARRAY_BUFFER, coords_vbo); glBufferData(GL_ARRAY_BUFFER, 2 * source_vert_count * sizeof(float)*3, nullptr, GL_STATIC_COPY); // 创建并初始化颜色VBO GLuint colors_vbo; glGenBuffers(1, &colors_vbo); glBindBuffer(GL_ARRAY_BUFFER, colors_vbo); glBufferData(GL_ARRAY_BUFFER, 2 * source_vert_count * sizeof(float)*3, nullptr, GL_STATIC_COPY); // 创建并绑定变换反馈对象(TFO) GLuint tfo; glGenTransformFeedbacks(1, &tfo); glBindTransformFeedback(GL_TRANSFORM_FEEDBACK, tfo); // 将VBO绑定到变换反馈缓冲绑定点,对应着色器中的binding值 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, coords_vbo); glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, colors_vbo);
3. 配置变换反馈输出变量并链接程序
必须在程序链接前调用glTransformFeedbackVaryings,指定要捕获的输出变量,顺序要和缓冲绑定点对应:
// 指定变换反馈要捕获的输出变量 const GLchar* varyings[] = {"coords_out", "colors_out"}; glTransformFeedbackVaryings(program, 2, varyings, GL_SEPARATE_ATTRIBS); // 链接程序并检查状态 glLinkProgram(program); GLint link_ok; glGetProgramiv(program, GL_LINK_STATUS, &link_ok); if (!link_ok) { char log[1024]; glGetProgramInfoLog(program, 1024, nullptr, log); fprintf(stderr, "Program link error: %s\n", log); }
4. 执行变换反馈
执行时禁用光栅化(不需要生成片段,提升性能),然后启动变换反馈并绘制源顶点:
glEnable(GL_RASTERIZER_DISCARD); glBeginTransformFeedback(GL_POINTS); // 根据你的源图元类型调整,比如GL_TRIANGLES glDrawArrays(GL_POINTS, 0, source_vert_count); glEndTransformFeedback(); glDisable(GL_RASTERIZER_DISCARD);
关键注意事项
- macOS的OpenGL 3.2 Core Profile完全支持上述特性,确保你的上下文是Core Profile而非兼容模式。
- 接口块的
binding值必须和glBindBufferBase的第二个参数(缓冲绑定点)一一对应。 glTransformFeedbackVaryings必须在程序链接前调用,调用后需重新链接程序。
内容的提问来源于stack exchange,提问作者Graou
相关产品推荐
相关产品推荐

