我正在尝试使用“顶点”着色器重新定位粒子(存储在纹理中),这些粒子将传递到Frag着色器并存储在单独的纹理中。
我正在尝试完全在GPU上实现高效的空间分级。这是针对SPH流体模拟的。
是否可以将2D纹理的所有像素(textels)传递到Vertex Shader?每个textel(RGBA)将被重新解释为传入的顶点(XYZW)。
答案 0 :(得分:3)
如果硬件支持Vertex Texture Fetch,则可以将2D纹理传递到顶点着色器。您可以使用以下代码对此进行测试:
int maxVertexTextureImageUnits;
glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextureImageUnits);
如果maxVertexTextureImageUnits
为零,则不支持此功能。
您不直接将纹理作为顶点数据传递,而是创建一个顶点网格,其坐标对应于纹理中每个像素的纹理坐标。然后在顶点着色器中使用这些顶点来读取片段着色器中生成的实际顶点坐标(纹素值)。然后将它们用于计算gl_Position
。
我从未亲自使用此功能(我的平台不支持),但我已经看到了酷炫的粒子/流体演示。我相信对它的支持是相当不稳定的。即使在支持它的硬件上,驱动程序也可能无法实现它。
答案 1 :(得分:2)
不可能假装2D纹理实际上是顶点数据。但是,我想知道你为什么要这样做。
最有效的方法是不将粒子数据存储为纹理,而是存储在buffer objects中。您可以直接使用缓冲区对象作为顶点数组的源数据。
鉴于“我将数据存储为纹理,因为粒子位置是片段着色器的输出”,我可以建议更有用的东西:buffer textures。这些是将数据存储在缓冲区对象中的1D纹理。它们仍然可以用作渲染目标(尽管显然你需要改变栅格化数据的方式,因为它们是一维渲染目标),但它们渲染的内容存储在缓冲区对象中。
这样,您可以对缓冲区纹理进行渲染,然后将缓冲区绑定为数组和源代码。
如果你绝对必须渲染到2D纹理,你可以使用更慢的方法:read from the texture into a buffer object. PBO主要用于异步像素传输,所以我建议给GPU一些别的东西在执行glGetTexImage
到缓冲区的时间与从中调用glDrawArrays
进行渲染的时间之间。否则,你只会停止GPU。
答案 2 :(得分:1)
是的,这很简单:只需渲染像素一样多的顶点,但不要绑定顶点缓冲区。相反,通过获取顶点ID(gl_VertexID
)来计算与当前顶点对应的像素(您应该渲染为点。)从顶点ID,您可以在纹理上发出提取并获取数据(确保你使用texelFetch
。)