您需要致电gl.shaderSource(shader, source) 上传您的 GLSL 源代码。然后您需要调用gl.compileShader(shader) 来编译着色器。之后您可以拨打gl.getShaderParameter(shader, gl.COMPILE_SHADER) 来检查是否成功。此外,在编译着色器后,您可以调用 gl.getShaderInfoLog(shader) 从 GPU 驱动程序/浏览器获取任何消息。
注意:根据 OpenGL 规范,着色器可以始终声称编译成功,只要它们在无效时仍然无法链接。
这意味着您还应该始终将着色器链接到程序并检查程序的LINK_STATUS 和程序信息日志
var program = gl.createProgram();
gl.attachShader(program, vShaderInfo.shader);
gl.attachShader(program, fShaderInfo.shader);
gl.linkProgram(program);
console.log("link success:", gl.getProgramParameter(program, gl.LINK_STATUS));
console.log("log:", gl.getProgramInfoLog(program));
您需要致电gl.getProgramInfoLog 不 gl.getShaderInfoLog 以获取链接错误。
运行查看错误
var gl = document.createElement("canvas").getContext("webgl");
function makeShader(type) {
if (type == 'x-fragment') {
str = "#ifdef GL_ES\n" +
"precision highp float;\n" +
"#endif\n" +
"varying vec2 vTextureCoord;\n" +
"uniform sampler2D uSampler;\n" +
"uniform int uDrawColourMap;\n" +
"uniform int hasTexture;\n" +
"uniform vec4 uColourMapColour;\n" +
"varying vec4 vColourAttribute;\n" +
"void main(void) {\n" +
"if (uDrawColourMap == 1) {\n" +
" gl_FragColor = uColourMapColour;\n" +
" return;\n" +
"}\n" +
"if (hasTexture == 1) {\n" +
" gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t));\n" +
"}\n" +
" else {\n" +
" gl_FragColor = vColourAttribute;\n" +
"}\n" +
"}\n";
shader = gl.createShader(gl.FRAGMENT_SHADER);
} else if (type == 'x-vertex') {
str = "attribute vec3 aVertexPosition;\n" +
"attribute vec2 aTextureCoord;\n" +
"attribute vec4 aColourAttribute;\n" +
"uniform mat4 uMVMatrix;\n" +
"uniform int hasTexture;\n" +
"uniform mat4 uPMatrix;\n" +
"varying vec4 vColourAttribute;\n" +
"varying vec2 vTextureCoord;\n" +
"void main(void) {\n" +
" gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0);\n" +
" if (hasTexture == 1) {\n"+
" vTextureCoord = aTextureCoord;\n"+
"}\n"+
" else {\n"+
"vColourAttribute = aColourAttribute;\n"+
"}\n"+
"}\n";
shader = gl.createShader(gl.VERTEX_SHADER);
}
return { shader: shader, src: str };
};
function compileShader(shaderInfo) {
var shader = shaderInfo.shader;
var src = shaderInfo.src;
gl.shaderSource(shader, src);
gl.compileShader(shader);
console.log("compile success:", gl.getShaderParameter(shader, gl.COMPILE_STATUS));
console.log("log:", gl.getShaderInfoLog(shader));
}
var vShaderInfo = makeShader('x-fragment');
var fShaderInfo = makeShader('x-vertex');
compileShader(vShaderInfo);
compileShader(fShaderInfo);
var program = gl.createProgram();
gl.attachShader(program, vShaderInfo.shader);
gl.attachShader(program, fShaderInfo.shader);
gl.linkProgram(program);
console.log("link success:", gl.getProgramParameter(program, gl.LINK_STATUS));
console.log("log:", gl.getProgramInfoLog(program));
上述程序的错误表明您对hasTexture 的统一精度在顶点着色器和片段着色器之间不匹配。 int 的默认值在顶点着色器中为 highp,在片段着色器中为 mediump,因此请更改其中一个。要么放
uniform mediump int hasTexture;
在您的顶点着色器中或
uniform highp int hasTexture;
在您的片段着色器中
或更改为布尔值。
注意:我不得不指出使用标志来选择着色器中的特征是一种反模式。如果在一个着色器中使用标志(最好),您应该考虑使用不同的着色器,或者您至少应该移除标志并设计着色器,以便您可以通过白色。
例子:
gl_FragColor = uColourMapColour *
texture2D(uSampler, vTextureCoord) *
vColourAttribute;
用纯色绘制
- 将
uColourMapColour 设置为您想要的颜色
- 用
gl.disableVertexAttribArray(vColourAttribLocation) 关闭vColourAttribute 的属性,然后用gl.vertexAttrib4fv(vColourAttribLocation, [1, 1, 1, 1]) 将其设置为1;
- 将
uSampler 设置为 1x1 像素的白色纹理
用顶点颜色绘制
- 将
uColourMapColour 设置为 [1, 1, 1, 1])
- 用
gl.enableVertexAttribArray(vColourAttribLocation)打开vColourAttribute的属性并将其指向一些数据(gl.bindBuffer、gl.vertexAttribPointer);
- 将
uSampler 设置为 1x1 像素的白色纹理
使用纹理绘制
- 将
uColourMapColour 设置为 [1, 1, 1, 1])
- 用
gl.disableVertexAttribArray(vColourAttribLocation) 关闭vColourAttribute 的属性,然后用gl.vertexAttrib4fv(vColourAttribLocation, [1, 1, 1, 1]) 将其设置为1;
- 将
uSampler 设置为您的纹理
这还可以让您组合诸如通过设置纹理和 uColourMapColour 以及混合顶点颜色和纹理颜色等来绘制着色纹理等内容。