setupVertexAttributes method

void setupVertexAttributes(
  1. Object3D object,
  2. Material material,
  3. WebGLProgram program,
  4. BufferGeometry geometry,
)

Implementation

void setupVertexAttributes(
  Object3D object,
  Material material,
  WebGLProgram program,
  BufferGeometry geometry,
) {
  if (capabilities.isWebGL2 == false && (object is InstancedMesh || geometry is InstancedBufferGeometry)) {
    if (extensions.get('ANGLE_instanced_arrays') == null) return;
  }

  initAttributes();

  var geometryAttributes = geometry.attributes;

  var programAttributes = program.getAttributes();

  var materialDefaultAttributeValues = material.defaultAttributeValues;

  for (var name in programAttributes.keys) {
    var programAttribute = programAttributes[name];

    if (programAttribute["location"] >= 0) {
      // var geometryAttribute = geometryAttributes[ name ];
      BufferAttribute? geometryAttribute = geometryAttributes[name];

      if (geometryAttribute == null) {
        if (name == 'instanceMatrix' && object is InstancedMesh) {
          geometryAttribute = object.instanceMatrix;
        }
        if (name == 'instanceColor' && object is InstancedMesh && object.instanceColor != null) {
          geometryAttribute = object.instanceColor;
        }
      }

      if (geometryAttribute != null) {
        var normalized = geometryAttribute.normalized;
        var size = geometryAttribute.itemSize;

        var attribute = attributes.get(geometryAttribute);

        // TODO Attribute may not be available on context restore

        if (attribute == null) {
          print("WebGLBindingState setupVertexAttributes name: $name attribute == null ");
          continue;
        }

        var buffer = attribute["buffer"];
        var type = attribute["type"];
        var bytesPerElement = attribute["bytesPerElement"];

        if (geometryAttribute is InterleavedBufferAttribute) {
          var data = geometryAttribute.data;
          var stride = data?.stride;
          var offset = geometryAttribute.offset;

          if (data != null && data is InstancedInterleavedBuffer) {
            // enableAttributeAndDivisor( programAttribute, data.meshPerAttribute );
            for (var i = 0; i < programAttribute["locationSize"]; i++) {
              enableAttributeAndDivisor(programAttribute["location"] + i, data.meshPerAttribute);
            }

            if (object is! InstancedMesh && geometry.maxInstanceCount == null) {
              geometry.maxInstanceCount = data.meshPerAttribute * data.count;
            }
          } else {
            // enableAttribute( programAttribute );
            for (var i = 0; i < programAttribute["locationSize"]; i++) {
              enableAttribute(programAttribute["location"] + i);
            }
          }

          gl.bindBuffer(gl.ARRAY_BUFFER, buffer);

          // vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );
          for (var i = 0; i < programAttribute["locationSize"]; i++) {
            vertexAttribPointer(
                programAttribute["location"] + i,
                size ~/ programAttribute["locationSize"],
                type,
                normalized,
                stride! * bytesPerElement,
                (offset + (size ~/ programAttribute["locationSize"]) * i) * bytesPerElement);
          }
        } else {
          if (geometryAttribute is InstancedBufferAttribute) {
            // enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );
            for (var i = 0; i < programAttribute["locationSize"]; i++) {
              enableAttributeAndDivisor(programAttribute["location"] + i, geometryAttribute.meshPerAttribute);
            }

            geometry.maxInstanceCount ??= geometryAttribute.meshPerAttribute * geometryAttribute.count;
          } else {
            // enableAttribute( programAttribute );
            for (var i = 0; i < programAttribute["locationSize"]; i++) {
              enableAttribute(programAttribute["location"] + i);
            }
          }

          gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
          // vertexAttribPointer( programAttribute, size, type, normalized, 0, 0 );
          for (var i = 0; i < programAttribute["locationSize"]; i++) {
            vertexAttribPointer(programAttribute["location"] + i, size ~/ programAttribute["locationSize"], type,
                normalized, size * bytesPerElement, (size ~/ programAttribute["locationSize"]) * i * bytesPerElement);
          }
        }
      } else if (materialDefaultAttributeValues != null) {
        var value = materialDefaultAttributeValues[name];

        if (value != null) {
          switch (value.length) {
            case 2:
              gl.vertexAttrib2fv(programAttribute["location"], value);
              break;

            case 3:
              gl.vertexAttrib3fv(programAttribute["location"], value);
              break;

            case 4:
              gl.vertexAttrib4fv(programAttribute["location"], value);
              break;

            default:
              gl.vertexAttrib1fv(programAttribute["location"], value);
          }
        }
      }
    }
  }

  disableUnusedAttributes();
}