我正在学习如何在Webgl中使用canvas,但我对纹理有一些问题。我想画一个立方体,一个球体,一个轴和一个网格。如果我只添加球体,轴和网格,一切都很完美但是当我将立方体添加到场景时,网格消失并向我显示此错误:
drawElements中的WebGL错误INVALID_OPERATION(TRIANGLES,357,UNSIGNED_SHORT,0) [.WebGLRenderingContext] GL错误:GL_INVALID_OPERATION:glDrawElements:尝试访问属性2中超出范围的顶点。
这是我的渲染类:
define([
'text!shaders/vertex-shader.glsl',
'text!shaders/fragment-shader.glsl',
'./Ejes',
'./Mesh',
'glMatrix',
'CuonUtils'], function(vsSource, fsSource,Ejes,Mesh,glMatrix, CuonUtils) {
var canvas = document.getElementById('canvas');
var gl = CuonUtils.getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
// Initialize shaders
if (!CuonUtils.initShaders(gl, vsSource, fsSource)) {
console.log('Failed to intialize shaders.');
return;
}
var program = gl.program;
// Cache attribute/uniform location
var aPostion = gl.getAttribLocation(program, 'aPostion');
var aNormal = gl.getAttribLocation(program, 'aNormal');
var aTexCoord = gl.getAttribLocation(program, 'aTexCoord');
var uModelMatrix = gl.getUniformLocation(program, 'uModelMatrix');
var uViewMatrix = gl.getUniformLocation(program, 'uViewMatrix');
var uProjectionMatrix = gl.getUniformLocation(program, 'uProjectionMatrix');
var uNormalMatrix = gl.getUniformLocation(program, 'uNormalMatrix');
var uLightColor = gl.getUniformLocation(program, 'uLightColor');
var uLightPosition = gl.getUniformLocation(program, 'uLightPosition');
var uAmbientLight = gl.getUniformLocation(program, 'uAmbientLight');
var uColor = gl.getUniformLocation(program, 'uColor');
var uSampler = gl.getUniformLocation(program, 'uSampler');
var uUseLighting = gl.getUniformLocation(program, 'uUseLighting');
var uUseTexture = gl.getUniformLocation(program, 'uUseTexture');
function initBuffers(gl, mesh){
if(mesh._webgl){
return;
}
mesh._webgl = {};
// Create Vertex Buffer Object
var VBOData = new Float32Array(
mesh.geometry.vertices);
var VBO = mesh._webgl.vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, VBO);
gl.bufferData(gl.ARRAY_BUFFER, VBOData, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
// Create Index Buffer Object
var IBOData = new Uint16Array(
mesh.geometry.faces);
var IBO = mesh._webgl.ibo = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, IBO);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, IBOData, gl.STATIC_DRAW);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
mesh._webgl.ibo.dataSize = IBOData.length;
// Create Normal Buffer Object
var NBOData = new Float32Array(
mesh.geometry.normals);
var NBO = mesh._webgl.nbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, NBO);
gl.bufferData(gl.ARRAY_BUFFER, NBOData, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
if(mesh.useTexture){
// Create st Buffer Object
var STBOData = new Float32Array(
mesh.geometry.st);
var STBO = mesh._webgl.stbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, STBO);
gl.bufferData(gl.ARRAY_BUFFER, STBOData, gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
var TBO = mesh._webgl.tbo = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, TBO);
gl.texImage2D(
gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE,
new Uint8Array([255, 255, 255, 255])
);
loadTexture(gl, mesh.imgSrc, mesh._webgl.tbo, function() {
bindTextureToSampler(gl, mesh._webgl.tbo);
});
}
}
function render(scene, camera) {
// Specify the color for clearing <canvas>
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.enable(gl.DEPTH_TEST);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// seteo las luces
gl.uniform3fv(uLightColor, scene.pointLight.getLightColor());
gl.uniform3fv(uLightPosition, scene.pointLight.getLightPosition());
gl.uniform3fv(uAmbientLight, scene.ambientLight.getLightColor());
for( var i = 0; i < scene.meshes.length; i++){
var mesh = scene.meshes[i];
initBuffers(gl, mesh);
gl.uniform1i(uUseLighting, mesh.useLight);
gl.uniform1i(uUseTexture, mesh.useTexture);
gl.enableVertexAttribArray(aPostion);
gl.bindBuffer(gl.ARRAY_BUFFER, mesh._webgl.vbo);
gl.vertexAttribPointer(
aPostion, 3, gl.FLOAT, false, 0, 0
);
gl.enableVertexAttribArray(aNormal);
gl.bindBuffer(gl.ARRAY_BUFFER, mesh._webgl.nbo);
gl.vertexAttribPointer(
aNormal, 3, gl.FLOAT, false, 0, 0
);
// Clean up
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.uniformMatrix4fv(uModelMatrix, false, mesh.getModelMatrix());
gl.uniformMatrix4fv(uViewMatrix, false, camera.getViewMatrix());
gl.uniformMatrix4fv(uProjectionMatrix, false, camera.getProjectionMatrix());
gl.uniformMatrix4fv(uNormalMatrix, false, mesh.getNormalMatrix());
gl.uniform4fv(uColor, mesh.material.getColor());
if(mesh.useTexture){
gl.enableVertexAttribArray(aTexCoord);
gl.bindBuffer(gl.ARRAY_BUFFER, mesh._webgl.stbo);
gl.vertexAttribPointer(
aTexCoord, 2, gl.FLOAT, false, 0, 0
);
gl.bindBuffer(gl.ARRAY_BUFFER, null);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, mesh._webgl.tbo);
gl.uniform1i(uSampler, 0);
}
draw(gl,mesh);
}
}
function loadTexture(gl, imageSrc, textureBO, callback) {
var image = new Image();
image.src = imageSrc;
image.onload = function () {
gl.bindTexture(gl.TEXTURE_2D, textureBO);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
setupTexture(image.width, image.height);
gl.bindTexture(gl.TEXTURE_2D, null);
callback();
};
}
function bindTextureToSampler(gl, textureBO) {
gl.bindTexture(gl.TEXTURE_2D, textureBO);
gl.uniform1i(uSampler, 0);
}
function setupTexture(width, height) {
if (isPowerOf2(width) && isPowerOf2(height) ){
// the dimensions are power of 2 so generate mips and turn on
// tri-linear filtering.
gl.generateMipmap(gl.TEXTURE_2D);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
} else {
// at least one of the dimensions is not a power of 2 so set the filtering
// so WebGL will render it.
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
}
}
function isPowerOf2(value) {
return (value & (value - 1)) === 0;
}
function draw(gl, mesh) {
// gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, mesh._webgl.ibo);
gl.drawElements(mesh.tipe, mesh._webgl.ibo.dataSize, gl.UNSIGNED_SHORT, 0);
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
gl.bindTexture(gl.TEXTURE_2D, null);
}
return {
render: render
};
});
这是我的主要课程:
define([
'./WebGLRenderer',
'./Scene',
'./Mesh',
'./Geometry',
'./Material',
'./RegularConvexPolygonGeometry',
'./Cubo',
'./Sphere',
'./Cylinder',
'./PerspectiveCamera',
'./OrthographicCamera',
'./Light',
'./PointLight',
'./Ejes',
'dat',
'./cuadrado',
'CuonUtils'
], function(WebGLRenderer, Scene, Mesh, Geometry, Material,
RegularConvexPolygonGeometry, Cubo, Sphere, Cylinder,
PerspectiveCamera, OrthographicCamera, Light, PointLight,
Ejes, dat, Cuadrado, CuonUtils) {
var canvas = document.getElementById('canvas');
var gl = CuonUtils.getWebGLContext(canvas);
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
////////////
// ESCENA //
////////////
var clearColor = [0.0,0.0,0.0];
//Ambient Light
var light = Object.create(Light);
light.init();
light.hex = Math.floor( 0xaaaaaa );
//Point Light
var pointLight = Object.create(PointLight);
pointLight.init();
var scene = Object.create(Scene);
scene.init(clearColor, light, pointLight);
//////////
// EJES //
//////////
//GRID
var GrillaGeometry = Object.create(Ejes);
GrillaGeometry.getGrillaGeometry();
var grillaMaterial = Object.create(Material);
grillaMaterial.init();
grillaMaterial.hex = Math.floor( 0x0f0f0f );
var GrillaMesh = Object.create(Mesh);
GrillaMesh.init(GrillaGeometry,grillaMaterial);
GrillaMesh.tipe = gl.LINES;
GrillaMesh.useLight = false;
GrillaMesh.useTexture = false;
//X
var EjeXGeometry = Object.create(Ejes);
EjeXGeometry.getXGeometry();
var EjeXMaterial = Object.create(Material);
EjeXMaterial.init();
EjeXMaterial.hex = Math.floor( 0xff0000 );
var EjeXMesh = Object.create(Mesh);
EjeXMesh.init(EjeXGeometry,EjeXMaterial);
EjeXMesh.tipe = gl.LINES;
EjeXMesh.useLight = false;
EjeXMesh.useTexture = false;
//Y
var EjeYGeometry = Object.create(Ejes);
EjeYGeometry.getYGeometry();
var EjeYMaterial = Object.create(Material);
EjeYMaterial.init();
EjeYMaterial.hex = Math.floor( 0x00ff00 );
var EjeYMesh = Object.create(Mesh);
EjeYMesh.init(EjeYGeometry,EjeYMaterial);
EjeYMesh.tipe = gl.LINES;
EjeYMesh.useLight = false;
EjeYMesh.useTexture = false;
//Z
var EjeZGeometry = Object.create(Ejes);
EjeZGeometry.getZGeometry();
var EjeZMaterial = Object.create(Material);
EjeZMaterial.init();
EjeZMaterial.hex = Math.floor( 0x0000ff );
var EjeZMesh = Object.create(Mesh);
EjeZMesh.init(EjeZGeometry,EjeZMaterial);
EjeZMesh.tipe = gl.LINES;
EjeZMesh.useLight = false;
EjeZMesh.useTexture = false;
scene.addMesh(GrillaMesh);
scene.addMesh(EjeXMesh);
scene.addMesh(EjeYMesh);
scene.addMesh(EjeZMesh);
////////////////
// ESFERA //
////////////////
var sphereGeometry = Object.create(Sphere);
sphereGeometry.init();
var sphereMaterial = Object.create(Material);
sphereMaterial.init();
sphereMaterial.hex = Math.floor( 0xffffff );
var sphereMesh = Object.create(Mesh);
sphereMesh.init(sphereGeometry,sphereMaterial);
sphereMesh.tipe = gl.TRIANGLES;
sphereMesh.tx = 5.0;
sphereMesh.useLight = true;
sphereMesh.useTexture = true;
sphereMesh.imgSrc = 'scripts/texture/earthmap.jpg';
scene.addMesh(sphereMesh);
////////////////
// CUBO //
////////////////
var cubeGeometry = Object.create(Cubo);
cubeGeometry.init();
var cubeMaterial = Object.create(Material);
cubeMaterial.init();
cubeMaterial.hex = Math.floor( 0xffffff );
var cubeMesh = Object.create(Mesh);
cubeMesh.init(cubeGeometry,cubeMaterial);
cubeMesh.tipe = gl.TRIANGLES;
cubeMesh.tz = 5.0;
cubeMesh.useLight = true;
cubeMesh.useTexture = true;
cubeMesh.imgSrc = 'scripts/texture/firefox-icon3.png';
scene.addMesh(cubeMesh);
//////////////////////////////
/// PERSPECTIVE PROJECTION ///
//////////////////////////////
// var camera = Object.create(PerspectiveCamera);
// PerspectiveCamera.init(Math.PI / 4,1,0.1,200);
///////////////////////////////
/// ORTHOGRAPHIC PROJECTION ///
///////////////////////////////
var camera = Object.create(OrthographicCamera);
OrthographicCamera.init(-8,8,-8,8,0.1,1000);
function tick(){
WebGLRenderer.render(scene, camera);
requestAnimationFrame(tick);
}
tick();
});
我几乎可以肯定问题是我的渲染类,但万一我也会发布其他类。
立方体:
define(['glMatrix','./Geometry'], function(glMatrix, Geometry) {
var Cubo = Object.create(Geometry);
Cubo.init = function(){
var vertices = new Float32Array([
1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0,-1.0, 1.0, 1.0,-1.0, 1.0, // v0-v1-v2-v3 front
1.0, 1.0, 1.0, 1.0,-1.0, 1.0, 1.0,-1.0,-1.0, 1.0, 1.0,-1.0, // v0-v3-v4-v5 right
1.0, 1.0, 1.0, 1.0, 1.0,-1.0, -1.0, 1.0,-1.0, -1.0, 1.0, 1.0, // v0-v5-v6-v1 up
-1.0, 1.0, 1.0, -1.0, 1.0,-1.0, -1.0,-1.0,-1.0, -1.0,-1.0, 1.0, // v1-v6-v7-v2 left
-1.0,-1.0,-1.0, 1.0,-1.0,-1.0, 1.0,-1.0, 1.0, -1.0,-1.0, 1.0, // v7-v4-v3-v2 down
1.0,-1.0,-1.0, -1.0,-1.0,-1.0, -1.0, 1.0,-1.0, 1.0, 1.0,-1.0 // v4-v7-v6-v5 back
]);
//Creo las caras
var indexVertices = new Uint16Array([
0, 1, 2, 0, 2, 3, // front
4, 5, 6, 4, 6, 7, // right
8, 9,10, 8,10,11, // up
12,13,14, 12,14,15, // left
16,17,18, 16,18,19, // down
20,21,22, 20,22,23 // back
]);
//Normales
var normales = new Float32Array([
0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, // v0-v1-v2-v3 front
1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, // v0-v3-v4-v5 right
0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, // v0-v5-v6-v1 up
-1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, // v1-v6-v7-v2 left
0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, // v7-v4-v3-v2 down
0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0, 0.0, 0.0,-1.0 // v4-v7-v6-v5 back
]);
var st = new Float32Array([
// Front
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// Back
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// Top
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// Bottom
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// Right
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0,
// Left
0.0, 0.0,
1.0, 0.0,
1.0, 1.0,
0.0, 1.0
]);
Geometry.init.call(this, vertices, indexVertices, normales, st);
};
return Cubo;
});
sphere:
define(['./Geometry'], function(Geometry) {
var Sphere = Object.create(Geometry);
Sphere.init = function(){
var SPHERE_DIV = 13;
var i, ai, si, ci;
var j, aj, sj, cj;
var p1, p2;
var vertices = [];
var indexVertices = [];
var st = [];
//Creo los vertices
for (j = 0; j <= SPHERE_DIV; j++) {
aj = j * Math.PI / SPHERE_DIV;
sj = Math.sin(aj);
cj = Math.cos(aj);
for (i = 0; i <= SPHERE_DIV; i++) {
ai = i * 2 * Math.PI / SPHERE_DIV;
si = Math.sin(ai);
ci = Math.cos(ai);
vertices.push(si * sj); // X
vertices.push(cj); // Y
vertices.push(ci * sj); // Z
st.push(1 - (i / SPHERE_DIV) );
st.push(1 - (j / SPHERE_DIV) );
}
}
//Creo los indices
for (j = 0; j < SPHERE_DIV; j++) {
for (i = 0; i < SPHERE_DIV; i++) {
p1 = j * (SPHERE_DIV+1) + i;
p2 = p1 + (SPHERE_DIV+1);
indexVertices.push(p1);
indexVertices.push(p2);
indexVertices.push(p1 + 1);
indexVertices.push(p1 + 1);
indexVertices.push(p2);
indexVertices.push(p2 + 1);
}
}
Geometry.init.call(this, vertices, indexVertices, vertices, st);
};
return Sphere;
});
网格:
define(['./Geometry'], function(Geometry) {
var Ejes = Object.create(Geometry);
Ejes.getXGeometry = function(){
var vertices = [];
var indexVertices = [];
var st = [];
vertices.push(0.0,0.0,0.0);
vertices.push(10.0,0.0,0.0);
indexVertices.push(0,1);
Geometry.init.call(this,vertices,indexVertices, vertices, st);
};
Ejes.getYGeometry = function(){
var vertices = [];
var indexVertices = [];
var st = [];
vertices.push(0.0,0.0,0.0);
vertices.push(0.0,10.0,0.0);
indexVertices.push(0,1);
Geometry.init.call(this,vertices,indexVertices, vertices, st);
};
Ejes.getZGeometry = function(){
var vertices = [];
var indexVertices = [];
var st = [];
vertices.push(0.0,0.0,0.0);
vertices.push(0.0,0.0,10.0);
indexVertices.push(0,1);
Geometry.init.call(this,vertices,indexVertices,vertices, st);
};
Ejes.getGrillaGeometry = function(){
var vertices = [];
var indexVertices = [];
var st = [];
for(var i=-10; i<0; i+=1)
{
// verticales
vertices.push(i,0,-10);
vertices.push(i,0,10);
// horizontales
vertices.push(-10,0,i);
vertices.push(10,0,i);
}
vertices.push(0,0,-10);
vertices.push(0,0,0);
vertices.push(-10,0,0);
vertices.push(0,0,0);
for(i=1; i<=10; i+=1)
{
// verticales
vertices.push(i,0,-10);
vertices.push(i,0,10);
// horizontales
vertices.push(-10,0,i);
vertices.push(10,0,i);
}
for(i=0; i<84;i+=1)
{
indexVertices.push(i);
}
Geometry.init.call(this,vertices,indexVertices,vertices, vertices);
};
return Ejes;
});
我真的很感激你能给我的任何帮助。