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

问题描述:

我正在学习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)); 
} 

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

+0

请同时发布您的JavaScript代码。你如何初始化纹理和其他? – datenwolf 2011-12-18 16:28:52

+0

我试图在[lession4](http://learningwebgl.com/blog/?p=370)中添加一个纹理立方体(来自lession5) – 2011-12-18 18:29:39

这可能会也可能没有意义,但是否具有纹理或不需要不同的着色器。为了解决这个问题,许多人在不需要纹理时使用单像素白色纹理。这样他们只需要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 ... 

这也使您可以通过使用非白色和纹理一起给您的纹理着色。

我想我们可能需要看一些更多的代码,然后才能帮助您找出确切的问题。例如,顶点着色器是什么样的,你如何链接它们?

与此同时,我可以给你一些关于你发布的着色器的指针。首先,它不会给你所描述的效果。实际发生的事情是,它将始终显示纹理颜色,或者如果未指定纹理,则显示为黑色。顶点颜色永远不会显示。这是因为您将分配给最终的片段颜色两次,第二次分配总是覆盖第一个。

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

gl_FragColor = vColor + texture2D(uSampler, vTextureCoord); 

存在,如果纹理是空的,你仍然会得到黑色的唯一问题(什么乘以0仍然为0)。为避免这种情况,如果没有可用的实际纹理,请始终使用纯白色纹理。

如果您想要描述确切的效果(只有在没有纹理的情况下才使用顶点颜色),则可能需要使用条件语句。这些通常是最好的避免,但我怀疑你的使用会是非常沉重的。

另外,作为式尖端,以下行是等效的:

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

第二可能更快,但是,应该是首选。然而,除此之外,你可以直接通过vTextureCoord(如我所示),因为它已经是 a vec2。