Как сделать Webgl шейдер фоном веб-страницы
Я пытаюсь сделать шейдер фоном веб-страницы, чтобы при скроллинге он оставался на месте. При этом должны соблюдаться условия:
- Работает без тега
bodyи дополнительного CSS. - Только html, добавляю js через
script. - Фон должен быть интерактивным: крутиться при перетаскивании мышью.
Я добавил ссылку на 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>