Как сделать Webgl шейдер фоном веб-страницы

Я пытаюсь сделать шейдер фоном веб-страницы, чтобы при скроллинге он оставался на месте. При этом должны соблюдаться условия:

  1. Работает без тега body и дополнительного CSS.
  2. Только html, добавляю js через script.
  3. Фон должен быть интерактивным: крутиться при перетаскивании мышью.

Я добавил ссылку на shader-web-background.min.js и прописал shaderWebBackground.shade( но это не помогло.

Ниже html код. Что я делаю не так?

<div class="canvas-container"></div>
<script src="https://unpkg.com/[email protected]/build/three.min.js"></script>
<script src="https://unpkg.com/[email protected]/examples/js/controls/OrbitControls.js"></script>
<script src="https://unpkg.com/[email protected]/examples/js/postprocessing/EffectComposer.js"></script>
<script src="https://unpkg.com/[email protected]/examples/js/postprocessing/RenderPass.js"></script>
<script src="https://unpkg.com/[email protected]/examples/js/postprocessing/ShaderPass.js"></script>
<script src="https://unpkg.com/[email protected]/examples/js/shaders/CopyShader.js"></script>
<script src="https://unpkg.com/[email protected]/examples/js/shaders/LuminosityHighPassShader.js"></script>
<script src="https://unpkg.com/[email protected]/examples/js/postprocessing/UnrealBloomPass.js"></script>
<script src="https://xemantic.github.io/shader-web-background/dist/shader-web-background.min.js"></script>
<script id="sphere-vertex-shader" type="x-shader/x-vertex">
  uniform float uTime;
    
    varying vec3 vNormal;
    varying vec3 vPosition;
    
    void main() {
        vNormal = normal;
        
        vec3 delta = 40.0 * normal * sin(
            abs(normal.x) * 2.0 +
            abs(normal.y) * 3.0 +
            abs(normal.z) * 4.0 + uTime / 2.0);
        
        delta.x += 20.0 * sin(uTime * normal.z);
        delta.y += 20.0 * sin(uTime * normal.x);
        delta.z += 20.0 * sin(uTime * normal.y);
        
        vec3 newPosition = position + delta;
        
        vPosition = newPosition;
        gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
        gl_PointSize = 1.0;
    }
    
</script>
<script id="sphere-fragment-shader" type="x-shader/x-fragment">
  uniform float uTime;
    
    varying vec3 vNormal;
    varying vec3 vPosition;
    
    
    void main() {
        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
    }
    
</script>
<script>
  let SCENE;
  let CAMERA;
  let RENDERER;
  let CONTROLS;
  let COMPOSER;
  let TIME = 10; // Let it be non zero at start
  main();

  function main() {
    init();
    animate();
  }

  function init() {
    initScene();
    initCamera();
    initRenderer();
    initComposer();
    initControls();
    initEventListeners();
    createObjects();
    document.querySelector(".canvas-container").appendChild(RENDERER.domElement);
  }

  function initScene() {
    SCENE = new THREE.Scene();
    initLights();
  }

  function initLights() {
    const point = new THREE.PointLight(0xffffff, 1, 0);
    point.position.set(0, 100, 50);
    SCENE.add(point);
  }

  function initCamera() {
    CAMERA = new THREE.PerspectiveCamera(
      45,
      window.innerWidth / window.innerHeight,
      1,
      2000
    );
    CAMERA.position.z = 100;
  }

  function initRenderer() {
    RENDERER = new THREE.WebGLRenderer({
      alpha: true
    });
    RENDERER.setPixelRatio(window.devicePixelRatio);
    RENDERER.setSize(window.innerWidth, window.innerHeight);
    RENDERER.shadowMap.enabled = true;
    RENDERER.shadowMapSort = true;
    RENDERER.setClearColor(0xcb79d94, 0.265);
  }

  function initComposer() {
    COMPOSER = new THREE.EffectComposer(RENDERER);
    COMPOSER.setSize(window.innerWidth, window.innerHeight);
    const renderPass = new THREE.RenderPass(SCENE, CAMERA);
    COMPOSER.addPass(renderPass);
    const bloomPass = new THREE.UnrealBloomPass(
      new THREE.Vector2(window.innerWidth, window.innerHeight),
      1.1,
      0.4,
      0.1
    );
    bloomPass.renderToScreen = true;
    COMPOSER.addPass(bloomPass);
  }

  function initControls() {
    CONTROLS = new THREE.OrbitControls(CAMERA);
    CONTROLS.enableZoom = false;
    CONTROLS.minPolarAngle = (Math.PI * 1) / 4;
    CONTROLS.maxPolarAngle = (Math.PI * 3) / 4;
    CONTROLS.update();
  }

  function initEventListeners() {
    window.addEventListener("resize", onWindowResize);
    onWindowResize();
  }

  function onWindowResize() {
    CAMERA.aspect = window.innerWidth / window.innerHeight;
    CAMERA.updateProjectionMatrix();
    RENDERER.setSize(window.innerWidth, window.innerHeight);
    COMPOSER.setSize(window.innerWidth, window.innerHeight);
  }

  function animate() {
    requestAnimationFrame(animate);
    CONTROLS.update();
    TIME += 0.005;
    updateUniforms();
    render();
  }

  function updateUniforms() {
    SCENE.traverse(function(child) {
      if (
        child instanceof THREE.Points &&
        child.material.type === "ShaderMaterial"
      ) {
        child.material.uniforms.uTime.value = TIME;
        child.material.needsUpdate = true;
      }
    });
  }

  function render() {
    CAMERA.lookAt(SCENE.position);
    COMPOSER.render(SCENE, CAMERA);
  }

  function createObjects() {
    const geometry = new THREE.TorusBufferGeometry(25, 1, 3000, 13);
    const shaderMaterial = new THREE.ShaderMaterial({
      uniforms: {
        uTime: {
          value: TIME
        }
      },
      transparent: true,
      side: THREE.DoubleSide,
      vertexShader: document.getElementById("sphere-vertex-shader").textContent,
      fragmentShader: document.getElementById("sphere-fragment-shader")
        .textContent
    });
    const torus = new THREE.Points(geometry, shaderMaterial);
    SCENE.add(torus);
  }
</script>

<script>
  shaderWebBackground.shade({
    shaders: {
      sphere - vertex - shader: {
        uniforms: {
          iResolution: (gl, loc, ctx) => gl.uniform2f(loc, ctx.width, ctx.height),
          iTime: (gl, loc) => gl.uniform1f(loc, performance.now() / 1000),
        }
      }
    }
  });
</script>


Ответы (0 шт):