ошибка:
THREE.WebGLProgram: Shader Error 0 - VALIDATE_STATUS false

Program Info Log: Fragment shader is not compiled.
ERROR: 0:42: ‘texture’ : function name expected
37:
38: void main() {
39:
40: gl_FragColor = vec4( color * vColor, 1.0 );
41:
> 42: gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );
43:
44: }
45:
46:
код html:
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite App</title>
    <style>
      body {margin: 0; }
    </style>
  </head>
  <body>
    <script type="x-shader/x-vertex" id="vertexshader">

      attribute float size;
      attribute vec3 customColor;
  
      varying vec3 vColor;
  
      void main() {
  
        vColor = customColor;
  
        vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
  
        gl_PointSize = size * ( 300.0 / length( mvPosition.xyz ) );
  
        gl_Position = projectionMatrix * mvPosition;
  
      }
  
    </script>
    <script type="x-shader/x-fragment" id="fragmentshader">
  
      uniform vec3 color;
      uniform sampler2D texture;
  
      varying vec3 vColor;
  
      void main() {
  
        gl_FragColor = vec4( color * vColor, 1.0 );
  
        gl_FragColor = gl_FragColor * texture2D( texture, gl_PointCoord );
  
      }
  
    </script>
    <script type="module" src="main.js"></script>
  </body>
</html>


код js:
import * as THREE from 'three';
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;

const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

const controls = new OrbitControls( camera, renderer.domElement );
controls.enableZoom = false;

controls.enableDamping = true; 
controls.dampingFactor = 0.05; 


const loader = new GLTFLoader();
const url = 'GRAF_3_23.glb';

loader.load(url, function (gltf) {
  const model = gltf.scene;

  model.traverse((child) => {
    if (child.isMesh) {
      const geometry = child.geometry;

      const texturePoint = new THREE.TextureLoader().load('texture3.png');
      
      const sizeVariation = 0.001;

      const geometryPoint = new THREE.BufferGeometry();

      const positions = geometry.getAttribute('position').array;

      
      const randomSize = [];
      for (let i = 0; i < positions.length; i += 3) {
        const startSize = 0.06;
        const size = startSize + (Math.random() * sizeVariation);
        randomSize.push(size, size, size); // каждый размер - это три компоненты размера в формате [x, y, z] 
      }
      // let startSize = 0.06;
      
      const materialPoint = new THREE.PointsMaterial({
        size: 1,
        sizeAttenuation: true,
        map: texturePoint,
        alphaTest: 0.01,
        transparent: true,
        color: new THREE.Color(1., 1., 1.),
        opacity: 1.
      });
      
      const sizes = new Float32Array(randomSize);
      geometryPoint.setAttribute('size', new THREE.BufferAttribute(sizes, 1));

      const randomPosition = [];
      for (let i = 0; i < positions.length; i += 3) {
        randomPosition.push(10.0*Math.random()-5.0, 10.0*Math.random()-5.0, 10.0*Math.random()-5.0);
      }
      const randomPositionCopy = [...randomPosition];

      let increment = 0.002;
   
      geometryPoint.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));




      geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(randomPosition), 3));
      function updateArray(increment) {
        for(let j = 0; j < 75; j++) {
          for(let i = 0; i<randomPosition.length; i++) {
            if (randomPosition[i] < positions[i]) {
              randomPosition[i] = randomPosition[i] + increment;
            } else if(randomPosition[i] > positions[i]) {
              randomPosition[i] = randomPosition[i] - increment;
            } else if((randomPosition[i] - positions[i]) < 0.002) {
              randomPosition[i] = positions[i];
            }
          }
        }
        geometryPoint.setAttribute('position', new THREE.BufferAttribute(new Float32Array(randomPosition), 3));
      }
      function reverseUpdateArray(increment) {
        for(let j = 0; j < 75; j++) {
          for(let i = 0; i<randomPosition.length; i++) {
            if (randomPosition[i] < randomPositionCopy[i]) {
              randomPosition[i] = randomPosition[i] + increment;
            } else if(randomPosition[i] > randomPositionCopy[i]) {
              randomPosition[i] = randomPosition[i] - increment;
            } else if((randomPosition[i] - randomPositionCopy[i]) < 0.002) {
              randomPosition[i] = randomPositionCopy[i];
            }
          }
        }
        geometryPoint.setAttribute('position', new THREE.BufferAttribute(new Float32Array(randomPosition), 3));
      }

      let time = 0;
      let sinPosition;
      let sinPosition2;
      let cosPosition;
      let randSignArray = [];
      let sign;
      let ratio = 1.0;

      for(let i = 0; i<randomPosition.length; i++) {
        sign = Math.random() < 0.5 ? -1.0 : 1.0;
        randSignArray[i] = sign;
      }
      geometryPoint.setAttribute('position', new THREE.BufferAttribute(new Float32Array(randomPosition), 3));
      // animateVerticles();
      // function animateVerticles() {
      //   requestAnimationFrame(animateVerticles);
      //   time += 0.1;
      //   sinPosition = Math.sin(time)*0.1;
      //   cosPosition = Math.cos(time*0.1)*0.1;
      //   sinPosition2 = Math.sin(time/Math.PI)*0.1;
      //   for(let i = 0; i<randomPosition.length; i++) {
      //     randomPosition[i] += (sinPosition * cosPosition * sinPosition2) * randSignArray[i] * ratio;
      //   }
      //   geometryPoint.setAttribute('position', new THREE.BufferAttribute(new Float32Array(randomPosition), 3));
      // }

      window.addEventListener('wheel', function(event) {
        if (event.deltaY > 0) {
          updateArray(increment);
          if(ratio > 0.0) {
            ratio -= 0.01;
          }
        } else {
          reverseUpdateArray(increment);
          ratio += 0.01;
        }
        console.log(ratio);

      });



      
// ________________________________________________________________________________________________________________________________________________

      const texture = makeTexture();
      texture.needsUpdate = true;
      texture.minFilter = THREE.LinearFilter;
      texture.magFilter = THREE.LinearFilter;

      const attributes = {
        alpha: {
          type: 'f',
          value: []
        },
        customColor: {
          type: 'c',
          value: []
        },
        size: {
          type: 'f',
          value: []
        }

      };

      const uniforms = {
        color: {
          type: "c",
          value: new THREE.Color(0xfffffff)
        },
        texture: {
          type: "t",
          value: texture
        }
      };

      const shaderMaterial = new THREE.ShaderMaterial({
        uniforms: uniforms,
        vertexShader: document.getElementById('vertexshader').textContent,
        fragmentShader: document.getElementById('fragmentshader').textContent,
        blending: THREE.AdditiveBlending,
        transparent: true,
        // fog: false,
        depthTest: false,
        // depthWrite: false
      });


      // const bufferGeometry = new THREE.BufferGeometry();
        let particles = 500;

        
        var colors = new Float32Array( particles * 3 );
        var sizesP = new Float32Array( particles );
        var color = new THREE.Color();
        for ( var i = 0, i3 = 0; i < particles; i ++, i3 += 3 ) {

          var x = -1 + Math.random() * 2;
          var y = -1 + Math.random() * 2;
          var z = -1 + Math.random() * 2;
          var d = 1 / Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
          x *= d;
          y *= d;
          z *= d;


          color.setHSL( i / particles, 1.0, 0.5 );

          colors[ i3 + 0 ] = color.r;
          colors[ i3 + 1 ] = color.g;
          colors[ i3 + 2 ] = color.b;

          sizes[ i ] = 20;
        }
        geometryPoint.setAttribute( 'customColor', new THREE.BufferAttribute( colors, 3 ) );
        geometryPoint.setAttribute( 'size', new THREE.BufferAttribute( sizesP, 1 ) );
        geometryPoint.attributes.position.dynamic = true;

        // let pointCloud = new THREE.Points(bufferGeometry, shaderMaterial);
        const points = new THREE.Points(geometryPoint, shaderMaterial);
      function makeTexture() {
      const canvas = document.createElement('canvas');
      const size = 100;
      canvas.width = size;
      canvas.height = size;
      const context = canvas.getContext('2d');
      const gradient = context.createRadialGradient(canvas.width / 2, canvas.height / 2, 0, canvas.width / 2, canvas.height / 2, canvas.width / 2);
      gradient.addColorStop(0, 'rgba(255, 255, 255, 1)');
      gradient.addColorStop(0.9, 'rgba(255, 255, 255, 1)');
      gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');
      context.fillStyle = gradient;
      context.fillRect(0, 0, canvas.width, canvas.height);
      return new THREE.Texture(canvas);
      }
// ________________________________________________________________________________________________________________________________________________




      scene.add(points);
      points.rotateX(Math.PI/2.0);
    }
  });
  camera.position.z = 3;



// ________________________________________________________________________________________________________________________________________________

    // Создаем переменные для точки и радиуса
  let point = new THREE.Vector3(0, 0, 0);
  let radius = 1;

  // Создаем функцию для генерации случайной точки внутри заданного радиуса
  function generateRandomPointInRadius(radius) {
    let angle1 = Math.random() * 2 * Math.PI;
    let angle2 = Math.random() * 2 * Math.PI;
    let x = radius * Math.sin(angle1) * Math.cos(angle2);
    let y = radius * Math.sin(angle1) * Math.sin(angle2);
    let z = radius * Math.cos(angle1);
    return new THREE.Vector3(x, y, z);
  }

  // Инициализируем переменные для генерации случайной точки
  let randomPoint = generateRandomPointInRadius(radius);
  let dist = point.distanceTo(randomPoint);
  let t = 0;

  // Создаем функцию для анимации точки
  function animatePoint() {
    t += 0.01;
    if (t > 1) {
      randomPoint = generateRandomPointInRadius(radius);
      dist = point.distanceTo(randomPoint);
      t = 0;
    }
    let newPos = point.clone().lerp(randomPoint, t);
    let moveDist = newPos.distanceTo(point);
    if (moveDist >= dist) {
      randomPoint = generateRandomPointInRadius(radius);
      dist = point.distanceTo(randomPoint);
      t = 0;
    }
    point.copy(newPos);
  }

  // Добавляем точку на сцену
  let pointGeometry = new THREE.SphereGeometry(0.2, 32, 32);
  let pointMaterial = new THREE.MeshBasicMaterial({color: 0xff0000});
  let pointMesh = new THREE.Mesh(pointGeometry, pointMaterial);
  pointMesh.position.set(point.x, point.y, point.z);
  scene.add(pointMesh);

// ________________________________________________________________________________________________________________________________________________

  function animate() {
  requestAnimationFrame(animate);
  animatePoint();
  pointMesh.position.set(point.x, point.y, point.z);
  controls.update();
  renderer.render(scene, camera);
  }
  animate();
});