Почему 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
где вершины и грани были явно указаны в коде.