WebGL使用循环多次绘制出现几何体重叠或变形问题求助
排查和解决建议
矩阵累加修改问题
你在循环内直接修改object.mvMatrix本身,mat4.translate默认会在传入的原矩阵基础上做修改,每一轮循环都会在上一轮平移后的矩阵基础上继续叠加偏移,而不是基于初始的模型视图矩阵计算偏移,导致实例位置越来越偏离预期,最终出现重叠、错位。
解决方法:每次循环前先拷贝一份初始的object.mvMatrix,在拷贝出来的矩阵上做平移操作,不要直接修改原矩阵:App.scene.tree1_.instancedDraws.overrideDrawArraysInstance = function(object) { // 先保存初始矩阵 const originalMvMatrix = mat4.clone(object.mvMatrix); for (var i = 0; i < object.instancedDraws.numberOfInstance; i++) { // 每次从初始矩阵开始计算偏移 mat4.translate( object.mvMatrix, originalMvMatrix, // 这里如果要不同实例位置不同,需要根据i生成对应偏移,所有实例偏移一致会导致重叠 [0 , 0, 18 * (i+1)] ); world.setMatrixUniforms(object, world.pMatrix, object.mvMatrix); // 后续绘制逻辑 } // 循环结束后恢复原矩阵,避免影响外部逻辑 object.mvMatrix = originalMvMatrix; };drawArraysInstanced参数使用错误- 第二个参数是顶点数组的起始偏移,你当前传了
1,会跳过第一个顶点,导致绘制的几何体顶点顺序不对出现变形,如果你的顶点数据是从0开始的,这里应该填0。 - 第四个参数是单次调用绘制的实例数,你现在每次循环传
1,相当于完全没有用到实例化绘制的特性,不如直接用普通的drawArrays。如果要发挥实例化绘制的性能优势,可以去掉循环,直接把实例数填为object.instancedDraws.numberOfInstance,同时通过实例化顶点属性传递每个实例的偏移量即可。 - 你之前正常绘制用的是
drawElements(索引绘制),但这里用的是drawArraysInstanced(无索引的数组绘制),请确认你当前绑定的顶点缓冲适配非索引绘制,如果此时还绑定着索引缓冲,或者顶点数据是专门给索引绘制准备的,会出现顶点读取错误导致变形。
- 第二个参数是顶点数组的起始偏移,你当前传了
实例偏移量固定问题
你当前所有循环的偏移量都是固定的[0,0,18],如果没有矩阵重置的逻辑,所有实例会沿着Z轴每次累加18的偏移,即便修复了矩阵问题,所有实例偏移都相同的话也会完全重叠。需要根据循环索引i生成不同的偏移值,比如X轴根据i做水平偏移:[i * 10, 0, 18]。矩阵栈操作校验
确认进入overrideDrawArraysInstance方法前,你已经调用了mvPushMatrix保存了初始的object.mvMatrix,避免方法内修改的矩阵泄漏到外部其他绘制逻辑。
内容的提问来源于stack exchange,提问作者Nikola Lukic
相关产品推荐
相关产品推荐

