Search code examples
javascriptthree.js3d

Textures are not applied properly


Im trying to add two textures. One for the wall and another for the floor. After rendering Im just getting a solid color instead of the texture. Here is my scene & camera configuration:

    const tempScene = new THREE.Scene();
    tempScene.background = new THREE.Color(0x021D49);
    const ambient = new THREE.AmbientLight(0xffffff, 0.6);
    tempScene.add(ambient);
    const directionalLight = new THREE.DirectionalLight(0xfafafa, 0.6);
    directionalLight.position.set(0, 300, 300);
    tempScene.add(directionalLight);

    const tempCamera = new THREE.PerspectiveCamera(
      60,
      el.clientWidth / el.clientHeight,
      0.1,
      10000,
    );

    tempCamera.up.set(0, 0, 1);
    tempCamera.position.set(0, 300, 300);
    tempCamera.lookAt(0, 0, 0);
    const tempControls = new OrbitControls(tempCamera, el);
    tempControls.maxPolarAngle = Math.PI / 2;
    tempControls.minDistance = 10;
    tempControls.maxDistance = 500;
    tempControls.enablePan = false;

    const tempRenderer = new THREE.WebGLRenderer({ canvas: el, antialias: true });
    tempRenderer.setSize(el.clientWidth, el.clientHeight);
    tempRenderer.setPixelRatio(window.devicePixelRatio);
    tempRenderer.shadowMap.enabled = true;
    tempRenderer.shadowMap.type = THREE.PCFSoftShadowMap;
    tempRenderer.outputEncoding = THREE.sRGBEncoding;

Here is the code for texture:

      const floorTex = new THREE.TextureLoader().load(floorTexture);
      const wallMaterial = new THREE.MeshBasicMaterial({ map: wallTex, side: THREE.DoubleSide });
      const floorMaterial = new THREE.MeshStandardMaterial({ map: floorTex });
      const lineMaterial = new THREE.LineBasicMaterial({ color: 0x000000 });

        const wallGeometry = new THREE.BufferGeometry();
        const wallVertices = new Float32Array([
          -x1,
          y1,
          0, // vertex 1
          -x1,
          y1,
          10, // vertex 2
          -x2,
          y2,
          0, // vertex 3
          -x2,
          y2,
          10, // vertex 4
        ]);
        wallGeometry.setAttribute('position', new THREE.BufferAttribute(wallVertices, 3));
        wallGeometry.setIndex([0, 2, 1, 2, 3, 1]);
        const wall = new THREE.Mesh(wallGeometry, wallMaterial);
        const geo = new THREE.EdgesGeometry(wall.geometry);
        const wireframe = new THREE.LineSegments(geo, lineMaterial);
        wall.add(wireframe);
        wall.castShadow = true;
        wall.receiveShadow = true;
        scene!.add(wall);
        
        
       const floorGeometry = new THREE.Shape(floorPoints.map((point) => new THREE.Vector2(point[0],          point[1])));
      const shapeGeometry = new THREE.ShapeGeometry(floorGeometry);
      const floor = new THREE.Mesh(shapeGeometry, floorMaterial);
      floor.receiveShadow = true;
      scene!.add(floor);

This is how it looks

But in real the texture look like this: floorTexture wallTexture


Solution

  • Your wall does not get a texture applied since you define no texture coordinates for wallGeometry. Next to position you need a uv buffer attribute holding these data.

    Unfortunately, the code snippet does not provide enough information to investigate why the floor has no texture. Instances of ShapeGeometry do have a texture coordinates so I could imagine there is a loading issue with your texture.

    BTW: If you add tempRenderer.outputEncoding = THREE.sRGBEncoding; to your code, you have to set the encoding property of all color textures to THREE.sRGBEncoding as well. Otherwise your sRGB workflow is incomplete.