Почему Three.js не согласен с интерполяцией Гуро? - PullRequest
0 голосов
/ 16 июня 2019

Я хочу закрасить 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);

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

correct shading

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

incorrect shading

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

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

...