使用具有不同属性数的两个或多个着色器时发生冲突

Conflict when using two or more shaders with different number of attributes

本文关键字:两个 冲突 属性      更新时间:2023-09-26

我正在尝试在我的WebGL程序中实现拾取(使用颜色和readPixels)。当我启动我的程序时,我创建了分离阴影程序。一个用于打电话着色,另一个只是给形状一种颜色,用来检测点击了哪个形状

phong着色器有2个属性。顶点位置和顶点法线。挑选的人只是有位置。

现在我发现,由于某种奇怪的原因,当这两个着色器都存在于同一个程序中,并且我正在使用picking着色器时,我的drawArray调用似乎失败了。最后一件事是我的gl.vertexAttribPointer调用。我一直在胡思乱想,发现当我检查活动的attrib数组时,使用:gl.getVertexAttrib(索引,gl.VERTEX_ATTRIB_ARAY_ENABLED);

两个0,1都返回true(这是指拾取着色器使用gl.useProgram(拾取)处于活动状态时)

现在,如果我使用gl.disableVertexAttribArray(1)禁用1;一切恢复正常。另一个修复方法是先用phong着色器绘制,然后使用拾取着色器,这神奇地使它正常。我猜在这种情况下,当使用phong着色器时附加顶点法线缓冲区时,当我切换到拾取着色器并使用drawArray调用时,它会以某种方式保持不变。

我想知道我是否错误地使用了gl.enableAttribArray,并且在切换着色器或类似的东西时应该禁用它们。

我还尝试过以不同的顺序创建着色器程序,但没有成功。

正如您可能已经发现的那样,useProgram除了应该在下一次绘图调用中运行的程序(着色器代码)之外,不会影响任何东西。您必须确保仅启用当前程序使用的属性。

如果您以某种方式包装了WebGL代码,建议将每个程序的最高可用属性编号存储在包装器中的某个位置,然后与最新使用的程序进行比较,并在draw调用之前相应地启用/禁用。

如果没有看到您的代码,很难判断,但是。。。WebGL要求所有将被访问的属性都有足够的数据来满足draw调用。因此,如果您设置了两个属性,每个属性都有3个数据顶点,并绘制了3个顶点,然后切换着色器并设置了一个属性,其中有6个顶点,第二个属性只有3个顶点然后尝试绘制6个顶点。如果您当前绘制的着色器访问这两个属性WebGL将使绘制调用失败。

如果你运行Chrome 19,它应该在JavaScript控制台中告诉你这是否是问题所在。

OpenGL是一个状态机。通过选择拾取着色器,可以使OpenGL处于不再具有phong着色器的附加属性的状态。

许多人陷入了错误和糟糕的习惯,认为OpenGL存在某种"一次性初始化"。事实并非如此。您应该设置某些绘图操作所需的所有状态,就在该绘图操作之前,理想情况下还应该在完成后恢复设置。这意味着:绑定着色器后,还应该启用和绑定所需的着色器输入,即顶点属性。