addAttribute(name, type, varyingExpression, varyingType) {
    this.attributes_.push({
      name,
      type,
      varyingName: name.replace(/^a_/, 'v_'),
      varyingType: varyingType ?? type,
      varyingExpression: varyingExpression ?? name,
    });
    return this;
  }
Adds an attribute accessible in the vertex shader, read from the geometry buffer.
The given name should include a type, such as `vec2 a_position`.
Attributes will also be made available under the same name in fragment shaders.
@param {string} name Attribute name, including the `a_` prefix
@param {'float'|'vec2'|'vec3'|'vec4'} type GLSL type
@param {string} [varyingExpression] Expression which will be assigned to the varying in the vertex shader, and
passed on to the fragment shader.
@param {'float'|'vec2'|'vec3'|'vec4'} [varyingType] Type of the attribute after transformation;
e.g. `vec4` after unpacking color components
@return {ShaderBuilder} the builder object