【问题标题】:WebGL: use both texture and color buffersWebGL:同时使用纹理和颜色缓冲区
【发布时间】:2014-09-06 18:36:53
【问题描述】:

This question,其中 OP 报告在执行指令 gl.enableVertexAttribArray(shaderProgram.textureCoordAttribute); 时发出警告让我思考:如果我想要一个场景中有两个(假设:平面)形状,一个有纹理和一个颜色统一的?在片段着色器的main 中,如果我取消注释第二条指令并注释掉第一条指令,如下所示:

void main(void) {
    //gl_FragColor = vColor;
    gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));
}

警告仍在发出,但这次是关于指令gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);
如果我不加注释,它仍然会抱怨 vertexColorAttribute 因为很明显它被覆盖了。
那我怎么能两者兼得?我要使用两个不同的片段着色器吗?如果可以,怎么做?

【问题讨论】:

  • 对不起,我确定我有。谢谢。
  • 没问题,谢谢:)

标签: javascript webgl


【解决方案1】:

正确的方法是有两个单独的着色器,因为你想渲染任何一个 有纹理的彩色的。

以内存和执行时间为代价,您的顶点数据中可能始终具有颜色纹理属性,并根据您的用例使用某种混合。

正如您所描述的,您可以使用简单的加法混合,因为大多数 WebGL 实现在没有绑定纹理时默认绑定黑色像素 [0,0,0,255] 纹理。

因此有类似的东西

void main(void) {
    gl_FragColor = vColor + texture2D(uSampler, vTexCoord);
}

当没有绑定纹理时会渲染颜色,当颜色为 [0,0,0,0] 时会正确渲染绑定的纹理。

有关各种blend modes 的概述,请参见维基百科

作为一个更昂贵的解决方案,您可以只使用统一作为标志来指示您想要使用的“方法”并相应地在着色器内部分支。不过,这仍然需要所有顶点属性都可用,而且在某些平台上分支效率很低。

void main(void) {
    if (uMethod == 1)
        gl_FragColor = vColor;
    else if (uMethod == 2)
        gl_FragColor = texture2D(uSampler, vTexCoord);
    else
        gl_FragColor = vColor + texture2D(uSampler, vTexCoord);
}

【讨论】:

  • 另一种方法是将多个图像打包到一个纹理中并调整纹理坐标以显示正确的区域。其中一个区域可能是一个纯红色正方形。
  • 这会使其非常不灵活,要么需要分支和/或繁重的纹理坐标变换数学,要么会浪费大量 GPU 存储空间。
  • 我不这么认为,这是纹理图集的标准。您只需在顶点缓冲区中相应地设置纹理坐标,然后就不需要任何颜色制服或属性。
  • 每次添加其他颜色的网格时,您都需要使用该图集调整图集以及所有网格上的所有纹理坐标...
  • 如果 OP 真的只想使用统一颜色进行渲染,那么好吧,无论如何都可以放弃顶点属性,只在着色器中使用一种统一颜色。
猜你喜欢
  • 2014-12-05
  • 1970-01-01
  • 2022-10-15
  • 2011-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多