在尝试创建createRegularPolygon
函数时,我遇到了一个无法让它呈现的问题。它会抛出一个错误,告诉我我试图访问超出范围的顶点。
[.Offscreen-For-WebGL-0x7f8c4a89c400] GL错误:GL_INVALID_OPERATION:glDrawElements:尝试访问属性0中超出范围的顶点
以下是我生成几何体的代码,下面将是整个测试代码。以下代码的某些内容会破坏格式
export const createRegularPolygon =
(gl: WebGLRenderingContext) =>
(position: [number, number], sides: number, radius: number): FlatGeometry | null => {
const points: number[] = [...position, 0];
const indices = [];
let i = -1;
while (++i <= sides) {
const segment = i * 2 * Math.PI / sides;
points.push(
radius * Math.cos(segment) + position[0],
radius * Math.sin(segment) + position[1],
0,
);
}
i = 0;
while (++i <= sides) indices.push(i, i + 1, 0);
const verticiesBufferData = new Float32Array(points);
const verticiesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, verticiesBuffer);
gl.bufferData(
gl.ARRAY_BUFFER,
verticiesBufferData,
gl.STATIC_DRAW,
);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
const indicesBufferData = new Float32Array(indices);
const indicesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer);
gl.bufferData(
gl.ELEMENT_ARRAY_BUFFER,
indicesBufferData,
gl.STATIC_DRAW,
);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
if (!verticiesBuffer || !indicesBuffer) return null;
return {
verticies: verticiesBuffer,
indices: indicesBuffer,
size: indices.length,
};
};
以下是已编译的代码:
(function () {
'use strict';
function reduce(array, func, base) {
let i = -1;
while (++i < array.length)
base = func(base, array[i], i, array);
return base;
}
const map = (array, func) => reduce(array, (result, value, index, array) => add(result, func(value, index, array)), []);
const flatten = (array) => [].concat(...array);
const copy = (array) => array.slice(0);
const add = (array, value, index = 0) => {
const result = copy(array);
result.splice(index, 0, value);
return result;
};
const createTriangle = (gl) => (points) => {
const vertices = flatten(map(points, pnt => [...pnt, 0]));
const vertexBuffer = gl.createBuffer();
if (!vertexBuffer)
return null;
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
const indexBuffer = gl.createBuffer();
if (!indexBuffer)
return null;
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2]), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
return {
verticies: vertexBuffer,
indices: indexBuffer,
size: 3,
};
};
const createRectangle = (gl) => (width, height = width) => {
const vertices = [
-width / 2, height / 2, 0,
width / 2, height / 2, 0,
-width / 2, -height / 2, 0,
width / 2, -height / 2, 0,
];
const vertexBuffer = gl.createBuffer();
if (!vertexBuffer)
return null;
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
const indexBuffer = gl.createBuffer();
if (!indexBuffer)
return null;
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array([0, 1, 2, 1, 3, 2]), gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
return {
verticies: vertexBuffer,
indices: indexBuffer,
size: 6,
};
};
const createRegularPolygon = (gl) => (position, sides, radius) => {
const points = [...position, 0];
const indices = [];
let i = -1;
while (++i <= sides) {
const segment = i * 2 * Math.PI / sides;
points.push(radius * Math.cos(segment) + position[0], radius * Math.sin(segment) + position[1], 0);
}
i = 0;
while (++i <= sides)
indices.push(i, i + 1, 0);
const verticiesBufferData = new Float32Array(points);
const verticiesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, verticiesBuffer);
gl.bufferData(gl.ARRAY_BUFFER, verticiesBufferData, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
const indicesBufferData = new Float32Array(indices);
const indicesBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indicesBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indicesBufferData, gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
if (!verticiesBuffer || !indicesBuffer)
return null;
console.log(verticiesBufferData, indicesBufferData);
return {
verticies: verticiesBuffer,
indices: indicesBuffer,
size: indices.length,
};
};
const draw = (gl) => (shader) => (geometry) => {
gl.useProgram(shader.program);
gl.bindBuffer(gl.ARRAY_BUFFER, geometry.verticies);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, geometry.indices);
gl.vertexAttribPointer(shader.attribLocations.vertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(shader.attribLocations.vertexPosition);
gl.drawElements(gl.TRIANGLES, geometry.size, gl.UNSIGNED_SHORT, 0);
gl.disableVertexAttribArray(shader.attribLocations.vertexPosition);
};
const createShaderLoader = (gl) => (type, source) => {
const shader = gl.createShader(type);
gl.shaderSource(shader, source);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
gl.deleteShader(shader);
return null;
}
return shader;
};
const createShader = (gl) => (vsSource, fsSource) => {
const loadShader = createShaderLoader(gl);
const vertexShader = loadShader(gl.VERTEX_SHADER, vsSource);
const fragmentShader = loadShader(gl.FRAGMENT_SHADER, fsSource);
const shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!shaderProgram || !gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
return null;
}
return {
program: shaderProgram,
attribLocations: {
vertexPosition: gl.getAttribLocation(shaderProgram, 'aVertexPosition'),
},
uniformLocations: {
projectionMatrix: gl.getUniformLocation(shaderProgram, 'uProjectionMatrix'),
modelViewMatrix: gl.getUniformLocation(shaderProgram, 'uModelViewMatrix'),
}
};
};
const vs = `
attribute vec4 aVertexPosition;
void main() {
gl_Position = aVertexPosition;
}
`;
const fs = `
void main() {
gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
}
`;
function main(gl) {
if (!gl)
return false;
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.clearDepth(1.0);
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.LEQUAL);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
const polygonT = createTriangle(gl)([[-1, 1], [-1, -1], [1, -1]]);
const polygonP = createRegularPolygon(gl)([0, 0], 3, 0.5);
const polygonR = createRectangle(gl)(2, 0.25);
const defaultShader = createShader(gl)(vs, fs);
if (!defaultShader || !polygonT || !polygonR || !polygonP)
return false;
[polygonP].forEach(draw(gl)(defaultShader));
return true;
}
const canvas = document.querySelector(`canvas`);
if (canvas) {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const gl = canvas.getContext('webgl');
if (gl)
main(gl);
}
}());
<html>
<style>
html,
body {
width: 100%;
height: 100%;
}
html,
body,
canvas {
padding: 0;
margin: 0;
}
</style>
<body>
<canvas></canvas>
</body>
</html>
答案 0 :(得分:1)
这个错误只是一个错字
const indicesBufferData = new Float32Array(indices);
const indicesBufferData = new Uint16Array(indices);
应该是这个
FROM i386/ubuntu:17.04