2
votes

If I understand correctly, the THREE.Geometry methods, .computeFaceNormals() & .computeVertexNormals(), each assign values to an 'innate' attribute array, "normal".

So, if I want to use both vertex- & face- normals in a single shader, I must:

  1. calculate face-normals
  2. clone the results (from 'normals') to a new attribute array, (i.e. 'fNormals')
  3. calculate vertex-normals
  4. render...

So far, using this approach, I'm trying this:

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();

EDIT: Ok, realizing some mistakes & editing this as I debug. Still unsure as to how to address the generated normals...

Thanks for any insights-

1

1 Answers

4
votes

You can access faces normals in 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
}

This should work if your bind your attribute to the faces:

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

You can find an example of how to use custom attributes in webgl_materials_wireframe