我想從model.json文件中繪製3d模型(例如房子)。我沒有問題像藍色一樣用一種顏色畫房子。然而,當我嘗試使用,而不是顏色紋理,我收到一個錯誤:WebGL:添加紋理會導致DrawElements錯誤(屬性緩衝區空間不足)
WebGL: DrawElements: bound vertex attribute buffers do not have sufficient size for given indices from the bound element array
我在網上搜索,並嘗試數百種不同的變化,我根本無法突破這個錯誤 - 我沒有足夠的WebGL來看看有什麼不對。有一個包含多個紋理圖像的圖像文件夾,但在這一點上,如果我可以爲整個房子畫一個紋理,我會欣喜若狂。
問題在於renderable.js(附後),但你可以在http://tinyurl.com/mk9vbta訪問所有文件。任何幫助將不勝感激,不知道要去哪裏。
renderable.js
"use strict";
function RenderableModel(gl,model){
function Drawable(attribLocations, vArrays, nVertices, indexArray, drawMode){
// Create a buffer object
var vertexBuffers=[];
var nElements=[];
var nAttributes = attribLocations.length;
for (var i=0; i<nAttributes; i++){
if (vArrays[i]){
vertexBuffers[i] = gl.createBuffer();
if (!vertexBuffers[i]) {
console.log('Failed to create the buffer object');
return null;
}
// Bind the buffer object to an ARRAY_BUFFER target
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffers[i]);
// Write date into the buffer object
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vArrays[i]), gl.STATIC_DRAW);
// Texture coords must always be passed as last attribute location (a_Attribute)
nElements[i] = (i == (nAttributes - 1))? 2: vArrays[i].length/nVertices;
}
else{
vertexBuffers[i]=null;
}
}
var indexBuffer=null;
if (indexArray){
indexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indexArray), gl.STATIC_DRAW);
}
var a_texture = createTexture("texture0.jpg");
// Set the texture unit 0 to the sampler
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, a_texture);
this.draw = function(){
nElements[1] = 2;
for (var i=0; i<nAttributes; i++){
if (vertexBuffers[i]){
gl.enableVertexAttribArray(attribLocations[i]);
// Bind the buffer object to target
gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffers[i]);
// Assign the buffer object to a_Position variable
gl.vertexAttribPointer(attribLocations[i], nElements[i], gl.FLOAT, false, 24, 0);
}
else{
gl.disableVertexAttribArray(attribLocations[i]);
gl.vertexAttrib3f(attribLocations[i],1,1,1);
//console.log("Missing "+attribLocations[i])
}
}
if (indexBuffer){
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
gl.drawElements(drawMode, indexArray.length, gl.UNSIGNED_SHORT, 0);
}
else{
gl.drawArrays(drawMode, 0, nVertices);
}
}
}
// Vertex shader program
var VSHADER_SOURCE =
'attribute vec2 textureCoord;\n' +
'attribute vec3 position;\n' +
'uniform mat4 modelT, viewT, projT;\n'+
//'varying vec4 v_Color;\n' +
'varying highp vec2 vTextureCoord;\n' +
'void main() {\n' +
' gl_Position = projT*viewT*modelT*vec4(position,1.0);\n' +
//' v_Color = vec4(0, 1.0, 0.0, 1.0);\n' + // use instead of textures for now
' vTextureCoord = textureCoord;\n' +
'}\n';
// Fragment shader program
var FSHADER_SOURCE =
'#ifdef GL_ES\n' +
'precision highp float;\n' +
'#endif\n' +
'uniform sampler2D uSampler;\n' +
//'varying vec4 v_Color;\n' + // use instead of texture
'varying highp vec2 vTextureCoord;\n' +
'void main() {\n' +
// 'vec4 v_Color = vec4(texture2D(uSampler, vTextureCoord).rgb, 1.0);\n'+
' gl_FragColor = texture2D(uSampler, vTextureCoord);\n' +
'}\n';
// create program
var program = createProgram(gl, VSHADER_SOURCE, FSHADER_SOURCE);
if (!program) {
console.log('Failed to create program');
return false;
}
var a_Position = gl.getAttribLocation(program, 'position');
var a_TextureCoord = gl.getAttribLocation(program, 'textureCoord'); // for texture
var a_Locations = [a_Position,a_TextureCoord];
// Get the location/address of the uniform variable inside the shader program.
var mmLoc = gl.getUniformLocation(program,"modelT");
var vmLoc = gl.getUniformLocation(program,"viewT");
var pmLoc = gl.getUniformLocation(program,"projT");
// textures
var textureLoc = gl.getUniformLocation(program,'uSampler');
var drawables=[];
var modelTransformations=[];
var nDrawables=0;
var nNodes = (model.nodes)? model.nodes.length:1;
var drawMode=(model.drawMode)?gl[model.drawMode]:gl.TRIANGLES;
for (var i= 0; i<nNodes; i++){
var nMeshes = (model.nodes)?(model.nodes[i].meshIndices.length):(model.meshes.length);
for (var j=0; j<nMeshes;j++){
var index = (model.nodes)?model.nodes[i].meshIndices[j]:j;
var mesh = model.meshes[index];
drawables[nDrawables] = new Drawable(
a_Locations,[mesh.vertexPositions, mesh.vertexTexCoordinates],
mesh.vertexPositions.length/3,
mesh.indices, drawMode
);
var m = new Matrix4();
if (model.nodes)
m.elements=new Float32Array(model.nodes[i].modelMatrix);
modelTransformations[nDrawables] = m;
nDrawables++;
}
}
// Get the location/address of the vertex attribute inside the shader program.
this.draw = function (cameraPosition,pMatrix,vMatrix,mMatrix)
{
gl.useProgram(program);
gl.uniformMatrix4fv(pmLoc, false, pMatrix.elements);
gl.uniformMatrix4fv(vmLoc, false, vMatrix.elements);
gl.uniform1i(textureLoc, 0);
// pass variables determined at runtime
for (var i= 0; i<nDrawables; i++){
// pass model matrix
var mMatrix=modelTransformations[i];
gl.uniformMatrix4fv(mmLoc, false, mMatrix.elements);
drawables[i].draw();
}
gl.useProgram(null);
}
this.getBounds=function() // Computes Model bounding box
{
var xmin, xmax, ymin, ymax, zmin, zmax;
var firstvertex = true;
var nNodes = (model.nodes)?model.nodes.length:1;
for (var k=0; k<nNodes; k++){
var m = new Matrix4();
if (model.nodes)m.elements=new Float32Array(model.nodes[k].modelMatrix);
//console.log(model.nodes[k].modelMatrix);
var nMeshes = (model.nodes)?model.nodes[k].meshIndices.length:model.meshes.length;
for (var n = 0; n < nMeshes; n++){
var index = (model.nodes)?model.nodes[k].meshIndices[n]:n;
var mesh = model.meshes[index];
for(var i=0;i<mesh.vertexPositions.length; i+=3){
var vertex = m.multiplyVector4(new Vector4([mesh.vertexPositions[i],mesh.vertexPositions[i+1],mesh.vertexPositions[i+2],1])).elements;
//if (i==0){
// console.log([mesh.vertexPositions[i],mesh.vertexPositions[i+1],mesh.vertexPositions[i+2]]);
// console.log([vertex[0], vertex[1], vertex[2]]);
//}
if (firstvertex){
xmin = xmax = vertex[0];
ymin = ymax = vertex[1];
zmin = zmax = vertex[2];
firstvertex = false;
}
else{
if (vertex[0] < xmin) xmin = vertex[0];
else if (vertex[0] > xmax) xmax = vertex[0];
if (vertex[1] < ymin) ymin = vertex[1];
else if (vertex[1] > ymax) ymax = vertex[1];
if (vertex[2] < zmin) zmin = vertex[2];
else if (vertex[2] > zmax) zmax = vertex[2];
}
}
}
}
var dim= {};
dim.min = [xmin,ymin,zmin];
dim.max = [xmax,ymax,zmax];
//console.log(dim);
return dim;
}
// Load texture image and create/return texture object
function createTexture(imageFileName)
{
var tex = gl.createTexture();
var img = new Image();
img.onload = function(){
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL,true);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, img);
gl.bindTexture(gl.TEXTURE_2D, null);
}
img.src = imageFileName;
return tex;
}
}
** + 1 **:但值得一提的是,這種行爲特定於WebGL,這是一個額外的安全特性[here](http://www.khronos.org/registry/webgl/specs/latest /1.0/#4.5)。在OpenGL和OpenGL ES中,使用超出範圍的索引是未定義的行爲,即使使用調試輸出擴展,大多數驅動程序(我知道)都不會在發生這種情況時進行報告。 –
如果我有足夠的可信度,我會+1!非常感謝。我回去檢查每個屬性數組的長度,並注意到textureCoordinate數組爲1。所以我看着模型文件,注意到我得到的vertexTextureCoordinates值是一個二維數組 - 我認爲這是因爲模型文件在同一個網格上考慮了多個紋理的可能性。謝謝gman。問題解決了。 –