const canvas = document.getElementById('canvas');
const gl = canvas.getContext('webgl');
if (!gl) {
alert('您的浏览器不支持 WebGL!');
throw new Error('WebGL 初始化失败');
}
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(0.1, 0.1, 0.1, 1.0);
const vsSource = `
attribute vec2 aPosition; // 2D 位置 (x, y)
attribute vec3 aColor; // 颜色 (r, g, b)
varying vec3 vColor;
void main() {
gl_Position = vec4(aPosition, 0.0, 1.0);
vColor = aColor;
}
`;
const fsSource = `
precision mediump float;
varying vec3 vColor;
void main() {
gl_FragColor = vec4(vColor, 1.0);
}
`;
function loadShader(gl, type, source) {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
console.error('着色器编译错误:', gl.getShaderInfoLog(shader));
gl.deleteShader(shader);
return null;
}
return shader;
}
const vertexShader = loadShader(gl, gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl, gl.FRAGMENT_SHADER, fsSource);
const program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
console.error('程序链接失败:', gl.getProgramInfoLog(program));
}
gl.useProgram(program);
const vertices = new Float32Array([
-0.2, 0.0, 1.0, 0.0, 0.0,
-0.8, -0.5, 0.0, 1.0, 0.0,
-0.8, 0.5, 0.0, 0.0, 1.0,
0.8, -0.5, 1.0, 1.0, 0.0,
0.8, 0.5, 1.0, 0.0, 1.0
]);
const indices = new Uint16Array([
0, 1, 2,
0, 3, 4
]);
const vertexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW);
const indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW);
const aPosition = gl.getAttribLocation(program, 'aPosition');
const aColor = gl.getAttribLocation(program, 'aColor');
const stride = (2 + 3) * 4;
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, stride, 0);
gl.enableVertexAttribArray(aPosition);
gl.vertexAttribPointer(aColor, 3, gl.FLOAT, false, stride, 2 * 4);
gl.enableVertexAttribArray(aColor);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawElements(
gl.TRIANGLES,
indices.length,
gl.UNSIGNED_SHORT,
0
);
console.log('✅ 绘制完成:使用 5 个顶点和索引缓存绘制了两个不重叠且共用顶点的三角形。');
const vertexSizeBytes = (positionComponents + colorComponents + ...) * Float32Array.BYTES_PER_ELEMENT;
gl.vertexAttribPointer(posLoc, positionComponents, gl.FLOAT, false, vertexSizeBytes, 0);
const colorOffsetBytes = positionComponents * Float32Array.BYTES_PER_ELEMENT;
gl.vertexAttribPointer(colorLoc, colorComponents, gl.FLOAT, false, vertexSizeBytes, colorOffsetBytes);