如何在WebGL中使用纹理和颜色?

时间:2011-12-18 14:48:06

标签: javascript glsl webgl

我正在学习WebGL,我想制作一个程序,其中还有彩色和纹理对象。我尝试修改片段着色器:如果对象没有纹理,那么它将被着色。

precision mediump float;

varying vec4 vColor;
varying vec2 vTextureCoord;

uniform sampler2D uSampler;

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

它不起作用。我收到错误:无法初始化着色器。

2 个答案:

答案 0 :(得分:8)

这可能有意义也可能没有意义,但无论您是否有纹理都需要不同的着色器。为了解决这个问题,许多人在不想要纹理时会使用单个像素的白色纹理。这样他们只需要1个着色器来覆盖这两种情况。着色器可能看起来像这样

uniform vec4 u_color;
uniform sampler2D u_texture;

varying vec2 v_texCoord;

void main(void) {
  gl_FragColor = texture2D(u_texture, v_texCoord) * u_color;
}

现在,在您的代码中,您可以像这样绘制纹理

// at init time.
var whiteColor = new Float32Array([1, 1, 1, 1]);

// at draw time
gl.uniform4fv(u_colorLocation, whiteColor);  // use white color
gl.bindTexture(gl.TEXTURE_2D, someTexture);  // and some texture
... draw ...

要绘制无纹理,你可以这样做

// at init time.
var whiteTexture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, whiteTexture);
var whitePixel = new Uint8Array([255, 255, 255, 255]);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, 
              gl.RGBA, gl.UNSIGNED_BYTE, whitePixel);


// at draw time
gl.uniform4fv(u_colorLocation, someColor);  // use the color I want
gl.bindTexture(gl.TEXTURE_2D, whiteTexture);  // use the white texture
... draw ...

这也使您能够通过一起使用非白色和纹理来着色纹理。

答案 1 :(得分:3)

我认为在确定问题之前我们可能需要查看更多代码。例如,您的顶点着色器是什么样的,以及如何链接它们?

与此同时,我可以向您提供有关您发布的着色器的几点建议。首先,它不会给你你所描述的效果。实际发生的是,它将始终显示纹理颜色,或者,如果没有给出纹理,则显示黑色。顶点颜色永远不会显示。这是因为您要将最终片段颜色分配两次,第二次分配始终覆盖第一次。

您可能想要尝试的是通过添加或乘以颜色和纹理值将两个值混合在一起。尝试这样的事情:

gl_FragColor = vColor + texture2D(uSampler, vTextureCoord);

唯一的问题是如果纹理是空的,你仍然会变黑(任何乘以0的东西仍然是0)。为避免这种情况,如果您没有可用的实际纹理,请始终使用纯白色纹理。

如果您想要所描述的精确效果(仅在没有纹理时使用顶点颜色),您可能需要使用条件语句。这些通常是最好的避免,但我怀疑你的用法会非常重。

此外,作为样式提示,以下行是等效的:

vec2(vTextureCoord.s, vTextureCoord.t)
vTextureCoord.st

然而,第二个可能更快,应该是首选。但是,除此之外,你可以直接传递vTextureCoord(就像我展示的那样),因为它已经 一个vec2。