Почему Three.js не согласен с интерполяцией Гуро?

Я хочу затенить THREE.BoxBufferGeometry используя простой THREE.MeshLambertMaterial, Предполагается, что материал будет использовать модель освещения Ламберта, чтобы выбрать цвета для каждой вершины (и она это делает), а затем использовать затенение Гуро для получения плавных градиентов на каждой грани.

Части Гуро не происходит. Вместо этого все грани куба заштрихованы одним сплошным цветом.

Я пробовал различные другие BufferGeometryи получил противоречивые результаты.

Например, если вместо этого я сделаю IcosahedronBufferGeometryЯ получаю ту же проблему: каждое лицо одного сплошного цвета.

geometry = new THREE.IcosahedronBufferGeometry(2, 0); // no Gouraud shading.
geometry = new THREE.IcosahedronBufferGeometry(2, 2); // no Gouraud shading.

С другой стороны, если я сделаю SphereBufferGeometryГуро присутствует.

geometry = new THREE.SphereBufferGeometry(2, 3, 2); // yes Gouraud shading.
geometry = new THREE.SphereBufferGeometry(2, 16, 16); // yes Gouraud shading.

Но тогда, если я сделаю куб, используя PolyhedronBufferGeometryзатенение Гуро не появится, если я не установлю детали на что-то другое, кроме 0,

const verticesOfCube = [
    -1,-1,-1,    1,-1,-1,    1, 1,-1,    -1, 1,-1,
    -1,-1, 1,    1,-1, 1,    1, 1, 1,    -1, 1, 1,
];

const indicesOfFaces = [
    2,1,0,    0,3,2,
    0,4,7,    7,3,0,
    0,1,5,    5,4,0,
    1,2,6,    6,5,1,
    2,3,7,    7,6,2,
    4,5,6,    6,7,4
];

const geometry = new THREE.PolyhedronBufferGeometry(verticesOfCube, indicesOfFaces, 1, 1); // no Gouraud shading
geometry = new THREE.PolyhedronBufferGeometry(verticesOfCube, indicesOfFaces, 1, 1); // yes Gouraud shading

Я знаю о существовании BufferGeometry методы computeFaceNormals() а также computeVertexNormals(), Нормалы здесь крайне важны, так как они используются для определения цветов для каждой грани и вершины соответственно. Но пока они помогают с Icosahedronони не влияют на BoxНезависимо от того, присутствуют ли они, присутствует только один, или оба присутствуют в обоих возможных порядках.

Вот код, который я ожидаю работать:

const geometry = new THREE.BoxBufferGeometry(2, 2, 2);
geometry.computeFaceNormals();
geometry.computeVertexNormals();

const material = new THREE.MeshLambertMaterial({
  color: 0xBE6E37
});

const mesh = new THREE.Mesh(geometry, material);

Я должен получить куб, грани которого (настоящие, треугольные) затенены градиентом. Сначала должны быть вычислены нормали граней, а затем нормали вершин путем усреднения нормалей образованных ими граней. Вот треугольная бипирамида, на которой применяется правильное затенение Гуро:

правильное затенение

Но код выше производит это вместо этого:

неправильное затенение

Three.js ни при каких условиях не регистрирует ошибки и предупреждения на консоли.

Так что же здесь происходит? Единственное объяснение, которое я могу придумать, заключается в том, что Box на самом деле состоит из 24 вершин, по три в каждом углу куба, и они образуют грани так, что вычисленная нормаль каждой вершины представляет собой в среднем максимум две грани, указывающие в одном направлении. Но я нигде не могу найти это записанное, и это объяснение не подходит для Polyhedron где вершины и грани были явно указаны в коде.

0 ответов

Другие вопросы по тегам