从 webgl 中的着色器中更新缓冲区



我是着色器和WebGL的初学者,我已经采取了一些捷径来开发我目前拥有的东西,所以请耐心等待。

有没有办法只更新 GPU 中的属性缓冲区数据?基本上我想做的是将三个缓冲区 t0、t1、t2 发送到 GPU 中,分别代表点及其在时间 0、1 和 2 中的位置。然后,我希望根据 t2、t1 和 t0 的属性更新它们的新位置 tn,具体取决于点的速度、转弯角度等。

我目前的实现更新了javascript中的位置,然后在每次绘制时将缓冲区复制到WebGL中。但是为什么?这对我来说似乎非常低效,我不明白为什么我不能在着色器中做所有事情来跳过从 CPU->GPU 移动数据。这可能吗?

这是当前的顶点着色器,它根据转弯方向和转弯角度在点上设置颜色(tn 在 JS atm 中通过调试函数更新(:

export const VsSource = `
#define M_PI 3.1415926535897932384626433832795

attribute vec4 t0_pos;
attribute vec4 t1_pos;
attribute vec4 t2_pos;
varying vec4 color;
attribute vec4 r_texture;
void main() {
float dist = distance(t1_pos, t2_pos);
vec4 v = normalize(t1_pos-t0_pos);
vec4 u = normalize(t2_pos-t1_pos);
float angle = acos(dot(u, v));
float intensinty = angle / M_PI * 25.0;
float turnDirr = (t0_pos.y-t1_pos.y) * (t2_pos.x-t1_pos.x) + (t1_pos.x-t0_pos.x) * (t2_pos.y-t1_pos.y);
if(turnDirr > 0.000000001 ) {
color = vec4(1.0, 0.0, 0.0, intensinty);
} else if( turnDirr < -0.000000001 ) {
color = vec4(0.0, 0.0, 1.0, intensinty);
} else {
color = vec4(1.0, 1.0, 1.0, 0.03);
}

gl_Position = t2_pos;
gl_PointSize = 50.0;
}
`;

我想做的是根据这些属性更新位置gl_Position (tn(,然后以某种方式洗牌/复制缓冲区 tn->t2、t2->t1、t1->t0 为另一个周期做准备,但所有这些都在顶点着色器中(不仅是为了效率,也是出于与问题无关但与我正在从事的项目相关的其他一些原因(。

请注意,您的问题可能应该作为重复项关闭,因为已经涵盖了如何从顶点着色器编写输出,但只是添加一些与您的问题相关的注释......

在 WebGL1 中,无法更新 GPU 中的缓冲区。您可以改为将数据存储在纹理中并更新纹理。不过,您无法从自身更新纹理

pos = pos + vel   // won't work

但是您可以更新另一个纹理

newPos = pos + vel   // will work

然后下次将称为newPos的纹理传递为pos,反之亦然

在WebGL2中,您可以使用"transformFeedback"将顶点着色器的输出(变化(写入缓冲区。它具有相同的问题,即您无法写回正在从中读取的缓冲区。

在这个答案中,有一个写入纹理的示例,还有一个使用 transformfeedback 写入缓冲区的示例

也是在此处将顶点数据放在纹理中的示例

有一个粒子系统使用纹理来更新本问答中的位置的示例

最新更新