Three.js : texture and html

Hi everyone !
I’m a graphist wich is modeling 3D model on blender (not since a long time). And i’ve been doing some research for imbed my creation on website. I tried to do it with HTML and found some good result (thanks to chat gpt that helping me understand some main html topic).

Then i’ve found that a gltf loader is a good way to use 3D in website. Since, i’ve done a gltf loader (basicaly), but found an issue. The texture on my models doesn’t load and it makes just one colour on my models. I’ve written my code with the help of Chat GPT because of my lack of knowledge in html and three.js and i think it can make some mistake in the code. I’m looking for someone that can help me just improving my code and load the texture on models please. Here below the code i have :

<!DOCTYPE html>
<html>
<head>
    <title>Visualiseur 3D</title>
    <style>
        #elementor-container {
            width: 100%; /* Largeur modifiable */
            height: 500px; /* Hauteur modifiable */
        }
        #container {
            width: 100%;
            height: 100%;
        }
    </style>
</head>
<body>
    <div id="elementor-container">
        <div id="container"></div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/three@0.137.5/build/three.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.137.5/examples/js/controls/OrbitControls.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/three@0.137.5/examples/js/loaders/GLTFLoader.js"></script>

    <script>
        let camera, scene, renderer, plane;
        const container = document.getElementById("container");
        const elementorContainer = document.getElementById("elementor-container");

        init();
        render();

        function init() {
            scene = new THREE.Scene();
            camera = new THREE.PerspectiveCamera(45, elementorContainer.offsetWidth / elementorContainer.offsetHeight, 0.1, 1000);
            camera.position.set(0, 0, 3); // Position de la caméra rapprochée

            renderer = new THREE.WebGLRenderer({ antialias: true });
            renderer.setSize(elementorContainer.offsetWidth, elementorContainer.offsetHeight);
            renderer.setClearColor(0xD8BFD8); // Couleur de fond mauve pour le rendu
            renderer.shadowMap.enabled = true;
            container.appendChild(renderer.domElement);

            const ambientLight = new THREE.AmbientLight(0xffffff, 1); // Lumière ambiante plus forte
            scene.add(ambientLight);

            const directionalLight = new THREE.DirectionalLight(0xffffff, 1); // Lumière directionnelle plus forte
            directionalLight.position.set(0, 1, 0);
            directionalLight.castShadow = true;
            scene.add(directionalLight);

            const planeGeometry = new THREE.PlaneGeometry(1000, 1000);
            const planeMaterial = new THREE.MeshStandardMaterial({ color: 0x99386c }); // Couleur du sol
            plane = new THREE.Mesh(planeGeometry, planeMaterial);
            plane.rotation.x = -Math.PI / 2;
            plane.position.y = -1;
            plane.receiveShadow = true;
            scene.add(plane);

            const loader = new THREE.GLTFLoader();
            loader.load('3D_visual/salazzle.gltf', function (gltf) {
                gltf.scene.traverse(function (child) {
                    if (child.isMesh) {
                        child.castShadow = true;
                    }
                });
                gltf.scene.position.y = -1; // Ajuster la position du modèle pour qu'il touche le sol
                scene.add(gltf.scene);
                render();
            }, undefined, function (error) {
                console.error('Erreur lors du chargement du modèle:', error);
            });

            const controls = new THREE.OrbitControls(camera, renderer.domElement);
            controls.addEventListener('change', render);

            window.addEventListener('resize', onWindowResize);
        }

        function onWindowResize() {
            camera.aspect = elementorContainer.offsetWidth / elementorContainer.offsetHeight;
            camera.updateProjectionMatrix();
            renderer.setSize(elementorContainer.offsetWidth, elementorContainer.offsetHeight);
            render();
        }

        function render() {
            renderer.render(scene, camera);
        }
    </script>
</body>
</html>

Thx a lot for helping :smiling_face:

You can consider exporting your .gltf as .glb in the meantime which will embed the textures with the file.

Otherwise you’ll need to load your texture separately using
https://threejs.org/examples/#webgl_geometry_cube
https://threejs.org/docs/index.html#api/en/loaders/TextureLoader

1 Like

Thanks for your help ! Is the glb better option for my project ? Is it works similar ?

You’re welcome! :slight_smile:
Basically it works the same, both are optimized for the web. It’s just handier in this case to have it in one file in my opinion.

A little more in depth: you have three options with .glb, .gltf and gltf embedded.
.gltf exports the models JSON, bin (if any), and image texture file (if any). Meaning more requests/having to load the texture separately. If your project is doing some special optimizations or changes to those files it could be beneficial.

.glb contains the above in one binary file.

.gltf embedded also embeds the texture into one file but is generally not recommended for file size reasons, it can be nice to have it in a non-binary format if you want to be able to easily read the file.

.glb is the binary version of GLTF… .gltf is the more human readable text version
The binary version is much smaller and faster to load.
The blender exporter should export the material with embedded textures as long as you’re using the standard bsdf material.