Добавить возможность градиентного фона в Vanta JS

Вопрос или проблема

Добрый день!

Мне нужно заменить однотонный цвет фона в VANTA JS (анимация HALO) на градиентный фон.

Вот мое решение с помощью ChatGPT (не знаю, как это заменит разработчиков, haha!), но ничего не изменилось: старый однотонный цвет фона остался и новые функции не сработали.

— Живой образец: https://jsfiddle.net/jnqmx7z5/

— ФАЙЛ: vanta.halo.js

Новые функции: addGradientBackground и updateGradientResolution

addGradientBackground() {
    // Создание пользовательского градиентного шейдера
    const gradientShaderMaterial = new THREE.ShaderMaterial({
      uniforms: {
        resolution: { type: 'v2', value: new THREE.Vector2() }  // Заменитель для разрешения
      },
      vertexShader: `
        void main() {
          gl_Position = vec4(position, 1.0);
        }
      `,
      fragmentShader: `
        uniform vec2 resolution;
  
        void main() {
          // Вычисление нормализованной координаты (0.0 до 1.0)
          vec2 uv = gl_FragCoord.xy / resolution.xy;
  
          // Цвета градиента (rgb(249, 38, 225) и rgb(42, 181, 251))
          vec3 color1 = vec3(249.0 / 255.0, 38.0 / 255.0, 225.0 / 255.0);
          vec3 color2 = vec3(42.0 / 255.0, 181.0 / 255.0, 251.0 / 255.0);
  
          // Плавная интерполяция между цветами на основе оси x (uv.x)
          vec3 color = mix(color1, color2, smoothstep(0.22, 0.9976, uv.x));
          
          gl_FragColor = vec4(color, 1.0);
        }
      `
    });  
  
    // Создание плоскостной геометрии на весь экран
    const planeGeometry = new THREE.PlaneGeometry(2, 2);
    const backgroundPlane = new THREE.Mesh(planeGeometry, gradientShaderMaterial);
  
    // Помещаем плоскость за эффект HALO
    backgroundPlane.position.z = -1;
    
    // Добавляем плоскость в сцену HALO
    this.scene.add(backgroundPlane);
  }

  updateGradientResolution() {
    // Получаем текущую ширину и высоту из рендерера или камеры
    const width = this.renderer.domElement.width;
    const height = this.renderer.domElement.height;
  
    // Обновляем униформу для шейдерного материала
    const gradientShaderMaterial = this.scene.children.find(child => child.material && child.material.uniforms && child.material.uniforms.resolution);
    if (gradientShaderMaterial) {
      gradientShaderMaterial.material.uniforms.resolution.value.set(width, height);
    }
  }


onInit() {
    const pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat }
    const ww = this.width * window.devicePixelRatio / this.scale
    const hh = this.height * window.devicePixelRatio / this.scale

    // Теперь вставляем логику пользовательского градиентного шейдера здесь только для HALO
    this.addGradientBackground();
    
    this.bufferTarget = new THREE.WebGLRenderTarget( ww, hh, pars )
    this.bufferFeedback = new THREE.WebGLRenderTarget( ww, hh, pars )

  }

onResize() {
    if (this.bufferTarget) {
      const ww = this.width * window.devicePixelRatio / this.scale
      const hh = this.height * window.devicePixelRatio / this.scale
      
      // Обновляем разрешение градиента при изменении размера окна
      this.updateGradientResolution();

      this.bufferTarget.setSize( ww, hh )
      this.bufferFeedback.setSize( ww, hh )
    }
  }

— Пересоздание vanta.halo.min.js

npx webpack --config webpack.config.js

— Ссылка.
Как three.js использует градиентный цвет для фона

Прозрачный фон с three.js

Ответ или решение

Добрый день!

Чтобы заменить сплошной фон в VANTA JS (эффект HALO) на градиентный фон, необходимо внести несколько изменений в вашу реализацию. Я вижу, что вы уже начали работать с шейдерами и добавили функции для создания градиентного фона. Однако давайте удостоверимся, что все части вашего кода правильно реализованы и скоординированы между собой.

Вот шаги, которые вы должны выполнить:

1. Настройка шейдеров градиента

Убедитесь, что ваш шейдер правильно обрабатывает входные данные. Вот улучшенный вариант функции addGradientBackground:

addGradientBackground() {
    // Создаем шейдер материи для градиента
    const gradientShaderMaterial = new THREE.ShaderMaterial({
        uniforms: {
            resolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) }
        },
        vertexShader: `
            void main() {
                gl_Position = vec4(position, 1.0);
            }
        `,
        fragmentShader: `
            uniform vec2 resolution;

            void main() {
                // Нормализуем координаты (0.0 до 1.0)
                vec2 uv = gl_FragCoord.xy / resolution.xy;

                // Цвета градиента
                vec3 color1 = vec3(249.0 / 255.0, 38.0 / 255.0, 225.0 / 255.0);
                vec3 color2 = vec3(42.0 / 255.0, 181.0 / 255.0, 251.0 / 255.0);

                // Плавная интерполяция между цветами по оси x
                vec3 color = mix(color1, color2, smoothstep(0.0, 1.0, uv.x));

                gl_FragColor = vec4(color, 1.0);
            }
        `
    });

    // Создаем геометрию плоскости для полного экрана
    const planeGeometry = new THREE.PlaneGeometry(2, 2);
    const backgroundPlane = new THREE.Mesh(planeGeometry, gradientShaderMaterial);

    // Помещаем плоскость позади эффекта HALO
    backgroundPlane.position.z = -1;

    // Добавляем плоскость в сцену HALO
    this.scene.add(backgroundPlane);
}

2. Обновление разрешения шейдера

Убедитесь, что ваше обновление разрешения работает корректно. Обратите внимание, что вы должны обновить uniform в шейдере при каждом изменении размера окна:

updateGradientResolution() {
    const width = this.renderer.domElement.width;
    const height = this.renderer.domElement.height;

    const gradientShaderMaterial = this.scene.children.find(child => 
        child.material && child.material.uniforms && child.material.uniforms.resolution
    );

    if (gradientShaderMaterial) {
        gradientShaderMaterial.material.uniforms.resolution.value.set(width, height);
    }
}

3. Инициализация

При инициализации убедитесь, что вы добавляете бэкграунд до создания рендер-таргетов. Например:

onInit() {
    const pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBFormat }
    const ww = this.width * window.devicePixelRatio / this.scale;
    const hh = this.height * window.devicePixelRatio / this.scale;

    // Вставляем вашу логику шейдера градиента для HALO
    this.addGradientBackground();

    this.bufferTarget = new THREE.WebGLRenderTarget(ww, hh, pars);
    this.bufferFeedback = new THREE.WebGLRenderTarget(ww, hh, pars);
}

4. Обработка изменения размера

Убедитесь, что вы вызываете updateGradientResolution в функции onResize, чтобы правильно обновить размеры:

onResize() {
    if (this.bufferTarget) {
        const ww = this.width * window.devicePixelRatio / this.scale;
        const hh = this.height * window.devicePixelRatio / this.scale;

        // Обновление разрешения градиента при изменении размера окна
        this.updateGradientResolution();

        this.bufferTarget.setSize(ww, hh);
        this.bufferFeedback.setSize(ww, hh);
    }
}

Итог

После внесения этих изменений ваш код должен корректно отображать градиентный фон вместо сплошного цвета. Убедитесь также, что у вас установлен WebGL и соответствующие библиотеки Three.js. Проверьте консоль на наличие ошибок, которые могут помочь вам в отладке.

Если вы всё ещё сталкиваетесь с проблемами, я рекомендую перелопатить код на наличие других возможных конфликтов или ошибок, которые могли бы препятствовать правильной работе вашего градиентного фона.

Если у вас есть дальнейшие вопросы или необходима дополнительная помощь, обращайтесь!

С наилучшими пожеланиями!

Оцените материал
Добавить комментарий

Капча загружается...