Прежде чем я перейду к проблеме, я хочу подчеркнуть, что я далек от эксперта в том, что касается методов 3D-моделирования, текстурирования и рендеринга. Я знаю некоторые основы, но, пожалуйста, дайте мне знать, если мой подход к этому изначально неверен.
Также простите за отсутствие встроенных изображений. StackOverflow требует, чтобы я сначала заработал 10 репутации ...
Эта проблема
В настоящее время я работаю над проектом, который включает конвейер, в котором модели создаются в Blender (2.80 Beta), экспортируются как GLTF , используя эти настройки экспорта, а затем импортированный в three.js 0.102.1. Это отлично работает для большинства моделей. Однако, когда я хочу экспортировать свою модель ландшафта, материалы не экспортируются (или, возможно, не импортируются), как ожидалось.
Поскольку это местность, предпочтительнее использовать несколько текстур (или, лучше сказать, материалов), смешивая их в местах пересечения. Конечно, это можно сделать, используя одну гигантскую текстуру для всего ландшафта, но прелесть использования нескольких текстур в том, что вы просто повторяете их по всей местности и используете маску для определения смешивания. Вы сохраняете высокий уровень детализации без необходимости создавать массивную уникальную текстуру.
Почему я считаю GLTF узким местом
Это не Блендер:
В Blender карта выглядит нормально, а материалы смешиваются должным образом:
Смешивание травы и грязи
Используя следующую настройку узла:
Граф узлов материала
Это не three.js:
Я создал аналогичную настройку материала в three.js, используя NodeMaterials:
// 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):
Правильно текстурированный ландшафт
Правильное смешивание
Полагаю, это GLTF?
Конечно, здесь может быть ошибка экспортера или импортера.
- Импорт GLTF обратно в Blender дает тот же результат, что и three.js (черный ландшафт с белыми бликами там, где должна была идти грязь), поэтому я сомневаюсь, что проблема в этом.
- Я действительно в неведении, когда дело доходит до экспорта, так что проблема может заключаться в этом.
Кроме того, когда я попытался прочитать и понять спецификацию GLTF 2.0, я не увидел ничего в спецификациях материалов или текстур, которые позволяли бы смешивать или смешивать любого рода.
Я также наткнулся на расширение KHR_technique_webgl
, которое потенциально могло разрешить эта проблема тоже, хотя я не уверен в деталях.
Заключение
Поскольку я действительно хотел бы избежать жестко запрограммированного решения или использования одной гигантской текстуры, GLTF по-прежнему будет для меня лучшим вариантом. Итак, я что-то упустил в моем конвейере? Можно ли в данном случае использовать GLTF в данный момент? Есть ли в работе что-нибудь, что могло бы поддержать подобные материалы?
Мы будем благодарны за любую информацию. Спасибо.
Дополнительные ссылки: