在 WebGL 中绘制多个模型
Draw multiple models in WebGL
问题约束:
- 我没有使用 three.js 或类似的,而是纯 WebGL
- WebGL 2 也不是一个选项
我有几个加载的模型存储为 Vertices
和 Normals
数组(来自 STL reader)。
到目前为止,当两个模型大小相同时没有问题。每当我加载 2 个不同的模型时,浏览器中都会显示一条错误消息:
WebGL: INVALID_OPERATION: drawArrays: attempt to access out of bounds arrays
所以我怀疑我没有正确操作多个缓冲区。
使用以下打字稿方法加载模型:
public AddModel(model: Model)
{
this.models.push(model);
model.VertexBuffer = this.gl.createBuffer();
model.NormalsBuffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, model.VertexBuffer);
this.gl.bufferData(this.gl.ARRAY_BUFFER, model.Vertices, this.gl.STATIC_DRAW);
model.CoordLocation = this.gl.getAttribLocation(this.shaderProgram, "coordinates");
this.gl.vertexAttribPointer(model.CoordLocation, 3, this.gl.FLOAT, false, 0, 0);
this.gl.enableVertexAttribArray(model.CoordLocation);
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, model.NormalsBuffer);
this.gl.bufferData(this.gl.ARRAY_BUFFER, model.Normals, this.gl.STATIC_DRAW);
model.NormalLocation = this.gl.getAttribLocation(this.shaderProgram, "vertexNormal");
this.gl.vertexAttribPointer(model.NormalLocation, 3, this.gl.FLOAT, false, 0, 0);
this.gl.enableVertexAttribArray(model.NormalLocation);
}
加载完成后调用Render方法绘制所有加载的模型:
public Render(viewMatrix: Matrix4, perspective: Matrix4)
{
this.gl.uniformMatrix4fv(this.viewRef, false, viewMatrix);
this.gl.uniformMatrix4fv(this.perspectiveRef, false, perspective);
this.gl.uniformMatrix4fv(this.normalTransformRef, false, viewMatrix.NormalMatrix());
// Clear the canvas
this.gl.clearColor(0, 0, 0, 0);
this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
// Draw the triangles
if (this.models.length > 0)
{
for (var i = 0; i < this.models.length; i++)
{
var model = this.models[i];
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, model.VertexBuffer);
this.gl.enableVertexAttribArray(model.NormalLocation);
this.gl.enableVertexAttribArray(model.CoordLocation);
this.gl.vertexAttribPointer(model.CoordLocation, 3, this.gl.FLOAT, false, 0, 0);
this.gl.uniformMatrix4fv(this.modelRef, false, model.TransformMatrix);
this.gl.uniform3fv(this.materialdiffuseRef, model.Color.AsVec3());
this.gl.drawArrays(this.gl.TRIANGLES, 0, model.TrianglesCount);
}
}
}
一个模型工作得很好。两个克隆模型也可以正常工作。不同的模型因提到的错误而失败。
我错过了什么?
WebGL的正常使用方式
在初始时间
每个着色器程序
- 创建并编译顶点着色器
- 创建并编译片段着色器
- 创建程序,附加着色器,link程序
每个模型
- 对于每种类型的顶点数据(位置、法线、颜色、纹理坐标)
- 创建缓冲区
- 复制数据到缓冲区
创建纹理
然后在渲染时
- 每个模型
- 使用适合模型的着色器程序
- 绑定缓冲区、启用和设置属性
- 绑定纹理并设置制服
- 调用 drawArrays 或 drawElements
但是看看你的代码,它是绑定缓冲区,并在初始化时而不是渲染时启用和设置属性。
也许会看到 this article and this one
问题约束:
- 我没有使用 three.js 或类似的,而是纯 WebGL
- WebGL 2 也不是一个选项
我有几个加载的模型存储为 Vertices
和 Normals
数组(来自 STL reader)。
到目前为止,当两个模型大小相同时没有问题。每当我加载 2 个不同的模型时,浏览器中都会显示一条错误消息:
WebGL: INVALID_OPERATION: drawArrays: attempt to access out of bounds arrays
所以我怀疑我没有正确操作多个缓冲区。
使用以下打字稿方法加载模型:
public AddModel(model: Model)
{
this.models.push(model);
model.VertexBuffer = this.gl.createBuffer();
model.NormalsBuffer = this.gl.createBuffer();
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, model.VertexBuffer);
this.gl.bufferData(this.gl.ARRAY_BUFFER, model.Vertices, this.gl.STATIC_DRAW);
model.CoordLocation = this.gl.getAttribLocation(this.shaderProgram, "coordinates");
this.gl.vertexAttribPointer(model.CoordLocation, 3, this.gl.FLOAT, false, 0, 0);
this.gl.enableVertexAttribArray(model.CoordLocation);
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, model.NormalsBuffer);
this.gl.bufferData(this.gl.ARRAY_BUFFER, model.Normals, this.gl.STATIC_DRAW);
model.NormalLocation = this.gl.getAttribLocation(this.shaderProgram, "vertexNormal");
this.gl.vertexAttribPointer(model.NormalLocation, 3, this.gl.FLOAT, false, 0, 0);
this.gl.enableVertexAttribArray(model.NormalLocation);
}
加载完成后调用Render方法绘制所有加载的模型:
public Render(viewMatrix: Matrix4, perspective: Matrix4)
{
this.gl.uniformMatrix4fv(this.viewRef, false, viewMatrix);
this.gl.uniformMatrix4fv(this.perspectiveRef, false, perspective);
this.gl.uniformMatrix4fv(this.normalTransformRef, false, viewMatrix.NormalMatrix());
// Clear the canvas
this.gl.clearColor(0, 0, 0, 0);
this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
// Draw the triangles
if (this.models.length > 0)
{
for (var i = 0; i < this.models.length; i++)
{
var model = this.models[i];
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, model.VertexBuffer);
this.gl.enableVertexAttribArray(model.NormalLocation);
this.gl.enableVertexAttribArray(model.CoordLocation);
this.gl.vertexAttribPointer(model.CoordLocation, 3, this.gl.FLOAT, false, 0, 0);
this.gl.uniformMatrix4fv(this.modelRef, false, model.TransformMatrix);
this.gl.uniform3fv(this.materialdiffuseRef, model.Color.AsVec3());
this.gl.drawArrays(this.gl.TRIANGLES, 0, model.TrianglesCount);
}
}
}
一个模型工作得很好。两个克隆模型也可以正常工作。不同的模型因提到的错误而失败。
我错过了什么?
WebGL的正常使用方式
在初始时间
每个着色器程序
- 创建并编译顶点着色器
- 创建并编译片段着色器
- 创建程序,附加着色器,link程序
每个模型
- 对于每种类型的顶点数据(位置、法线、颜色、纹理坐标)
- 创建缓冲区
- 复制数据到缓冲区
创建纹理
然后在渲染时
- 每个模型
- 使用适合模型的着色器程序
- 绑定缓冲区、启用和设置属性
- 绑定纹理并设置制服
- 调用 drawArrays 或 drawElements
但是看看你的代码,它是绑定缓冲区,并在初始化时而不是渲染时启用和设置属性。
也许会看到 this article and this one