【问题标题】:WebGL: Pass texture from vertex shader to fragment shaderWebGL:将纹理从顶点着色器传递到片段着色器
【发布时间】:2018-07-24 20:04:28
【问题描述】:

是否可以将纹理从顶点传递到 WebGL 中的片段着色器?如果是这样,如何实现这种行为?

我尝试将 Sampler2D 传递给片段着色器,但出现错误:

sampler2Ds 必须是统一的

如果其他人可以在这个问题上提供任何帮助,我将不胜感激!

【问题讨论】:

  • 请尽可能多地展示您的 vs 和 fs 源代码以帮助我们帮助您
  • @DacreDenny 你是说可以将纹理从顶点着色器传递到片段着色器吗?我没有发布代码,因为错误似乎断言 sampler2D 必须是统一的,而不是变化的。无论如何,我会更新问题...
  • 看下面的答案

标签: glsl webgl


【解决方案1】:

为什么要将纹理从顶点着色器传递到片段着色器?只需在两个着色器中声明相同的采样器?

顶点着色器

...
uniform sampler2D foo;
....

片段着色器

...
uniform sampler2D foo;
...

否则答案是否定的,你不能在着色器之间传递纹理。您可以传递一些值来选择采样器结果

顶点着色器

varying float textureSelector;
...
textureSelector = ???

片段着色器

vec4 color1 = texture2D(foo, ...);
vec4 color2 = texture2D(bar, ...);
vec4 color = mix(color1, color2, textureSelector);

注意:根据 Nicol 的 cmets 更新,根据规范,如果在内部条件代码中使用纹理会中断。来自the spec, Appendix A.6

纹理访问

在非统一条件块的主体内访问 mip 映射纹理会给出未定义的值。非统一条件块是在编译时无法确定执行的块

换句话说,这样的代码可能不起作用

varying float textureSelector;
uniform sampler2D foo;
uniform sampler2D bar;

...

if (textureSelector > ???) {
  ... use foo ...
} else {
  ... use bar ...
}

所以我想最好在着色器的非条件部分对所有纹理进行采样,然后使用上述 mix 之类的数学运算,或者在从纹理中获取值后使用条件。访问 N 个纹理但只选择 1 个的示例。

#define NUM_TEXTURES 6
uniform sampler2D u_textures[NUM_TEXTURES];
varying float textureSelector;  // 0 to NUM_TEXTURES - 1
void main() {
  vec4 color = vec4(0);
  for (int i = 0; i < NUM_TEXTURES; ++i) {
    float id = float(i);
    float mult = step(id - .5, textureSelector) * step(textureSelector, id + .5);
    vec4 texColor = texture2D(u_textures[i], someTexCoord);
    color = mix(color, texColor, mult); 
  }
  ... use color ...
}

当然,对于大多数用例,您可能应该使用纹理图集并使用纹理坐标来选择其中的一部分。使用多个纹理的正常原因是法线贴图、不透明度贴图、反射率贴图、环境光遮蔽、照明和/或平滑混合(如泥土/草/雪),在这种情况下您不需要条件。要重新迭代,在着色器中从多个纹理中进行选择并不常见。

【讨论】:

  • 谢谢,我以为是这样。您是否知道是否存在所有可能变化的数据类型的列表?用例是避免片段着色器中的大型纹理查找树(我有多个纹理,如果我能在顶点着色器中找到适合片段的纹理,我认为那将是最佳的)。当你说“你可以传递一些值来选择着色器”时,你能多说一下你的意思吗——我可以为每个纹理定义一个片段着色器,然后只改变用于给定点的片段着色器吗?
  • "if (textureSelector > ???)" 这样做有很多注意事项。 WebGL 是否支持dFdx/y 函数和textureGrad?如果不是,那么这样的选择器会引入问题。至少,如果实际的纹理提取是在条件下完成的。如果您之前都进行了提取并忽略了条件中的其中一个,那将起作用。
  • WebGL Reference Sheetthe spec 中有一个可能变化的列表,参考表显示了每个主题的规范部分。
  • 谢谢@gman。我正在将我的纹理索引转换为一个 int,然后使用它来执行查找——这是否解决了你提到的问题,NicolBolas?
  • 我知道根据变量选择纹理没有明显的问题。当然它们是变化的,所以它们变化。转换为 int 不会阻止它们变化。为三角形的每个顶点传递相同的值。我真的取决于你想用它们做什么。当然也可以混用。 GLSL 只是一种编程语言。给定输入,由您来编写正确的数学运算。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-20
  • 1970-01-01
  • 1970-01-01
  • 2013-09-17
  • 1970-01-01
相关资源
最近更新 更多