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

Javascript 使用具有不同属性数的两个或多个着色器时发生冲突,javascript,opengl-es,webgl,Javascript,Opengl Es,Webgl,我正在尝试在我的WebGL程序中实现拾取(使用颜色和读取像素)。当我启动程序时,我会创建一个单独的着色器程序。一个用于phong着色,另一个用于简单地为形状提供一种颜色,用于检测单击的形状 phong着色器具有2个属性。顶点位置和顶点法线。挑选的人只是有位置 现在我发现,出于某种奇怪的原因,当这两个着色器存在于同一个程序中并且我正在使用拾取着色器时,我的drawArray调用似乎失败了。最后发生的事情是我的gl.vertexattributepointer调用。我一直在胡闹,发现当我使用以下工具

我正在尝试在我的WebGL程序中实现拾取(使用颜色和读取像素)。当我启动程序时,我会创建一个单独的着色器程序。一个用于phong着色,另一个用于简单地为形状提供一种颜色,用于检测单击的形状

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

现在我发现,出于某种奇怪的原因,当这两个着色器存在于同一个程序中并且我正在使用拾取着色器时,我的drawArray调用似乎失败了。最后发生的事情是我的gl.vertexattributepointer调用。我一直在胡闹,发现当我使用以下工具检查活动attrib阵列时: gl.getVertexAttrib(索引,启用gl.VERTEX属性数组)

两个0,1都返回true(这是当使用gl.useProgram(拾取)激活拾取着色器时)

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

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


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

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


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

如果不查看代码,很难判断,但是。。。WebGL要求要访问的所有属性都有足够的数据来满足draw调用。因此,如果设置2个属性(每个属性具有3个数据顶点)并绘制3个顶点,则切换着色器并设置1个属性(具有6个顶点),并保留第二个属性(仅具有3个顶点),然后尝试绘制6个顶点,如果您当前使用两个属性绘制的着色器访问WebGL,则绘制调用将失败


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

正如您可能已经发现的那样,useProgram只会影响下一次draw调用中应该运行的程序(着色器代码)。必须确保仅启用当前程序使用的属性


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

我在每个gl.useProgram之后启用顶点属性数组,但这并不能修复它。我仍然需要使用gl显式禁用第二个属性数组。disableAttributeArray(1)@nkassis:然后禁用它。这就是你应该做的。@nkassis只是一个澄清,要调用的函数拼写为gl.DisableVertexAttributeArrayYeah chrome 19确实抱怨“无效的操作:drawArrays:attribs未正确设置”(顺便说一句:OMG感谢greg的添加:P)我的印象是,当我使用另一个着色器运行gl.useProgram时,启用的顶点属性会重置。现在我启用了两个顶点属性,而我应该为这个特定着色器启用一个顶点属性。显示代码有点困难,因为我将代码包装在一堆对象和函数中,以使我的生活更轻松;p这就是我决定要做的,我知道每个着色器存在哪些顶点属性,哪些着色器处于活动状态,所以我只是包装我的gl.useProgram调用,以便我可以首先进行清理。实际上,useProgram会影响制服。您可以通过制作同一程序的多个副本来模拟GL_ARB_uniform_buffer_对象,事实上,驾驶员可以在GL_ARB_uniform_buffer_对象的引擎盖下进行此操作。您认为制服受到影响的方式是什么?据我所知,由于安全原因,一个项目的制服不能在另一个项目内使用——但它们的状态不应受到GL.useProgram的影响,不是吗?