使用 GLTF 支持混合材质/纹理

Posted

技术标签:

【中文标题】使用 GLTF 支持混合材质/纹理【英文标题】:Blended materials / textures support using GLTF 【发布时间】:2019-08-21 13:19:42 【问题描述】:

在讨论这个问题之前,我想强调一下,在 3D 建模、纹理和渲染技术方面,我远非专家。我知道一些基础知识,但如果我的处理方法一开始就有问题,请告诉我。

另外,请原谅缺少嵌入图像。 *** 要求我先获得 10 点声望...

问题

我目前正在处理一个项目,该项目涉及一个管道,其中模型在 Blender (2.80 Beta) 中创建,导出为 GLTF using these export settings,然后导入 three.js 0.102.1。这适用于大多数模型。但是,当我想导出我的地形模型时,材质并没有按预期导出(或可能导入)。

Example image of the problem

由于这是地形,因此首选多个纹理(或更好的材质),在它们相交的地方混合它们。当然,这可以对整个地形使用一个巨大的纹理来完成,但是使用多个纹理的美妙之处在于您只需在整个地形上重复它们,并使用蒙版来确定混合。您无需创建庞大的单一纹理即可保持高水平的细节。

为什么我认为 GLTF 是瓶颈

这不是搅拌机:

在 Blender 中,地图看起来很好,并且材料按预期混合:Blending of grass and dirt

使用以下节点设置:Material node graph

不是三.js:

我使用 NodeMaterials 在three.js 中创建了类似的材质设置:

// MATERIAL
let mtl = new THREE.StandardNodeMaterial();
mtl.roughness = new THREE.FloatNode( .9 );
mtl.metalness = new THREE.FloatNode( 0 );

function createUv(scale, offset) 
    let uvOffset = new THREE.FloatNode( offset || 0 );
    let uvScale = new THREE.FloatNode( scale || 1 );

    let uvNode = new THREE.UVNode();
    let offsetNode = new THREE.OperatorNode(
        uvOffset,
        uvNode,
        THREE.OperatorNode.ADD
    );
    let scaleNode = new THREE.OperatorNode(
        offsetNode,
        uvScale,
        THREE.OperatorNode.MUL
    );

    return scaleNode;


let grass = new THREE.TextureNode( getTexture("grass"), createUv(35) );
let dirt = new THREE.TextureNode( getTexture("dirt"), createUv(35) );
let mask = new THREE.TextureNode( getTexture("mask"), createUv() );
let maskAlphaChannel = new THREE.SwitchNode(mask, "w");
let blend = new THREE.Math3Node(
    grass,
    dirt,
    maskAlphaChannel,
    THREE.Math3Node.MIX
);
mtl.color = blend;
mtl.normal = new THREE.NormalMapNode(
    new THREE.TextureNode( getTexture("dirtNormal"), createUv(35) )
);

let normalMask = new THREE.OperatorNode(
    new THREE.TextureNode( getTexture("mask"), createUv() ),
    new THREE.FloatNode(1),
    THREE.OperatorNode.MUL
);

mtl.normalScale = normalMask;

// build shader
mtl.build();

// set material
return mtl;

这会产生以下看起来相当不错的地形(这是在我的 three.js 项目中):Properly textured terrainProper blending

所以我猜是 GLTF?

当然,可能是 exporterimporter 在这里失败了。

将 GLTF 重新导入 Blender 会得到与 three.js 相同的结果(黑色地形,白色高光,污垢应该去的地方),所以我怀疑这是问题所在。 在导出方面我真的一无所知,所以问题可能出在此处。

此外,当我尝试阅读和理解 GLTF 2.0 规范时,我在材料或纹理规范中没有看到任何允许混合或混合的任何内容。 我还遇到了KHR_technique_webgl 扩展,它也可能解决这个问题,尽管我不确定具体细节。

结论

由于我真的很想避免使用硬编码解决方案或使用单个巨型纹理,因此 GLTF 仍然是我的选择。那么,我是否遗漏了我的管道中的任何内容?此时是否可以在这种情况下使用 GLTF?有什么作品可以支持这样的材料吗?

任何形式的见解将不胜感激。谢谢。

其他链接:

Blend file Image album

【问题讨论】:

【参考方案1】:

不幸的是,在撰写本文时,您无法导出任何格式来保留 Blender 中的自定义节点图并将其导入实时引擎。每个 Principled BSDF 套接字一个纹理是您所能做的。如果有帮助,glTF 导出器中有一个选项可以包含纹理变换(旋转、缩放、重复)。

对于像这样的自定义内容,我建议为您的材质添加名称和自定义属性(文本或数字)。在导出设置中启用“导出自定义属性/附加”,这些将作为material.userData 传递到threejs,您可以从中重建节点图。

【讨论】:

啊,我还没有想到使用自定义属性。那我大概会走这条路,非常感谢!【参考方案2】:

我知道它的旧帖子,但我发现 Blender 导出不混合节点。

【讨论】:

以上是关于使用 GLTF 支持混合材质/纹理的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL纹理覆盖材质颜色

将材质应用于 gltf 对象时出现未定义错误

如何向 GLTF 模型添加光泽度/镜面反射纹理?

三.js gltf模型变灰无纹理,改纹理后

UnityShader之固定管线命令Combine纹理混合Shader资料4

如何从 GLTF 模型动态覆盖纹理 - Three.js