<!-- NEW7 — TEST 7 · THE WOVEN CITY · part 196 -->
ll_loop_end`
 * in order to unroll a `for` loop in GLSL by the shader preprocessor. The directive has
 * to be placed right above the loop. The loop formatting has to correspond to a defined standard.
 *   - The loop has to be [normalized](https://en.wikipedia.org/wiki/Normalized_loop).
 *   - The loop variable has to be *i*.
 *   - The value `UNROLLED_LOOP_INDEX` will be replaced with the explicitly
 * value of *i* for the given iteration and can be used in preprocessor
 * statements.
 *
 * ```js
 * const material = new THREE.ShaderMaterial( {
 * 	uniforms: {
 * 		time: { value: 1.0 },
 * 		resolution: { value: new THREE.Vector2() }
 * 	},
 * 	vertexShader: document.getElementById( 'vertexShader' ).textContent,
 * 	fragmentShader: document.getElementById( 'fragmentShader' ).textContent
 * } );
 * ```
 *
 * @augments Material
 */
class ShaderMaterial extends Material {

	/**
	 * Constructs a new shader material.
	 *
	 * @param {Object} [parameters] - An object with one or more properties
	 * defining the material's appearance. Any property of the material
	 * (including any property from inherited materials) can be passed
	 * in here. Color values can be passed any type of value accepted
	 * by {@link Color#set}.
	 */
	constructor( parameters ) {

		super();

		/**
		 * This flag can be used for type testing.
		 *
		 * @type {boolean}
		 * @readonly
		 * @default true
		 */
		this.isShaderMaterial = true;

		this.type = 'ShaderMaterial';

		/**
		 * Defines custom constants using `#define` directives within the GLSL code
		 * for both the vertex shader and the fragment shader; each key/value pair
		 * yields another directive.
		 * ```js
		 * defines: {
		 * 	FOO: 15,
		 * 	BAR: true
		 * }
		 * ```
		 * Yields the lines:
		 * ```
		 * #define FOO 15
		 * #define BAR true
		 * ```
		 *
		 * @type {Object}
		 */
		this.defines = {};

		/**
		 * An object of the form:
		 * ```js
		 * {
		 * 	"uniform1": { value: 1.0 },
		 * 	"uniform2": { value: 2 }
		 * }
		 * ```
		 * specifying the uniforms to be passed to the shader code; keys are uniform
		 * names, values are definitions of the form
		 * ```
		 * {
		 * 	value: 1.0
		 * }
		 * ```
		 * where `value` is the value of the uniform. Names must match the name of
		 * the uniform, as defined in the GLSL code. Note that uniforms are refreshed
		 * on every frame, so updating the value of the uniform will immediately
		 * update the value available to the GLSL code.
		 *
		 * @type {Object}
		 */
		this.uniforms = {};

		/**
		 * An array holding uniforms groups for configuring UBOs.
		 *
		 * @type {Array<UniformsGroup>}
		 */
		this.uniformsGroups = [];

		/**
		 * Vertex shader GLSL code. This is the actual code for the shader.
		 *
		 * @type {string}
		 */
		this.vertexShader = default_vertex;

		/**
		 * Fragment shader GLSL code. This is the actual code for the shader.
		 *
		 * @type {string}
		 */
		this.fragmentShader = default_fragment;

		/**
		 * Controls line thickness or lines.
		 *
		 * WebGL and WebGPU ignore this setting and always render line primitives with a
		 * width of one pixel.
		 *
		 * @type {number}
		 * @default 1
		 */
		this.linewidth = 1;

		/**
		 * Renders the geometry as a wireframe.
		 *
		 * @type {boolean}
		 * @default false
		 */
		this.wireframe = false;

		/**
		 * Controls the thickness of the wireframe.
		 *
		 * WebGL and WebGPU ignore this property and always render
		 * 1 pixel wide lines.
		 *
		 * @type {number}
		 * @default 1
		 */
		this.wireframeLinewidth = 1;

		/**
		 * Defines whether the material color is affected by global fog settings; `true`
		 * to pass fog uniforms to the shader.
		 *
		 * Setting this property to `true` requires the definition of fog uniforms. It is
		 * recommended to use `UniformsUtils.merge()` to combine the custom shader uniforms
		 * with predefined fog uniforms.
		 *
		 * ```js
		 * const material = new ShaderMaterial( {
		 *     uniforms: UniformsUtils.merge( [ UniformsLib[ 'fog' ], shaderUniforms ] );
		 *     vertexShader: vertexShader,
		 *     fragmentShader: fragmentShader,
		 *     fog: true
		 * } );
		 * ```
		 *
		 * @type {boolean}
		 * @default false
		 */
		this.fog = false;

		/**
		 * Defines whether this material uses lighting; `true` to pass uniform data
		 * related to lighting to this shader.
		 *
		 * @type {boolean}
		 * @default false
		 */
		this.lights = false;

		/**
		 * Defines whether this material supports clipping; `true` to let the renderer
		 * pass the clippingPlanes uniform.
		 *
		 * @type {boolean}
		 * @default false
		 */
		this.clipping = false;

		/**
		 * Overwritten and set to `true` by default.
		 *
		 * @type {boolean}
		 * @default true
		 */
		this.forceSinglePass = true;

		/**
		 * This object allows to enable certain WebGL 2 extensions.
		 *
		 * - clipCullDistance: set to `true` to use vertex shader clipping
		 * - multiDraw: set to `true` to use vertex shader multi_draw / en