我目前正在学习webgl并有一个问题。 我正在尝试制作一个三角形并将颜色信息从js文件传递到片段着色器。以下是我的js代码。
var VSHADER_SOURCE =
'attribute vec4 a_Position;\n'+
'attribute vec4 a_Color;\n'+
'varying vec4 v_Color;\n'+
'void main(){\n'+
'gl_Position = a_Position;\n'+
'v_Color = a_Color;\n'+
'}\n';
var FSHADER_SOURCE =
'precision highp float;\n'+
'varying vec4 v_Color;\n'+
'void main() {\n'+
'gl_FragColor = v_Color;\n'+
'}\n';
function main(){
var canvas = document.getElementById('webgl');
var gl = getWebGLContext(canvas);
if(!gl){
console.log('Error!');
return;
}
//Init shaders.
if(!initShaders(gl, VSHADER_SOURCE, FSHADER_SOURCE)){
console.log('Error!');
return;
}
var vertices = new Float32Array([-0.8, -0.8, 0.8, -0.8, 0.0, 0.8]);
var color = new Float32Array([0.0, 0.0, 1.0, 1.0]);
var buffer_object = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer_object);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
var a_Position = gl.getAttribLocation(gl.program, 'a_Position');
gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Position);
var color_object = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, color_object);
gl.bufferData(gl.ARRAY_BUFFER, color, gl.STATIC_DRAW);
var a_Color = gl.getAttribLocation(gl.program, 'a_Color');
gl.vertexAttribPointer(a_Color, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(a_Color);
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.TRIANGLES, 0, 3);
return 0;
}
这必须创建一个蓝色三角形,但我唯一看到的是一个充满黑色的帆布。任何人都可以告诉我缺少什么?我创建了两个缓冲区对象,其中一个用于顶点,另一个用于颜色。
答案 0 :(得分:4)
你的例子有很多问题,但......具体问题。
您只为第一个顶点提供颜色。
你有3个顶点但只有1个颜色。你应该得到一个错误。 您是否检查过JavaScript控制台是否存在错误?
您有3个选项可以修复
为每个顶点提供颜色
new Float32Array([
0.0, 0.0, 1.0, 1.0,
0.0, 0.0, 1.0, 1.0,
0.0, 0.0, 1.0, 1.0,
]);
关闭a_Color属性并提供常量值
gl.disableVertexAtttibArray(a_Color);
gl.vertexAttrib4f(a_Color, 0, 0, 1, 1);
使用制服代替属性+变化
删除a_Color
和v_color
的所有引用,而不是您的。{
片段着色器
precision highp float;
uniform vec4 u_Color;
void main() {
gl_FragColor = u_Color;
}
现在你用
设置颜色在初始时
// Lookup the location
var u_colorLocation = gl.getUniformLocation(program, "u_Color");
在渲染时间
// Set the uniform
gl.uniform4f(u_colorLocation, 0, 0, 1, 1);
如果你选择#2,你可能会遇到另一个问题,你会收到一个警告,即没有启用attirbute 0,因为至少在我的电脑上,a_Color
被分配给属性0。 off意味着它必须被模拟,这是缓慢的。解决方案是通过在链接程序之前调用a_Position
来确保gl.bindAttribLocation
位于属性0中。
其他问题:
您的initShader
函数显然正在创建一个程序并将其附加到WebGLRenderContext(gl.program
)。大多数WebGL项目都有许多着色器程序,因此最好只返回程序。换句话说,而不是
initShader(...);
gl.getAttribLocation(gl.program, ...)
你可能想要
var program = initShader(...);
gl.getAttribLocation(program, ...)
您需要修复initShader,以便返回已创建的程序,而不是将其攻击到WebGLRenderingContext。
您还在使用precision highp float
。这对许多手机都不起作用。除非您确定需要highp
,否则最好使用mediump
。