How to make a 3d model scroll as a background

How To Make A Vertical 3D Gallery Slider

So if you follow along in the video, I refer to this blog post for you to enter code at ...

Read More

How To Make A Horizontal 3D Gallery Slider

So if you follow along in the video, I refer to this blog post for you to enter code at ...

Read More

How To Make A Auto Rotating 3D Carousel

So if you follow along in the video, I refer to this blog post for you to enter code at ...

Read More

How To Make A 3D Carousel For Products

So if you follow along in the video, I refer to this blog post for you to enter code at ...

Read More

So if you follow along in the video, I refer to this blog post for you to either enter code at certain points into the HTML widget, so below is everything you will need!

The plugin to allow you to upload the model files into wordpress:

Sketchfab, the website to download your own models:

The image I used in the pre loader in the tutorial:

Models I used in the tutorial:

The Three.js script used to create the whole scene, model, camera, lights … just everything to perfectly handle the object.

				
					<div id="canvas-container" style="width: 100%; height: 100vh; position: fixed; top: 0; left: 0; overflow: hidden; z-index: -1;">
    <canvas id="cubeCanvas" style="width: 100%; height: 100%; "></canvas>
    <div id="loading-screen" style="width: 100%; height: 100%; background-color: rgba(0,0,0,0.5); display: flex; justify-content: center; align-items: center; z-index: 1000;">
        <div style="text-align: center; color: white;">
            
            <!--this is where you place the url of the placeholder image while the model loads up.
            -->
            
            <img decoding="async" data-src="http://video-on-scroll.local/wp-content/uploads/2024/09/futuristic-tunnel-corridor-with-neon-glowing-light-2023-11-27-04-53-49-utc.jpeg" alt="Loading" style="max-width: 100%; max-height: 300px;" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==" class="lazyload">
            <p id="loading-progress">Loading 3D Model: 0%</p>
        </div>
    </div>
</div>

<!-- Three.js core scripts -->
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/build/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/loaders/GLTFLoader.js"></script>

<!-- Postprocessing scripts -->
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/postprocessing/EffectComposer.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/postprocessing/RenderPass.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/postprocessing/UnrealBloomPass.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/shaders/CopyShader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/shaders/LuminosityHighPassShader.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/postprocessing/ShaderPass.js"></script>

<script>
    const MODEL_URL = 'http://video-on-scroll.local/wp-content/uploads/2024/09/steampunk_underwater_explorer.glb';

    const CAMERA_FOV = 55;
    const CAMERA_NEAR = 0.1;
    const CAMERA_FAR = 3000;
    const CAMERA_DISTANCE_FACTOR_DESKTOP = 32;
    const CAMERA_DISTANCE_FACTOR_MOBILE = 100;
    const CAMERA_OFFSET_X = 0;
    const CAMERA_OFFSET_Y = 0;

    // Bloom effect variables
    const BLOOM_INTENSITY = 3;
    const BLOOM_THRESHOLD = 0.4;
    const BLOOM_RADIUS = 0.65;

    // Updated light settings
    const DIRECTIONAL_LIGHT_COLOR = 0xffffff;
    const DIRECTIONAL_LIGHT_INTENSITY = 2;
    const AMBIENT_LIGHT_COLOR = 0xffffff;
    const AMBIENT_LIGHT_INTENSITY = 1;
    const ADDITIONAL_LIGHT_COLOR = 0xffffff;
    const ADDITIONAL_LIGHT_INTENSITY = 2;

    // background colour settings
    const BACKGROUND_COLOUR_SCENE = 0x000000; // White background
    const BACKGROUND_COLOUR_TRANSPARENCE = 0; // Fully opaque

//----------------
// End of controls
//----------------

    let canvas, renderer, scene, camera, light, ambientLight, additionalLight;
    let model, rotationGroup, mixer, clock, composer;

    function setupScene() {
        canvas = document.getElementById('cubeCanvas');
        renderer = new THREE.WebGLRenderer({ canvas: canvas, alpha: false, antialias: true });
        renderer.setClearColor(BACKGROUND_COLOUR_SCENE, BACKGROUND_COLOUR_TRANSPARENCE);
        renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));

        scene = new THREE.Scene();
        scene.background = new THREE.Color(BACKGROUND_COLOUR_SCENE);
        camera = new THREE.PerspectiveCamera(CAMERA_FOV, canvas.clientWidth / canvas.clientHeight, CAMERA_NEAR, CAMERA_FAR);

        // Use updated light settings
        ambientLight = new THREE.AmbientLight(AMBIENT_LIGHT_COLOR, AMBIENT_LIGHT_INTENSITY);
        scene.add(ambientLight);

        light = new THREE.DirectionalLight(DIRECTIONAL_LIGHT_COLOR, DIRECTIONAL_LIGHT_INTENSITY);
        light.position.set(10, 10, 10).normalize();
        scene.add(light);

        additionalLight = new THREE.PointLight(ADDITIONAL_LIGHT_COLOR, ADDITIONAL_LIGHT_INTENSITY, 100);
        additionalLight.position.set(-15, 0, -15);
        scene.add(additionalLight);

        rotationGroup = new THREE.Group();
        scene.add(rotationGroup);

        clock = new THREE.Clock();

        // Postprocessing setup
        composer = new THREE.EffectComposer(renderer);
        const renderPass = new THREE.RenderPass(scene, camera);
        renderPass.clearColor = new THREE.Color(BACKGROUND_COLOUR_SCENE);
        renderPass.clearAlpha = BACKGROUND_COLOUR_TRANSPARENCE;
        composer.addPass(renderPass);

        const bloomPass = new THREE.UnrealBloomPass(
            new THREE.Vector2(window.innerWidth / 2, window.innerHeight / 2), // Reduced resolution
            BLOOM_INTENSITY,
            BLOOM_THRESHOLD,
            BLOOM_RADIUS
        );
        composer.addPass(bloomPass);

        resizeCanvas();
    }

    function fitModelToCanvas() {
        if (!model) return;

        const box = new THREE.Box3().setFromObject(model);
        const center = box.getCenter(new THREE.Vector3());

        model.position.sub(center);

        const isMobile = window.innerWidth <= 768;
        let distance = isMobile ? CAMERA_DISTANCE_FACTOR_MOBILE : CAMERA_DISTANCE_FACTOR_DESKTOP;

        camera.position.set(CAMERA_OFFSET_X, CAMERA_OFFSET_Y, distance);
        camera.lookAt(new THREE.Vector3(0, 0, 0));
        camera.updateProjectionMatrix();

        renderer.setSize(canvas.clientWidth, canvas.clientHeight);
    }

    function animate() {
        requestAnimationFrame(animate);

        if (mixer) {
            mixer.update(clock.getDelta());
        }

        composer.render();
    }

    function resizeCanvas() {
        if (canvas && renderer && camera) {
            camera.aspect = canvas.clientWidth / canvas.clientHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(canvas.clientWidth, canvas.clientHeight);
            composer.setSize(canvas.clientWidth, canvas.clientHeight);
            if (model) {
                fitModelToCanvas();
            }
        }
    }

    function updateLoadingScreen(progress) {
        const progressText = document.getElementById('loading-progress');
        if (progressText) {
            progressText.textContent = `Loading 3D Model: ${Math.round(progress * 100)}%`;
        }
    }

    function hideLoadingScreen() {
        const loadingScreen = document.getElementById('loading-screen');
        if (loadingScreen) {
            loadingScreen.style.display = 'none';
        }
    }

    function startModelLoad() {
        const loadingManager = new THREE.LoadingManager();

        loadingManager.onProgress = function (url, itemsLoaded, itemsTotal) {
            updateLoadingScreen(itemsLoaded / itemsTotal);
        };

        loadingManager.onLoad = function () {
            hideLoadingScreen();
        };

        const loader = new THREE.GLTFLoader(loadingManager);

        loader.load(MODEL_URL, 
            function (gltf) {
                model = gltf.scene;
                rotationGroup.add(model);

                fitModelToCanvas();

                if (gltf.animations && gltf.animations.length) {
                    mixer = new THREE.AnimationMixer(model);
                    const animation = gltf.animations[0];
                    const action = mixer.clipAction(animation);
                    action.play();
                }

                animate();
            },
            function (xhr) {
                // Progress callback
            },
            function (error) {
                // Error callback
            }
        );
    }

    function onScroll() {
        if (model) {
            const scrollPercent = window.scrollY / (document.documentElement.scrollHeight - window.innerHeight);
            const rotation = scrollPercent * 2 * Math.PI;
            rotationGroup.rotation.y = rotation;
        }
    }

    function initiateBackgroundLoading() {
        setupScene();
        startModelLoad();
    }

    initiateBackgroundLoading();
    window.addEventListener('resize', resizeCanvas);

    // Use requestAnimationFrame for smoother scrolling
    let ticking = false;
    window.addEventListener('scroll', function() {
        if (!ticking) {
            window.requestAnimationFrame(function() {
                onScroll();
                ticking = false;
            });
            ticking = true;
        }
    });
</script>
				
			
Hello! How can I help you today?