我一直在努力在Android上创建有效的转换反馈。到目前为止,我得到的最接近的问题与这个被低估的问题类似:https://stackoverflow.com/questions/41066101/transform-feedback-altering-render-result

我要创建的内容:

从顶点缓冲区对象渲染为变换反馈。然后使用最终的绘图着色器从变换反馈的缓冲区进行渲染。

我如何理解整个概念:

我了解程序与变量之间的联系方式(我遵循了此示例:https://gist.github.com/hpp/d2d26adc5987002eb520
在Android上,您必须提供“虚拟”片段着色器,否则程序链接将失败,并且不显示任何消息。

拥有链接程序之后,请执行以下步骤:(代码在Java中)


创建一个VBO来读取数据

int[] vbo = new int[1];
glGenBuffers(1, vbo, 0);
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, bufferLength, data, GL_STATIC_READ);

创建转换反馈缓冲区

int[] tbo = new int[1];
glGenBuffers(1, tbo, 0);
glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo[0]);
glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bufferLength, null, GL_DYNAMIC_COPY);
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tbo[0]);

每当我想进行计算时,我都会这样称呼:

glUseProgram(calculationShaderProgram);
// For all input variables:
glEnableVertexAttribArray(inputAttrib);
glVertexAttribPointer(...

// To bind the transform feedback buffer as the destination
glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, tfo[0]);

glEnable(GL_RASTERIZER_DISCARD);
glBeginTransformFeedback(GL_POINTS);
glDrawArrays(GL_POINTS, 0, vertexCount);
glEndTransformFeedback();
glDisable(GL_RASTERIZER_DISCARD);

glFinish(); // I know this is slow to call, but for simplicity's sake

之后,我应该能够绘制缓冲区的内容:

glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, tbo[0]);

glUseProgram(drawShaderProgram);
// For all input variables:
glEnableVertexAttribArray(inputAttrib);
glVertexAttribPointer(...

// Set uniforms ...
glDrawArrays(GL_POINTS, 0, vertexCount); // There is no glDrawTransformFeedback on android



现在,我的问题是:


在此过程中是否存在天生的错误?
即使我什么都没画,计算部分是否会弄乱我的设备的屏幕呢? (它显示随机颜色或由android更新的图标,例如电池和网络)
使用GL_TRANSFORM_FEEDBACK_BUFFER的顶点数组对象是否与使用GL_ARRAY_BUFFER的顶点数组对象相同?

最佳答案

花了一些时间,但这是解决方案。我将其保留在此处,因为在任何可用的OpenGL相关书籍中都没有正确解释这些部分。


从变换反馈缓冲区进行绘制时(上面的步骤4),无论它是否用作变换反馈缓冲区都没有关系,您必须将其绑定为GL_ARRAY_BUFFER,就像从顶点缓冲区对象中进行绘制一样。

glBindBuffer(GL_ARRAY_BUFFER, tbo[0]);

使用默认的帧缓冲时,

glBindFrameBuffer(GL_FRAMEBUFFER, 0);


或根本没有设置,则不允许使用

glEnable(GL_RASTERIZER_DISCARD);
// Draw to Transform feedback
// ...
glDisable(GL_RASTERIZER_DISCARD);


(在第3步中)而无需先致电

glClear(GL_COLOR_BUFFER_BIT);


否则,您将看到随机模式作为背景。在每个绘制循环之前仅进行一次glClear操作是不够的。

10-04 10:45