ThreeJS:一些材质纹理面/三角形未渲染

3
我有一个.obj和.mtl文件,从.tga文件中加载纹理。在3D建模软件中,一切似乎都正常工作/正常显示,但是当使用three.js (THREE.WebGLRenderer({ antialias: true }))加载时,某些对象的子元素(特别是膝盖和小腿之间,但例如不是口袋和腿部)似乎有一个透明的锯齿形缝隙/空三角形。
尝试开启抗锯齿、更改过度绘制值、关闭透明等。
加载器函数:
threejsHelper.helpers.loadObject('objects/pants/MaleBaggyPants.obj', 'objects/pants/MaleBaggyPants.mtl', {
    blinn1SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/button.tga') })),
    blinn2SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/back.tga') })),
    blinn4SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/front.tga') })),
    blinn5SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/pocket.tga') })),
    blinn6SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/back.tga') })),
    blinn7SG: (new THREE.MeshPhongMaterial({ color: 0xffffff, transparent: false, opacity: 1.0, overdraw: 0.5, map: threejsHelper.helpers.loadTexture(app.manager, 'objects/pants/front.tga') }))
}, function (object) {
    object.rotation.x = (-90*Math.PI/180);
    object.rotation.z = (-90*Math.PI/180);
    app.scene.add(object);
    app.ready = true;
});

辅助函数:

...
loadTexture: function (manager, path) {
    var texture;
    if (path.split('.').pop() == 'tga') {
        var loader = new THREE.TGALoader();
        texture = loader.load(path);
    } else {
        texture = new THREE.Texture();
        var loader = new THREE.ImageLoader(manager);
        loader.load(path, function (image) {
            texture.image = image;
            texture.needsUpdate = true;
        });
    }
    return texture;
},
loadMaterial: function (mtlPath, textures, complete) {
    var loader = new THREE.MTLLoader();
    loader.load(mtlPath, function (materials) {
        materials.preload();
        if (!!materials.materials) {
            for (var key in materials.materials) {
                if (key in textures) {
                    materials.materials[key] = textures[key];
                }
            }
        }
        complete(materials);
    });
},
loadObject: function (objPath, mtlPath, textures, complete) {
    app.helpers.loadMaterial(mtlPath, textures, function (materials) {
        var loader = new THREE.OBJLoader();
        loader.setMaterials(materials);
        loader.load(objPath, function (object) {
            complete(object);
        });
    });
},
...

1 2 3


1
尝试将 material.side 设置为 THREE.DoubleSide。另外,去掉过度绘制——这仅适用于 CanvasRenderer - WestLangley
看看能否提供一个现场示例的链接。创建一个更简单的 obj 文件来复制问题,并删除纹理,因为它们不应该相关。 - WestLangley
2
这对我来说看起来像是 three.js 的一个 bug。正如我所怀疑的那样,这些伪影出现在两个网格之间的接缝处。在 three.js 网站上提交一个 bug 报告吧。祝你好运! :) - WestLangley
1
请原谅我的无知,但是OBJLoader.js文件中从第306行开始的代码似乎暗示所有面都有一个固定的边限制/要求。所讨论的obj文件显示了一些具有超过4个面的面。例如,请参见obj文件中的第60067行。之后还有更多。就像切割工具用复杂的面修复了切割接缝一样。我想知道在等待错误解决的同时,在导出为obj之前的原始3D编辑器中进行三角化处理是否有帮助... - Radio
1
@MatisseVerDuyn 不用担心。我不是来为赏金而来,只是想解决有趣的问题。干杯! - Radio
显示剩余12条评论
2个回答

3
您在两个物体的接缝处似乎有额外的顶点,这可能会对三角剖分造成影响。
移除这些不必要的顶点,我99%确定它将解决您的问题。

extra vertices

我还注意到该模型的比例非常小。

2
我也注意到了这一点,在OP的帖子评论中做了记录。我认为删除会留下一个空隙。对模型进行三角剖分是更好的选择。或者可以重写OBJLoader以将具有4个或更多面的面三角化。请参见obj文件中的第60067行,以查看定义了6个顶点的面。OBJLoader.js允许在第321行使用第四个顶点,但不允许使用更多顶点,因此在Three.js中出现了未闭合的面。 - Radio
1
给2pha和@Radio - 感谢您对此问题的关注! - WestLangley
@2pha 感谢您深入挖掘这个问题 - 我将授予您赏金,以表彰您实际找到了问题的根源。但不幸的是,我必须使用我得到的东西(这些 .obj 文件是从 Second Life 提供的)...如果它们可以被其他软件正确渲染(例如来自上面的 finder quick look / preview 的示例),那么它们也应该能够在 three.js 中正确渲染。 - Matisse VerDuyn

1

我曾经遇到过同样的问题。在Threejs上,一些三角形无法正确渲染,而在我的OpenGL应用程序上则可以正常渲染。

我通过使用Uint32Array而不是Uint16Array来定义几何体的索引来解决了这个问题。我只需要加入这行代码,一切都像魔术般地正常工作了。

const indices = new Uint32Array(faceDict.index);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接