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

  final geometryAttributes = geometry.attributes;

  final programAttributes = program.getAttributes();

  final materialDefaultAttributeValues = material.defaultAttributeValues;

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

    if (programAttribute!.location.id >= 0) {
      // final 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) {
        final normalized = geometryAttribute.normalized;
        final size = geometryAttribute.itemSize;

        final attribute = attributes.get(geometryAttribute);

        // TODO Attribute may not be available on context restore

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

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

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

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

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

          gl.bindBuffer(WebGL.ARRAY_BUFFER, buffer);

          // vertexAttribPointer( programAttribute, size, type, normalized, stride * bytesPerElement, offset * bytesPerElement );
          for (int i = 0; i < programAttribute.locationSize; i++) {
            vertexAttribPointer(
              programAttribute.location.id + i,
              size ~/ programAttribute.locationSize,
              type,
              normalized,
              (stride! * bytesPerElement).toInt(),
              ((offset + (size ~/ programAttribute.locationSize) * i) * bytesPerElement).toInt()
            );
          }
        }
        else {
          if (geometryAttribute is InstancedBufferAttribute) {
            // enableAttributeAndDivisor( programAttribute, geometryAttribute.meshPerAttribute );
            for (int i = 0; i < programAttribute.locationSize; i++) {
              enableAttributeAndDivisor(programAttribute.location.id + i, geometryAttribute.meshPerAttribute);
            }
            geometry.maxInstanceCount ??= geometryAttribute.meshPerAttribute * geometryAttribute.count;
          }
          else {
            // enableAttribute( programAttribute );
            for (int i = 0; i < programAttribute.locationSize; i++) {
              enableAttribute(programAttribute.location.id + i);
            }
          }

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

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

            case 3:
              gl.vertexAttrib3fv(programAttribute.location.id, value);
              break;

            case 4:
              gl.vertexAttrib4fv(programAttribute.location.id, value);
              break;

            default:
              gl.vertexAttrib1fv(programAttribute.location.id, value);
          }
        }
      }
    }
  }

  disableUnusedAttributes();
}