我一直在努力在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操作是不够的。