WebGL2调用两个绘制函数仅显示第二个对象,gl_Position加号写法是否正确
渲染仅显示第二个对象的问题
根本原因
你全局仅声明了一个vao变量存储顶点数组对象,先调用的createGeometry()给vao赋值为金字塔的VAO,后调用的loadModel()直接覆盖了这个变量,金字塔的VAO引用直接丢失。渲染时两次gl.bindVertexArray(vao)绑定的都是茶壶的VAO,自然只有茶壶能被渲染。
另外你在loadModel()中用let vertexCounter = meshData.vertexCount声明了局部变量,全局的vertexCounter不会被正确赋值,会导致茶壶绘制的顶点数量错误。
解决步骤
- 拆分VAO变量,修正作用域问题
修改全局变量声明:
let gl; let vaoPyramid; // 存储金字塔VAO let vaoTeapot; // 存储茶壶VAO let program; let modelMatrix = mat4(1.0); let viewMatrix = mat4(1.0); let projectionMatrix = mat4(1.0); let modelMatrix1 = mat4(1.0); let vertexCounter = 5700;
- 修改两个初始化函数,分别给对应VAO赋值
createGeometry()中,将所有vao替换为vaoPyramidloadModel()中,将所有vao替换为vaoTeapot,同时去掉vertexCounter前的let关键词,改为直接修改全局变量:vertexCounter = meshData.vertexCount
- 修改渲染逻辑,绘制前绑定对应VAO
// 绘制金字塔 gl.bindVertexArray(vaoPyramid); gl.drawArrays(gl.TRIANGLES, 0, 18); // 绘制茶壶 gl.bindVertexArray(vaoTeapot); gl.drawArrays(gl.TRIANGLES, 0, vertexCounter);
顶点着色器位置相加写法的问题
根本原因
该写法完全错误。a_teapotposition是茶壶的逐顶点位置属性,金字塔的VAO根本没有配置对应属性缓冲区,两个对象的坐标变换逻辑完全独立,不能直接相加。
修正方案
首先在顶点着色器中放开u_model_matrix1的注释,然后修改着色器逻辑,区分两个对象的变换:
#version 300 es precision mediump float; layout(location = 0) in vec3 a_position; layout(location = 1) in vec3 a_teapotposition; // 修正为vec3,和顶点属性指针配置一致 layout(location = 2) in vec3 a_teapotcolor; uniform mat4 u_model_matrix; uniform mat4 u_model_matrix1; uniform mat4 u_viewMatrix; uniform mat4 u_projectionMatrix; out vec3 v_teapotcolor; void main() { vec4 worldPos; // 判断当前绘制的是哪个对象 if (a_position != vec3(0.0)) { // 金字塔用固定颜色,用u_model_matrix变换 v_teapotcolor = vec3(0.6, 0.3, 0.1); worldPos = u_model_matrix * vec4(a_position, 1.0); } else { // 茶壶用顶点颜色,用u_model_matrix1变换 v_teapotcolor = a_teapotcolor; worldPos = u_model_matrix1 * vec4(a_teapotposition, 1.0); } gl_Position = u_projectionMatrix * u_viewMatrix * worldPos; }
更规范的优化方案:不需要在着色器中做判断,绘制不同对象前切换u_model_matrix的赋值即可,只保留一个模型矩阵Uniform变量,减少着色器分支开销。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

