Как передать нормали Vertex и Face в шейдер Three.js?

Если я правильно понимаю, методы THREE.Geometry, .computeFaceNormals() и .computeVertexNormals(), каждый присваивает значения «врожденному» массиву атрибутов, «нормальному».

Итак, если я хочу использовать обе нормали вершин и граней в одном шейдере, я должен:

  1. вычислить нормали лица
  2. клонировать результаты (из «нормалей») в новый массив атрибутов (например, «fNormals»)
  3. вычислить нормали вершин
  4. оказывать...

Пока, используя этот подход, я пытаюсь сделать это:

var shader = new THREE.ShaderMaterial(
    {
        attributes: {
            fNormal: { type: "v3", value: [] }
        },
        //uniforms, vertexShader, etc...
    } );

//load a mesh & assign the shader to it...

//setup both vertex & face normals for use in shader

mesh.geometry.computeFaceNormals();

//clone above face-normals to 'fNormal' array:

for (var i=0; i < mesh.geometry.attributes[ 'normal' ].length; i++){
  var cloned = mesh.geometry.attributes[ 'normal' ].value[i];
  shader.attributes[ 'fNormal' ].value[i] = cloned;
}

//now calculate vertex normals & place them in the 'normal' attribute:
mesh.geometry.computeVertexNormals();

РЕДАКТИРОВАТЬ: Хорошо, понимая некоторые ошибки и редактируя это, когда я отлаживаю. Все еще не уверен, как обращаться с сгенерированными нормалями...

Спасибо за любые идеи-


person Jack    schedule 27.09.2014    source источник


Ответы (1)


Вы можете получить доступ к нормалям лиц в mesh.geometry.faces[].normal.

for (var i=0; i < mesh.geometry.faces.length; i++){
    shader.attributes.fNormal.value[i] = mesh.geometry.faces[i].normal;
    //I don't think you need to clone the normal vertex here
}

Это должно работать, если вы привязываете свой атрибут к лицам:

attributes: {
    fNormal: { type: "v3", value: [], boundTo: 'faces' }
},

Вы можете найти пример использования настраиваемых атрибутов в webgl_materials_wireframe.

person Volune    schedule 27.09.2014
comment
Да, я только встал на правильный путь, когда ваш ответ подтвердил это. Спасибо! Я не знал оboundTo до сих пор. Тем не менее, я в замешательстве: разве это не устанавливает массив длины, равный количеству граней, когда мне нужен массив, равный количеству вершин? - person Jack; 27.09.2014
comment
@Jackalope Вы можете увидеть в WebGLRenderer.js#L2211 что при boundTo === 'faces' фактически используется значение нормали для всех трех вершин грани. - person Volune; 27.09.2014