Three.js dont renderize the shadows of the scene:

Three.js dont renderize the shadows of the scene, my code is here:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    body {
      overflow: hidden;
      margin: 0;
    }
  </style>
<div id="bancode_13024" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13024" async></script>
</div>
<div id="bancode_13177" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13177" async></script>
</div>
<br>
<div id="bancode_13178" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13178" async></script>
</div>
<div id="bancode_13179" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13179" async></script>
</div>
  <script src="perlin.js"></script>
  <script src="stats.js"></script>
  <script type="module">
  import * as THREE from "https://cdnjs.cloudflare.com/ajax/libs/three.js/0.162.0/three.module.js"
var stats = new Stats();
stats.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
document.body.appendChild( stats.dom )
function animate() {
  stats.begin()
  // monitored code goes here
  stats.end()
  requestAnimationFrame( animate )
}
    let walkspeed=0
    //Créditos a ChatGPT-1 por el aporte con sus sugerencias e ideas:
    onload = () => {
      // Ajustar las funciones matemáticas iniciales:
      let seed = Math.random();
      const noise2d = (i, k) => {
        return noise.simplex2(i, k + seed);
      }
      const getSurfaceAt = (i, k) => {
        return noise2d(i / 10000, k / 10000) * 2000 + 
                noise2d(i / 1000, k / 1000) * 200 + 
                noise2d(i / 100, k / 100) * 20 + 
                noise2d(i / 10, k / 10) * 2;
      }
      const rand=()=>{
        return Math.random()
      }
      const distance2d=(obj1,obj2)=>{return ((obj1.x-obj2.x)**2+(obj1.y-obj2.y)**2)**0.5}
      const distance3d=(obj1,obj2)=>{return ((obj1.x-obj2.x)**2+(obj1.y-obj2.y)**2+(obj1.z-obj2.z)**2)**0.5}
      //Colocar el absorbe-texturas lo primero:
      const textureLoader = new THREE.TextureLoader();
      // Ajustar la preparación del canvas:
      const scene = new THREE.Scene()
      const camera = new THREE.PerspectiveCamera(75, innerWidth / innerHeight, 0.1, 100000)
      const renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight)
      renderer.shadowMap.enabled = true;
      renderer.shadowMap.type = THREE.PCFSoftShadowMap;
      document.body.appendChild(renderer.domElement)
            
      scene.background = new THREE.Color("rgb(0,127,255)")
      let rd = 8000

	  // White directional light at half intensity shining from the top.
	  const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
      directionalLight.castShadows=true
	  scene.add( directionalLight );
      directionalLight.shadow.camera.left = -500; // default -5
      directionalLight.shadow.camera.right = 500; // default 5
      directionalLight.shadow.camera.top = 500; // default 5
      directionalLight.shadow.camera.bottom = -500; // default -5
	  const ambientLight = new THREE.AmbientLight( 0xffffff, 0.03);
	  scene.add( ambientLight );

      scene.fog = new THREE.Fog(new THREE.Color("rgb(0,127,255)"), rd/10, rd*4/10)
	  directionalLight.shadow.mapSize.width = 1024; // default is 512
	  directionalLight.shadow.mapSize.height = 1024; // default is 512
      const terrainChunks = []
      const leavesChunks = []
      const trunksChunks = []
      const brownstoneChunks = []
      const graniteChunks = []
      const limestoneChunks = []
      const microleavesChunks = []
      const leavesMaterialChunks = []
      const chunkSize = rd * 0.85 // Tamaño del fragmento de terreno

      // Función para generar un nuevo fragmento de terreno
      const generateTerrainChunk = (x, z) => {
      	const chunkAccuracy = 1
        const terrainChunkGeometry = new THREE.PlaneGeometry(chunkSize, chunkSize, chunkAccuracy * 128, chunkAccuracy * 128)
        terrainChunkGeometry.rotateX(-Math.PI / 2);
        //Geneerar las piedras:
        const brownstoneTexture = textureLoader.load("brownstone.png")
        brownstoneTexture.wrapS = THREE.RepeatWrapping
        brownstoneTexture.wrapT = THREE.RepeatWrapping
        brownstoneTexture.repeat.set(4, 4)
        const brownstoneChunkMaterial = new THREE.MeshLambertMaterial({ map: brownstoneTexture, side: THREE.DoubleSide })

        const graniteTexture = textureLoader.load("Granite.jpg")
        graniteTexture.wrapS = THREE.RepeatWrapping
        graniteTexture.wrapT = THREE.RepeatWrapping
        graniteTexture.repeat.set(4, 4)
        const graniteChunkMaterial = new THREE.MeshLambertMaterial({ map: graniteTexture, side: THREE.DoubleSide })

        const leavesTexture = textureLoader.load("leaves.jpg");
        leavesTexture.wrapS = THREE.RepeatWrapping
        leavesTexture.wrapT = THREE.RepeatWrapping
        leavesTexture.repeat.set(4, 4)
        const leavesMaterial = new THREE.MeshLambertMaterial({ map: leavesTexture, side: THREE.DoubleSide })
        
        const limestoneTexture = textureLoader.load("limestone.jpg");
        limestoneTexture.wrapS = THREE.RepeatWrapping
        limestoneTexture.wrapT = THREE.RepeatWrapping
        limestoneTexture.repeat.set(4, 4)
        const limestoneChunkMaterial = new THREE.MeshLambertMaterial({ map: limestoneTexture, side: THREE.DoubleSide })
        //Generar el suelo:
        const dirtTexture = textureLoader.load("grass.jpg")
        dirtTexture.wrapS = THREE.RepeatWrapping
        dirtTexture.wrapT = THREE.RepeatWrapping
        dirtTexture.repeat.set(512, 512)
        const terrainChunkMaterial = new THREE.MeshLambertMaterial({ map: dirtTexture, side: THREE.DoubleSide });
        const terrainChunkMesh = new THREE.Mesh(terrainChunkGeometry, terrainChunkMaterial)
        terrainChunkMesh.position.set(x, -20, z)
        scene.add(terrainChunkMesh)
        terrainChunks.push(terrainChunkMesh)
        //Generar el terreno:
        const terrainChunkVertices = terrainChunkGeometry.attributes.position.array
        for (let i = 0; i < terrainChunkVertices.length; i += 3) {
          const chunkX = terrainChunkVertices[i] + x
          const chunkZ = terrainChunkVertices[i + 2] + z
          const y = getSurfaceAt(chunkX, chunkZ)
          terrainChunkVertices[i + 1] = y
          //Generar las rocas.
          const gRoca=()=>{
            let geometry=new THREE.SphereGeometry(20)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*2-1 // Ajusta según el rango deseado
              vertex.y += rand()*2+vertex.y // Ajusta según el rango deseado
              vertex.z += rand()*2-1 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.castShadow = true;
			geometry.receiveShadow = true;
            return geometry
          }
          //Generar las hojas.
          const gHojas=()=>{
            let geometry=new THREE.SphereGeometry(100)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*100-50 // Ajusta según el rango deseado
              vertex.y += rand()*100-50 // Ajusta según el rango deseado
              vertex.z += rand()*100-50 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.castShadow = true;
			geometry.receiveShadow = true;
            return geometry
          }
          const gTronco=()=>{
            let geometry=new THREE.CylinderGeometry(20, 20, 200, 32)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*8-4 // Ajusta según el rango deseado
              vertex.y += 0 // Ajusta según el rango deseado
              vertex.z += rand()*8-4 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.castShadow = true;
			geometry.receiveShadow = true;
            return geometry
          }
          if (Math.random() < 0.0025/chunkAccuracy/chunkAccuracy) {
            const limestone_meshMaterial = new THREE.Mesh(gRoca(),limestoneChunkMaterial)
            limestone_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) - 10, chunkZ)
            scene.add(limestone_meshMaterial)
            limestoneChunks.push(limestone_meshMaterial)
          }
          if (Math.random() < 0.0025/chunkAccuracy/chunkAccuracy) {
            const brownstone_meshMaterial = new THREE.Mesh(gRoca(),brownstoneChunkMaterial)
            brownstone_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) - 10, chunkZ)
            scene.add(brownstone_meshMaterial)
            brownstoneChunks.push(brownstone_meshMaterial)
          }
          if (Math.random() < 0.0025/chunkAccuracy/chunkAccuracy) {
            const granite_meshMaterial = new THREE.Mesh(gRoca(),graniteChunkMaterial)
            granite_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) - 10, chunkZ)
            scene.add(granite_meshMaterial)
            graniteChunks.push(granite_meshMaterial)
          }
          //Generar los árboles:
          if (rand() < 0.025/chunkAccuracy/chunkAccuracy) {
            const trunk_meshMaterial = new THREE.Mesh(gTronco(), trunk_material)
            trunk_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) + 25, chunkZ)
            scene.add(trunk_meshMaterial)
            trunksChunks.push(trunk_meshMaterial)
            const leavesMaterial_meshMaterial = new THREE.Mesh(gHojas(),leavesMaterial)
            leavesMaterial_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) + 200, chunkZ)
            scene.add(leavesMaterial_meshMaterial)
            leavesMaterialChunks.push(leavesMaterial_meshMaterial)
          }
        }
      }

      let trunk_texture = textureLoader.load("trunk.jpg")
      trunk_texture.wrapS = THREE.RepeatWrapping
      trunk_texture.wrapT = THREE.RepeatWrapping
      trunk_texture.repeat.set(1, 2.5)
      let trunk_material = new THREE.MeshLambertMaterial({ map: trunk_texture, side: THREE.DoubleSide })

      // Función para eliminar fragmentos de terreno que ya no son visibles
      const removeInvisibleChunks = () => {
        const visibleChunks = []
        camera.getWorldPosition(tmpVector)

        const allChunks = terrainChunks.concat(leavesChunks, trunksChunks, brownstoneChunks, graniteChunks, limestoneChunks, microleavesChunks)

        for (const chunk of allChunks) {
          chunk.getWorldPosition(tmpVector2)
          if (tmpVector.distanceTo(tmpVector2) < chunkSize * 1.5) {
            visibleChunks.push(chunk)
          } else {
            scene.remove(chunk)
            chunk.geometry.dispose()
          }
        }
      };

      const tmpVector = new THREE.Vector3()
      const tmpVector2 = new THREE.Vector3()

      //Crea los controles del mouse:
      let xa = 0;
      let ya = 0;
      onmousedown = () => {
        if (document.pointerLockElement === document.body || document.mozPointerLockElement === document.body) {
        } else {
          document.body.requestPointerLock()
        }
      };
      onmousemove = event => {
        if (document.pointerLockElement === document.body || document.mozPointerLockElement === document.body) {
          xa -= 0.01 * event.movementX;
          if (-1.5 < ya && 0 < event.movementY) {
            ya -= 0.005 * event.movementY
          }
          if (ya < 1.5 && event.movementY < 0) {
            ya -= 0.005 * event.movementY
          }
        }
      };

      //Crear los controles de teclado:
      let k = [];
      onkeydown = onkeyup = e => {
        k[e.keyCode] = e.type == "keydown";
      };

      // Crear una función de animación
      const animate = () => {
        // Ajustar el canvas...
        renderer.setSize(innerWidth, innerHeight)
        camera.aspect = innerWidth / innerHeight
        camera.updateProjectionMatrix()



        // Ajustar los controles...
        if (-1.5 > ya) {
          ya = -1.5
        }
        if (1.5 < ya) {
          ya = 1.5
        }
        camera.lookAt(
          camera.position.x + Math.sin(xa) * Math.cos(ya),
          camera.position.y + Math.sin(ya),
          camera.position.z + Math.cos(xa) * Math.cos(ya)
        );

	    // Colisiones:
	    for(let i1 in trunksChunks){
          if(distance3d({x:trunksChunks[i1].position.x,y:0,z:trunksChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<24){
            console.log("Collision.")
            camera.position.x+=(camera.position.x-trunksChunks[i1].position.x)/distance3d({x:trunksChunks[i1].position.x,y:0,z:trunksChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.z+=(camera.position.z-trunksChunks[i1].position.z)/distance3d({x:trunksChunks[i1].position.x,y:0,z:trunksChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
          }
        }
        for(let i1 in brownstoneChunks){
          if(distance3d({x:brownstoneChunks[i1].position.x,y:0,z:brownstoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<24){
            console.log("Collision.")
            module=distance3d({x:brownstoneChunks[i1].position.x,y:0,z:brownstoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.x+=(camera.position.x-brownstoneChunks[i1].position.x)/module
            camera.position.z+=(camera.position.z-brownstoneChunks[i1].position.z)/module
          }
        }
        for(let i1 in limestoneChunks){
          if(distance3d({x:limestoneChunks[i1].position.x,y:0,z:limestoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<24){
            console.log("Collision.")
            module=distance3d({x:limestoneChunks[i1].position.x,y:0,z:limestoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.x+=(camera.position.x-limestoneChunks[i1].position.x)/module
            camera.position.z+=(camera.position.z-limestoneChunks[i1].position.z)/module
          }
        }
        for(let i1 in graniteChunks){
          if(distance3d({x:graniteChunks[i1].position.x,y:0,z:graniteChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<24){
            console.log("Collision.")
            module=distance3d({x:graniteChunks[i1].position.x,y:0,z:graniteChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.x+=(camera.position.x-graniteChunks[i1].position.x)/module
            camera.position.z+=(camera.position.z-graniteChunks[i1].position.z)/module
          }
        }

        // Establecer la velocidad predeterminada
	    if(k[81]){
	    	walkspeed=1
	    }else{
	    	walkspeed=0.5
	    }

	    // Mover el jugador
	    if (k[65]) {
	      camera.position.x += walkspeed * Math.cos(xa)
	      camera.position.z -= walkspeed * Math.sin(xa)
	    }
	    if (k[87]) {
	      camera.position.x += walkspeed * Math.sin(xa)
	      camera.position.z += walkspeed * Math.cos(xa)
	    }
	    if (k[68]) {
	      camera.position.x -= walkspeed * Math.cos(xa)
	      camera.position.z += walkspeed * Math.sin(xa)
	    }
	    if (k[83]) {
	      camera.position.x -= walkspeed * Math.sin(xa)
	      camera.position.z -= walkspeed * Math.cos(xa)
	    }

        // Manteniendo la fuerza de sujección del Jugador contra el suelo:
      	camera.position.y = getSurfaceAt(camera.position.x, camera.position.z) + 30

        // Generar nuevos fragmentos de terreno a medida que el jugador se mueve
        const playerChunkX = Math.floor(camera.position.x / chunkSize) * chunkSize
        const playerChunkZ = Math.floor(camera.position.z / chunkSize) * chunkSize

        for (let x = -chunkSize; x <= chunkSize; x += chunkSize) {
          for (let z = -chunkSize; z <= chunkSize; z += chunkSize) {
            const chunkX = playerChunkX + x
            const chunkZ = playerChunkZ + z

            if (!terrainChunks.some(chunk => chunk.position.x === chunkX && chunk.position.z === chunkZ)) {
              generateTerrainChunk(chunkX, chunkZ);
            }
          }
        }

        // Eliminar fragmentos de terreno invisibles
        removeInvisibleChunks()

        // Llamada recursiva para la próxima animación
        requestAnimationFrame(animate)
        renderer.render(scene, camera)
      }

      // Iniciar la animación
      animate();
    };
  </script>
</head>
<body>
</body>
</html>

And the capture is this:


How can i apply shadows to see like this resource?:
image

You can debug the light’s shadow with this line:

scene.add( new THREE.CameraHelper( directionalLight.shadow.camera ) );

Make sure all shadow casting and receiving objects are inside the shadow camera’s frustum.

Besides, you have the following lines in your code:

geometry.castShadow = true;
geometry.receiveShadow = true;

These are incorrect since both properties belong to Object3D not BufferGeometry. So set castShadow and receiveShadow to true for all meshes in your scene.

1 Like

That command shows this line:

I have the following code:

            let geometry=new THREE.SphereGeometry(20)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*2-1 // Ajusta según el rango deseado
              vertex.y += rand()*2+vertex.y // Ajusta según el rango deseado
              vertex.z += rand()*2-1 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.castShadow = true;
	    geometry.receiveShadow = true;
            return geometry

Do u mean instead using geometry.castShadow = true i should use geometry.attributes.position.castShadow=true or `vertex.fromBufferAttribute.castShadow=true

This is my code now:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    body {
      overflow: hidden;
      margin: 0;
    }
  </style>
<div id="bancode_13024" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13024" async></script>
</div>
<div id="bancode_13177" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13177" async></script>
</div>
<br>
<div id="bancode_13178" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13178" async></script>
</div>
<div id="bancode_13179" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13179" async></script>
</div>
  <script src="perlin.js"></script>
  <script src="stats.js"></script>
  <script type="module">
  import * as THREE from "https://cdnjs.cloudflare.com/ajax/libs/three.js/0.162.0/three.module.js"
var stats = new Stats();
stats.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
document.body.appendChild( stats.dom )
function animate() {
  stats.begin()
  // monitored code goes here
  stats.end()
  requestAnimationFrame( animate )
}
    let walkspeed=0
    //Créditos a ChatGPT-1 por el aporte con sus sugerencias e ideas:
    onload = () => {
      // Ajustar las funciones matemáticas iniciales:
      let seed = Math.random();
      const noise2d = (i, k) => {
        return noise.simplex2(i, k + seed);
      }
      const getSurfaceAt = (i, k) => {
        return noise2d(i / 10000, k / 10000) * 2000 + 
                noise2d(i / 1000, k / 1000) * 200 + 
                noise2d(i / 100, k / 100) * 20 + 
                noise2d(i / 10, k / 10) * 2;
      }
      const rand=()=>{
        return Math.random()
      }
      const distance2d=(obj1,obj2)=>{return ((obj1.x-obj2.x)**2+(obj1.y-obj2.y)**2)**0.5}
      const distance3d=(obj1,obj2)=>{return ((obj1.x-obj2.x)**2+(obj1.y-obj2.y)**2+(obj1.z-obj2.z)**2)**0.5}
      //Colocar el absorbe-texturas lo primero:
      const textureLoader = new THREE.TextureLoader();
      // Ajustar la preparación del canvas:
      const scene = new THREE.Scene()
      const camera = new THREE.PerspectiveCamera(75, innerWidth / innerHeight, 0.1, 100000)
      const renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight)
      renderer.shadowMap.enabled = true;
      renderer.shadowMap.type = THREE.PCFSoftShadowMap;
      document.body.appendChild(renderer.domElement)
            
      scene.background = new THREE.Color("rgb(0,127,255)")
      let rd = 8000

	  // White directional light at half intensity shining from the top.
	  const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
      directionalLight.castShadows=true
	  scene.add( directionalLight );
      directionalLight.shadow.camera.left = -500; // default -5
      directionalLight.shadow.camera.right = 500; // default 5
      directionalLight.shadow.camera.top = 500; // default 5
      directionalLight.shadow.camera.bottom = -500; // default -5
	  const ambientLight = new THREE.AmbientLight( 0xffffff, 0.03);
	  scene.add( ambientLight );

      scene.fog = new THREE.Fog(new THREE.Color("rgb(0,127,255)"), rd/10, rd*4/10)
	  directionalLight.shadow.mapSize.width = 1024; // default is 512
	  directionalLight.shadow.mapSize.height = 1024; // default is 512
      const terrainChunks = []
      const leavesChunks = []
      const trunksChunks = []
      const brownstoneChunks = []
      const graniteChunks = []
      const limestoneChunks = []
      const microleavesChunks = []
      const leavesMaterialChunks = []
      const chunkSize = rd * 0.85 // Tamaño del fragmento de terreno

      // Función para generar un nuevo fragmento de terreno
      const generateTerrainChunk = (x, z) => {
      	const chunkAccuracy = 1
        const terrainChunkGeometry = new THREE.PlaneGeometry(chunkSize, chunkSize, chunkAccuracy * 128, chunkAccuracy * 128)
        terrainChunkGeometry.rotateX(-Math.PI / 2);
        //Geneerar las piedras:
        const brownstoneTexture = textureLoader.load("brownstone.png")
        brownstoneTexture.wrapS = THREE.RepeatWrapping
        brownstoneTexture.wrapT = THREE.RepeatWrapping
        brownstoneTexture.repeat.set(4, 4)
        const brownstoneChunkMaterial = new THREE.MeshLambertMaterial({ map: brownstoneTexture, side: THREE.DoubleSide })

        const graniteTexture = textureLoader.load("Granite.jpg")
        graniteTexture.wrapS = THREE.RepeatWrapping
        graniteTexture.wrapT = THREE.RepeatWrapping
        graniteTexture.repeat.set(4, 4)
        const graniteChunkMaterial = new THREE.MeshLambertMaterial({ map: graniteTexture, side: THREE.DoubleSide })

        const leavesTexture = textureLoader.load("leaves.jpg");
        leavesTexture.wrapS = THREE.RepeatWrapping
        leavesTexture.wrapT = THREE.RepeatWrapping
        leavesTexture.repeat.set(4, 4)
        const leavesMaterial = new THREE.MeshLambertMaterial({ map: leavesTexture, side: THREE.DoubleSide })
        
        const limestoneTexture = textureLoader.load("limestone.jpg");
        limestoneTexture.wrapS = THREE.RepeatWrapping
        limestoneTexture.wrapT = THREE.RepeatWrapping
        limestoneTexture.repeat.set(4, 4)
        const limestoneChunkMaterial = new THREE.MeshLambertMaterial({ map: limestoneTexture, side: THREE.DoubleSide })
        //Generar el suelo:
        const dirtTexture = textureLoader.load("grass.jpg")
        dirtTexture.wrapS = THREE.RepeatWrapping
        dirtTexture.wrapT = THREE.RepeatWrapping
        dirtTexture.repeat.set(512, 512)
        const terrainChunkMaterial = new THREE.MeshLambertMaterial({ map: dirtTexture, side: THREE.DoubleSide });
        const terrainChunkMesh = new THREE.Mesh(terrainChunkGeometry, terrainChunkMaterial)
        terrainChunkMesh.position.set(x, -20, z)
        scene.add(terrainChunkMesh)
        terrainChunks.push(terrainChunkMesh)
        //Generar el terreno:
        const terrainChunkVertices = terrainChunkGeometry.attributes.position.array
        for (let i = 0; i < terrainChunkVertices.length; i += 3) {
          const chunkX = terrainChunkVertices[i] + x
          const chunkZ = terrainChunkVertices[i + 2] + z
          const y = getSurfaceAt(chunkX, chunkZ)
          terrainChunkVertices[i + 1] = y
          //Generar las rocas.
          const gRoca=()=>{
            let geometry=new THREE.SphereGeometry(20)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*2-1 // Ajusta según el rango deseado
              vertex.y += rand()*2+vertex.y // Ajusta según el rango deseado
              vertex.z += rand()*2-1 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.castShadow = true;
			geometry.receiveShadow = true;
            return geometry
          }
          //Generar las hojas.
          const gHojas=()=>{
            let geometry=new THREE.SphereGeometry(100)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*100-50 // Ajusta según el rango deseado
              vertex.y += rand()*100-50 // Ajusta según el rango deseado
              vertex.z += rand()*100-50 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.castShadow = true;
			geometry.receiveShadow = true;
            return geometry
          }
          const gTronco=()=>{
            let geometry=new THREE.CylinderGeometry(20, 20, 200, 32)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*8-4 // Ajusta según el rango deseado
              vertex.y += 0 // Ajusta según el rango deseado
              vertex.z += rand()*8-4 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.castShadow = true;
			geometry.receiveShadow = true;
            return geometry
          }
          if (Math.random() < 0.0025/chunkAccuracy/chunkAccuracy) {
            const limestone_meshMaterial = new THREE.Mesh(gRoca(),limestoneChunkMaterial)
            limestone_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) - 10, chunkZ)
            scene.add(limestone_meshMaterial)
            limestoneChunks.push(limestone_meshMaterial)
          }
          if (Math.random() < 0.0025/chunkAccuracy/chunkAccuracy) {
            const brownstone_meshMaterial = new THREE.Mesh(gRoca(),brownstoneChunkMaterial)
            brownstone_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) - 10, chunkZ)
            scene.add(brownstone_meshMaterial)
            brownstoneChunks.push(brownstone_meshMaterial)
          }
          if (Math.random() < 0.0025/chunkAccuracy/chunkAccuracy) {
            const granite_meshMaterial = new THREE.Mesh(gRoca(),graniteChunkMaterial)
            granite_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) - 10, chunkZ)
            scene.add(granite_meshMaterial)
            graniteChunks.push(granite_meshMaterial)
          }
          //Generar los árboles:
          if (rand() < 0.025/chunkAccuracy/chunkAccuracy) {
            const trunk_meshMaterial = new THREE.Mesh(gTronco(), trunk_material)
            trunk_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) + 25, chunkZ)
            scene.add(trunk_meshMaterial)
            trunksChunks.push(trunk_meshMaterial)
            const leavesMaterial_meshMaterial = new THREE.Mesh(gHojas(),leavesMaterial)
            leavesMaterial_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) + 200, chunkZ)
            scene.add(leavesMaterial_meshMaterial)
            leavesMaterialChunks.push(leavesMaterial_meshMaterial)
          }
        }
      }

      let trunk_texture = textureLoader.load("trunk.jpg")
      trunk_texture.wrapS = THREE.RepeatWrapping
      trunk_texture.wrapT = THREE.RepeatWrapping
      trunk_texture.repeat.set(1, 2.5)
      let trunk_material = new THREE.MeshLambertMaterial({ map: trunk_texture, side: THREE.DoubleSide })

      // Función para eliminar fragmentos de terreno que ya no son visibles
      const removeInvisibleChunks = () => {
        const visibleChunks = []
        camera.getWorldPosition(tmpVector)

        const allChunks = terrainChunks.concat(leavesChunks, trunksChunks, brownstoneChunks, graniteChunks, limestoneChunks, microleavesChunks)

        for (const chunk of allChunks) {
          chunk.getWorldPosition(tmpVector2)
          if (tmpVector.distanceTo(tmpVector2) < chunkSize * 1.5) {
            visibleChunks.push(chunk)
          } else {
            scene.remove(chunk)
            chunk.geometry.dispose()
          }
        }
      };

      const tmpVector = new THREE.Vector3()
      const tmpVector2 = new THREE.Vector3()

      //Crea los controles del mouse:
      let xa = 0;
      let ya = 0;
      onmousedown = () => {
        if (document.pointerLockElement === document.body || document.mozPointerLockElement === document.body) {
        } else {
          document.body.requestPointerLock()
        }
      };
      onmousemove = event => {
        if (document.pointerLockElement === document.body || document.mozPointerLockElement === document.body) {
          xa -= 0.01 * event.movementX;
          if (-1.5 < ya && 0 < event.movementY) {
            ya -= 0.005 * event.movementY
          }
          if (ya < 1.5 && event.movementY < 0) {
            ya -= 0.005 * event.movementY
          }
        }
      };

      //Crear los controles de teclado:
      let k = [];
      onkeydown = onkeyup = e => {
        k[e.keyCode] = e.type == "keydown";
      };

      // Crear una función de animación
      const animate = () => {
        // Ajustar el canvas...
        renderer.setSize(innerWidth, innerHeight)
        camera.aspect = innerWidth / innerHeight
        camera.updateProjectionMatrix()



        // Ajustar los controles...
        if (-1.5 > ya) {
          ya = -1.5
        }
        if (1.5 < ya) {
          ya = 1.5
        }
        camera.lookAt(
          camera.position.x + Math.sin(xa) * Math.cos(ya),
          camera.position.y + Math.sin(ya),
          camera.position.z + Math.cos(xa) * Math.cos(ya)
        );

	    // Colisiones:
	    for(let i1 in trunksChunks){
          if(distance3d({x:trunksChunks[i1].position.x,y:0,z:trunksChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<24){
            console.log("Collision.")
            camera.position.x+=(camera.position.x-trunksChunks[i1].position.x)/distance3d({x:trunksChunks[i1].position.x,y:0,z:trunksChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.z+=(camera.position.z-trunksChunks[i1].position.z)/distance3d({x:trunksChunks[i1].position.x,y:0,z:trunksChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
          }
        }
        for(let i1 in brownstoneChunks){
          if(distance3d({x:brownstoneChunks[i1].position.x,y:0,z:brownstoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<24){
            console.log("Collision.")
            module=distance3d({x:brownstoneChunks[i1].position.x,y:0,z:brownstoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.x+=(camera.position.x-brownstoneChunks[i1].position.x)/module
            camera.position.z+=(camera.position.z-brownstoneChunks[i1].position.z)/module
          }
        }
        for(let i1 in limestoneChunks){
          if(distance3d({x:limestoneChunks[i1].position.x,y:0,z:limestoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<24){
            console.log("Collision.")
            module=distance3d({x:limestoneChunks[i1].position.x,y:0,z:limestoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.x+=(camera.position.x-limestoneChunks[i1].position.x)/module
            camera.position.z+=(camera.position.z-limestoneChunks[i1].position.z)/module
          }
        }
        for(let i1 in graniteChunks){
          if(distance3d({x:graniteChunks[i1].position.x,y:0,z:graniteChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<24){
            console.log("Collision.")
            module=distance3d({x:graniteChunks[i1].position.x,y:0,z:graniteChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.x+=(camera.position.x-graniteChunks[i1].position.x)/module
            camera.position.z+=(camera.position.z-graniteChunks[i1].position.z)/module
          }
        }

        // Establecer la velocidad predeterminada
	    if(k[81]){
	    	walkspeed=1
	    }else{
	    	walkspeed=0.5
	    }

	    // Mover el jugador
	    if (k[65]) {
	      camera.position.x += walkspeed * Math.cos(xa)
	      camera.position.z -= walkspeed * Math.sin(xa)
	    }
	    if (k[87]) {
	      camera.position.x += walkspeed * Math.sin(xa)
	      camera.position.z += walkspeed * Math.cos(xa)
	    }
	    if (k[68]) {
	      camera.position.x -= walkspeed * Math.cos(xa)
	      camera.position.z += walkspeed * Math.sin(xa)
	    }
	    if (k[83]) {
	      camera.position.x -= walkspeed * Math.sin(xa)
	      camera.position.z -= walkspeed * Math.cos(xa)
	    }

        // Manteniendo la fuerza de sujección del Jugador contra el suelo:
      	camera.position.y = getSurfaceAt(camera.position.x, camera.position.z) + 30

        // Generar nuevos fragmentos de terreno a medida que el jugador se mueve
        const playerChunkX = Math.floor(camera.position.x / chunkSize) * chunkSize
        const playerChunkZ = Math.floor(camera.position.z / chunkSize) * chunkSize

        for (let x = -chunkSize; x <= chunkSize; x += chunkSize) {
          for (let z = -chunkSize; z <= chunkSize; z += chunkSize) {
            const chunkX = playerChunkX + x
            const chunkZ = playerChunkZ + z

            if (!terrainChunks.some(chunk => chunk.position.x === chunkX && chunk.position.z === chunkZ)) {
              generateTerrainChunk(chunkX, chunkZ);
            }
          }
        }

        // Eliminar fragmentos de terreno invisibles
        removeInvisibleChunks()

        // Llamada recursiva para la próxima animación
        requestAnimationFrame(animate)
        renderer.render(scene, camera)
      }

      // Iniciar la animación
      animate();
    };
  </script>
</head>
<body>
</body>
</html>

And with your command:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    body {
      overflow: hidden;
      margin: 0;
    }
  </style>
<div id="bancode_13024" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13024" async></script>
</div>
<div id="bancode_13177" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13177" async></script>
</div>
<br>
<div id="bancode_13178" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13178" async></script>
</div>
<div id="bancode_13179" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13179" async></script>
</div>
  <script src="perlin.js"></script>
  <script src="stats.js"></script>
  <script type="module">
  import * as THREE from "https://cdnjs.cloudflare.com/ajax/libs/three.js/0.162.0/three.module.js"
var stats = new Stats();
stats.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
document.body.appendChild( stats.dom )
function animate() {
  stats.begin()
  // monitored code goes here
  stats.end()
  requestAnimationFrame( animate )
}
    let walkspeed=0
    //Créditos a ChatGPT-1 por el aporte con sus sugerencias e ideas:
    onload = () => {
      // Ajustar las funciones matemáticas iniciales:
      let seed = Math.random();
      const noise2d = (i, k) => {
        return noise.simplex2(i, k + seed);
      }
      const getSurfaceAt = (i, k) => {
        return noise2d(i / 10000, k / 10000) * 2000 + 
                noise2d(i / 1000, k / 1000) * 200 + 
                noise2d(i / 100, k / 100) * 20 + 
                noise2d(i / 10, k / 10) * 2;
      }
      const rand=()=>{
        return Math.random()
      }
      const distance2d=(obj1,obj2)=>{return ((obj1.x-obj2.x)**2+(obj1.y-obj2.y)**2)**0.5}
      const distance3d=(obj1,obj2)=>{return ((obj1.x-obj2.x)**2+(obj1.y-obj2.y)**2+(obj1.z-obj2.z)**2)**0.5}
      //Colocar el absorbe-texturas lo primero:
      const textureLoader = new THREE.TextureLoader();
      // Ajustar la preparación del canvas:
      const scene = new THREE.Scene()
      const camera = new THREE.PerspectiveCamera(75, innerWidth / innerHeight, 0.1, 100000)
      const renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight)
      renderer.shadowMap.enabled = true;
      renderer.shadowMap.type = THREE.PCFSoftShadowMap;
      document.body.appendChild(renderer.domElement)
            
      scene.background = new THREE.Color("rgb(0,127,255)")
      let rd = 8000

	  // White directional light at half intensity shining from the top.
	  const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
      directionalLight.castShadows=true
	  scene.add( directionalLight );
      directionalLight.shadow.camera.left = -500; // default -5
      directionalLight.shadow.camera.right = 500; // default 5
      directionalLight.shadow.camera.top = 500; // default 5
      directionalLight.shadow.camera.bottom = -500; // default -5
	  const ambientLight = new THREE.AmbientLight( 0xffffff, 0.03);
	  scene.add( ambientLight );

      scene.fog = new THREE.Fog(new THREE.Color("rgb(0,127,255)"), rd/10, rd*4/10)
	  directionalLight.shadow.mapSize.width = 1024; // default is 512
	  directionalLight.shadow.mapSize.height = 1024; // default is 512
      const terrainChunks = []
      const leavesChunks = []
      const trunksChunks = []
      const brownstoneChunks = []
      const graniteChunks = []
      const limestoneChunks = []
      const microleavesChunks = []
      const leavesMaterialChunks = []
      const chunkSize = rd * 0.85 // Tamaño del fragmento de terreno

      // Función para generar un nuevo fragmento de terreno
      const generateTerrainChunk = (x, z) => {
      	const chunkAccuracy = 1
        const terrainChunkGeometry = new THREE.PlaneGeometry(chunkSize, chunkSize, chunkAccuracy * 128, chunkAccuracy * 128)
        terrainChunkGeometry.rotateX(-Math.PI / 2);
        //Geneerar las piedras:
        const brownstoneTexture = textureLoader.load("brownstone.png")
        brownstoneTexture.wrapS = THREE.RepeatWrapping
        brownstoneTexture.wrapT = THREE.RepeatWrapping
        brownstoneTexture.repeat.set(4, 4)
        const brownstoneChunkMaterial = new THREE.MeshLambertMaterial({ map: brownstoneTexture, side: THREE.DoubleSide })

        const graniteTexture = textureLoader.load("Granite.jpg")
        graniteTexture.wrapS = THREE.RepeatWrapping
        graniteTexture.wrapT = THREE.RepeatWrapping
        graniteTexture.repeat.set(4, 4)
        const graniteChunkMaterial = new THREE.MeshLambertMaterial({ map: graniteTexture, side: THREE.DoubleSide })

        const leavesTexture = textureLoader.load("leaves.jpg");
        leavesTexture.wrapS = THREE.RepeatWrapping
        leavesTexture.wrapT = THREE.RepeatWrapping
        leavesTexture.repeat.set(4, 4)
        const leavesMaterial = new THREE.MeshLambertMaterial({ map: leavesTexture, side: THREE.DoubleSide })
        
        const limestoneTexture = textureLoader.load("limestone.jpg");
        limestoneTexture.wrapS = THREE.RepeatWrapping
        limestoneTexture.wrapT = THREE.RepeatWrapping
        limestoneTexture.repeat.set(4, 4)
        const limestoneChunkMaterial = new THREE.MeshLambertMaterial({ map: limestoneTexture, side: THREE.DoubleSide })
        //Generar el suelo:
        const dirtTexture = textureLoader.load("grass.jpg")
        dirtTexture.wrapS = THREE.RepeatWrapping
        dirtTexture.wrapT = THREE.RepeatWrapping
        dirtTexture.repeat.set(512, 512)
        const terrainChunkMaterial = new THREE.MeshLambertMaterial({ map: dirtTexture, side: THREE.DoubleSide });
        const terrainChunkMesh = new THREE.Mesh(terrainChunkGeometry, terrainChunkMaterial)
        terrainChunkMesh.position.set(x, -20, z)
        scene.add(terrainChunkMesh)
        terrainChunks.push(terrainChunkMesh)
        //Generar el terreno:
        const terrainChunkVertices = terrainChunkGeometry.attributes.position.array
        for (let i = 0; i < terrainChunkVertices.length; i += 3) {
          const chunkX = terrainChunkVertices[i] + x
          const chunkZ = terrainChunkVertices[i + 2] + z
          const y = getSurfaceAt(chunkX, chunkZ)
          terrainChunkVertices[i + 1] = y
          //Generar las rocas.
          const gRoca=()=>{
            let geometry=new THREE.SphereGeometry(20)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*2-1 // Ajusta según el rango deseado
              vertex.y += rand()*2+vertex.y // Ajusta según el rango deseado
              vertex.z += rand()*2-1 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.castShadow = true;
			geometry.receiveShadow = true;
            return geometry
          }
          //Generar las hojas.
          const gHojas=()=>{
            let geometry=new THREE.SphereGeometry(100)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*100-50 // Ajusta según el rango deseado
              vertex.y += rand()*100-50 // Ajusta según el rango deseado
              vertex.z += rand()*100-50 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.castShadow = true;
			geometry.receiveShadow = true;
            return geometry
          }
          const gTronco=()=>{
            let geometry=new THREE.CylinderGeometry(20, 20, 200, 32)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*8-4 // Ajusta según el rango deseado
              vertex.y += 0 // Ajusta según el rango deseado
              vertex.z += rand()*8-4 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.castShadow = true;
			geometry.receiveShadow = true;
            return geometry
          }
          if (Math.random() < 0.0025/chunkAccuracy/chunkAccuracy) {
            const limestone_meshMaterial = new THREE.Mesh(gRoca(),limestoneChunkMaterial)
            limestone_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) - 10, chunkZ)
            scene.add(limestone_meshMaterial)
            limestoneChunks.push(limestone_meshMaterial)
          }
          if (Math.random() < 0.0025/chunkAccuracy/chunkAccuracy) {
            const brownstone_meshMaterial = new THREE.Mesh(gRoca(),brownstoneChunkMaterial)
            brownstone_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) - 10, chunkZ)
            scene.add(brownstone_meshMaterial)
            brownstoneChunks.push(brownstone_meshMaterial)
          }
          if (Math.random() < 0.0025/chunkAccuracy/chunkAccuracy) {
            const granite_meshMaterial = new THREE.Mesh(gRoca(),graniteChunkMaterial)
            granite_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) - 10, chunkZ)
            scene.add(granite_meshMaterial)
            graniteChunks.push(granite_meshMaterial)
          }
          //Generar los árboles:
          if (rand() < 0.025/chunkAccuracy/chunkAccuracy) {
            const trunk_meshMaterial = new THREE.Mesh(gTronco(), trunk_material)
            trunk_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) + 25, chunkZ)
            scene.add(trunk_meshMaterial)
            trunksChunks.push(trunk_meshMaterial)
            const leavesMaterial_meshMaterial = new THREE.Mesh(gHojas(),leavesMaterial)
            leavesMaterial_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) + 200, chunkZ)
            scene.add(leavesMaterial_meshMaterial)
            leavesMaterialChunks.push(leavesMaterial_meshMaterial)
          }
        }
      }

      let trunk_texture = textureLoader.load("trunk.jpg")
      trunk_texture.wrapS = THREE.RepeatWrapping
      trunk_texture.wrapT = THREE.RepeatWrapping
      trunk_texture.repeat.set(1, 2.5)
      let trunk_material = new THREE.MeshLambertMaterial({ map: trunk_texture, side: THREE.DoubleSide })

      // Función para eliminar fragmentos de terreno que ya no son visibles
      const removeInvisibleChunks = () => {
        const visibleChunks = []
        camera.getWorldPosition(tmpVector)

        const allChunks = terrainChunks.concat(leavesChunks, trunksChunks, brownstoneChunks, graniteChunks, limestoneChunks, microleavesChunks)

        for (const chunk of allChunks) {
          chunk.getWorldPosition(tmpVector2)
          if (tmpVector.distanceTo(tmpVector2) < chunkSize * 1.5) {
            visibleChunks.push(chunk)
          } else {
            scene.remove(chunk)
            chunk.geometry.dispose()
          }
        }
      };

      const tmpVector = new THREE.Vector3()
      const tmpVector2 = new THREE.Vector3()

      //Crea los controles del mouse:
      let xa = 0;
      let ya = 0;
      onmousedown = () => {
        if (document.pointerLockElement === document.body || document.mozPointerLockElement === document.body) {
        } else {
          document.body.requestPointerLock()
        }
      };
      onmousemove = event => {
        if (document.pointerLockElement === document.body || document.mozPointerLockElement === document.body) {
          xa -= 0.01 * event.movementX;
          if (-1.5 < ya && 0 < event.movementY) {
            ya -= 0.005 * event.movementY
          }
          if (ya < 1.5 && event.movementY < 0) {
            ya -= 0.005 * event.movementY
          }
        }
      };

      //Crear los controles de teclado:
      let k = [];
      onkeydown = onkeyup = e => {
        k[e.keyCode] = e.type == "keydown";
      };

      // Crear una función de animación
      const animate = () => {
        // Ajustar el canvas...
        renderer.setSize(innerWidth, innerHeight)
        camera.aspect = innerWidth / innerHeight
        camera.updateProjectionMatrix()



        // Ajustar los controles...
        if (-1.5 > ya) {
          ya = -1.5
        }
        if (1.5 < ya) {
          ya = 1.5
        }
        camera.lookAt(
          camera.position.x + Math.sin(xa) * Math.cos(ya),
          camera.position.y + Math.sin(ya),
          camera.position.z + Math.cos(xa) * Math.cos(ya)
        );

	    // Colisiones:
	    for(let i1 in trunksChunks){
          if(distance3d({x:trunksChunks[i1].position.x,y:0,z:trunksChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<24){
            console.log("Collision.")
            camera.position.x+=(camera.position.x-trunksChunks[i1].position.x)/distance3d({x:trunksChunks[i1].position.x,y:0,z:trunksChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.z+=(camera.position.z-trunksChunks[i1].position.z)/distance3d({x:trunksChunks[i1].position.x,y:0,z:trunksChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
          }
        }
        for(let i1 in brownstoneChunks){
          if(distance3d({x:brownstoneChunks[i1].position.x,y:0,z:brownstoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<24){
            console.log("Collision.")
            module=distance3d({x:brownstoneChunks[i1].position.x,y:0,z:brownstoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.x+=(camera.position.x-brownstoneChunks[i1].position.x)/module
            camera.position.z+=(camera.position.z-brownstoneChunks[i1].position.z)/module
          }
        }
        for(let i1 in limestoneChunks){
          if(distance3d({x:limestoneChunks[i1].position.x,y:0,z:limestoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<24){
            console.log("Collision.")
            module=distance3d({x:limestoneChunks[i1].position.x,y:0,z:limestoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.x+=(camera.position.x-limestoneChunks[i1].position.x)/module
            camera.position.z+=(camera.position.z-limestoneChunks[i1].position.z)/module
          }
        }
        for(let i1 in graniteChunks){
          if(distance3d({x:graniteChunks[i1].position.x,y:0,z:graniteChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<24){
            console.log("Collision.")
            module=distance3d({x:graniteChunks[i1].position.x,y:0,z:graniteChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.x+=(camera.position.x-graniteChunks[i1].position.x)/module
            camera.position.z+=(camera.position.z-graniteChunks[i1].position.z)/module
          }
        }

        // Establecer la velocidad predeterminada
	    if(k[81]){
	    	walkspeed=1
	    }else{
	    	walkspeed=0.5
	    }

	    // Mover el jugador
	    if (k[65]) {
	      camera.position.x += walkspeed * Math.cos(xa)
	      camera.position.z -= walkspeed * Math.sin(xa)
	    }
	    if (k[87]) {
	      camera.position.x += walkspeed * Math.sin(xa)
	      camera.position.z += walkspeed * Math.cos(xa)
	    }
	    if (k[68]) {
	      camera.position.x -= walkspeed * Math.cos(xa)
	      camera.position.z += walkspeed * Math.sin(xa)
	    }
	    if (k[83]) {
	      camera.position.x -= walkspeed * Math.sin(xa)
	      camera.position.z -= walkspeed * Math.cos(xa)
	    }

        // Manteniendo la fuerza de sujección del Jugador contra el suelo:
      	camera.position.y = getSurfaceAt(camera.position.x, camera.position.z) + 30

        // Generar nuevos fragmentos de terreno a medida que el jugador se mueve
        const playerChunkX = Math.floor(camera.position.x / chunkSize) * chunkSize
        const playerChunkZ = Math.floor(camera.position.z / chunkSize) * chunkSize

        for (let x = -chunkSize; x <= chunkSize; x += chunkSize) {
          for (let z = -chunkSize; z <= chunkSize; z += chunkSize) {
            const chunkX = playerChunkX + x
            const chunkZ = playerChunkZ + z

            if (!terrainChunks.some(chunk => chunk.position.x === chunkX && chunk.position.z === chunkZ)) {
              generateTerrainChunk(chunkX, chunkZ);
            }
          }
        }

        // Eliminar fragmentos de terreno invisibles
        removeInvisibleChunks()

        scene.add( new THREE.CameraHelper( directionalLight.shadow.camera ) );

        // Llamada recursiva para la próxima animación
        requestAnimationFrame(animate)
        renderer.render(scene, camera)
      }

      // Iniciar la animación
      animate();
    };
  </script>
</head>
<body>
</body>
</html>

You should set the properties to true for all instances of THREE.Mesh.

My code is this:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    body {
      overflow: hidden;
      margin: 0;
    }
  </style>
<div id="bancode_13024" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13024" async></script>
</div>
<div id="bancode_13177" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13177" async></script>
</div>
<br>
<div id="bancode_13178" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13178" async></script>
</div>
<div id="bancode_13179" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13179" async></script>
</div>
  <script src="perlin.js"></script>
  <script src="stats.js"></script>
  <script type="module">
  import * as THREE from "https://cdnjs.cloudflare.com/ajax/libs/three.js/0.162.0/three.module.js"
    var stats = new Stats();
    stats.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
    document.body.appendChild( stats.dom )
    function animateb() {
      stats.begin()
      // monitored code goes here
      stats.end()
      requestAnimationFrame( animateb )
    }
    animateb()
    let walkspeed=0
    //Créditos a ChatGPT-1 por el aporte con sus sugerencias e ideas:
    onload = () => {
      // Ajustar las funciones matemáticas iniciales:
      let seed = Math.random();
      const noise2d = (i, k) => {
        return noise.simplex2(i, k + seed);
      }
      const getSurfaceAt = (i, k) => {
        return noise2d(i / 10000, k / 10000) * 2000 + 
                noise2d(i / 1000, k / 1000) * 200 + 
                noise2d(i / 100, k / 100) * 20 + 
                noise2d(i / 10, k / 10) * 2;
      }
      const rand=()=>{
        return Math.random()
      }
      const distance2d=(obj1,obj2)=>{return ((obj1.x-obj2.x)**2+(obj1.y-obj2.y)**2)**0.5}
      const distance3d=(obj1,obj2)=>{return ((obj1.x-obj2.x)**2+(obj1.y-obj2.y)**2+(obj1.z-obj2.z)**2)**0.5}
      //Colocar el absorbe-texturas lo primero:
      const textureLoader = new THREE.TextureLoader();
      // Ajustar la preparación del canvas:
      const scene = new THREE.Scene()
      const camera = new THREE.PerspectiveCamera(75, innerWidth / innerHeight, 0.1, 100000)
      const renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight)
      renderer.shadowMap.enabled = true;
      renderer.shadowMap.type = THREE.PCFSoftShadowMap;
      document.body.appendChild(renderer.domElement)
            
      scene.background = new THREE.Color("rgb(0,127,255)")
      let rd = 8000

	  // White directional light at half intensity shining from the top.
	  const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
      directionalLight.castShadows=true
	  scene.add( directionalLight );
      directionalLight.shadow.camera.left = -500; // default -5
      directionalLight.shadow.camera.right = 500; // default 5
      directionalLight.shadow.camera.top = 500; // default 5
      directionalLight.shadow.camera.bottom = -500; // default -5
	  const ambientLight = new THREE.AmbientLight( 0xffffff, 0.03);
	  scene.add( ambientLight );

      scene.fog = new THREE.Fog(new THREE.Color("rgb(0,127,255)"), rd/10, rd*4/10)
	  directionalLight.shadow.mapSize.width = 1024; // default is 512
	  directionalLight.shadow.mapSize.height = 1024; // default is 512
      const terrainChunks = []
      const leavesChunks = []
      const trunksChunks = []
      const brownstoneChunks = []
      const graniteChunks = []
      const limestoneChunks = []
      const microleavesChunks = []
      const leavesMaterialChunks = []
      const chunkSize = rd * 0.85 // Tamaño del fragmento de terreno

      // Función para generar un nuevo fragmento de terreno
      const generateTerrainChunk = (x, z) => {
      	const chunkAccuracy = 1
        const terrainChunkGeometry = new THREE.PlaneGeometry(chunkSize, chunkSize, chunkAccuracy * 128, chunkAccuracy * 128)
        terrainChunkGeometry.rotateX(-Math.PI / 2);
        //Geneerar las piedras:
        const brownstoneTexture = textureLoader.load("brownstone.png")
        brownstoneTexture.wrapS = THREE.RepeatWrapping
        brownstoneTexture.wrapT = THREE.RepeatWrapping
        brownstoneTexture.repeat.set(4, 4)
        const brownstoneChunkMaterial = new THREE.MeshLambertMaterial({ map: brownstoneTexture, side: THREE.DoubleSide })

        const graniteTexture = textureLoader.load("Granite.jpg")
        graniteTexture.wrapS = THREE.RepeatWrapping
        graniteTexture.wrapT = THREE.RepeatWrapping
        graniteTexture.repeat.set(4, 4)
        const graniteChunkMaterial = new THREE.MeshLambertMaterial({ map: graniteTexture, side: THREE.DoubleSide })

        const leavesTexture = textureLoader.load("leaves.jpg");
        leavesTexture.wrapS = THREE.RepeatWrapping
        leavesTexture.wrapT = THREE.RepeatWrapping
        leavesTexture.repeat.set(4, 4)
        const leavesMaterial = new THREE.MeshLambertMaterial({ map: leavesTexture, side: THREE.DoubleSide })
        
        const limestoneTexture = textureLoader.load("limestone.jpg");
        limestoneTexture.wrapS = THREE.RepeatWrapping
        limestoneTexture.wrapT = THREE.RepeatWrapping
        limestoneTexture.repeat.set(4, 4)
        const limestoneChunkMaterial = new THREE.MeshLambertMaterial({ map: limestoneTexture, side: THREE.DoubleSide })
        //Generar el suelo:
        const dirtTexture = textureLoader.load("grass.jpg")
        dirtTexture.wrapS = THREE.RepeatWrapping
        dirtTexture.wrapT = THREE.RepeatWrapping
        dirtTexture.repeat.set(512, 512)
        const terrainChunkMaterial = new THREE.MeshLambertMaterial({ map: dirtTexture, side: THREE.DoubleSide });
        const terrainChunkMesh = new THREE.Mesh(terrainChunkGeometry, terrainChunkMaterial)
        terrainChunkMesh.position.set(x, -20, z)
        scene.add(terrainChunkMesh)
        terrainChunks.push(terrainChunkMesh)
        //Generar el terreno:
        const terrainChunkVertices = terrainChunkGeometry.attributes.position.array
        for (let i = 0; i < terrainChunkVertices.length; i += 3) {
          const chunkX = terrainChunkVertices[i] + x
          const chunkZ = terrainChunkVertices[i + 2] + z
          const y = getSurfaceAt(chunkX, chunkZ)
          terrainChunkVertices[i + 1] = y
          //Generar las rocas.
          const gRoca=()=>{
            let geometry=new THREE.SphereGeometry(20)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*100-50 // Ajusta según el rango deseado
              vertex.y += rand()*100-50 + vertex.y // Ajusta según el rango deseado
              vertex.z += rand()*100-50 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.attributes.position.castShadow=true
			geometry.attributes.position.receiveShadow=true
            return geometry
          }
          //Generar las hojas.
          const gHojas=()=>{
            let geometry=new THREE.SphereGeometry(100)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*100-50 // Ajusta según el rango deseado
              vertex.y += rand()*100-50 // Ajusta según el rango deseado
              vertex.z += rand()*100-50 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.attributes.position.castShadow=true
			geometry.attributes.position.receiveShadow=true
            return geometry
          }
          const gTronco=()=>{
            let geometry=new THREE.CylinderGeometry(20, 20, 200, 32)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*8-4 // Ajusta según el rango deseado
              vertex.y += 0 // Ajusta según el rango deseado
              vertex.z += rand()*8-4 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.attributes.position.castShadow=true
			geometry.attributes.position.receiveShadow=true
            return geometry
          }
          //Generar las rocas:
          if (Math.random() < 0.005/chunkAccuracy/chunkAccuracy) {
            const limestone_meshMaterial = new THREE.Mesh(gRoca(),limestoneChunkMaterial)
            limestone_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) - 10, chunkZ)
            scene.add(limestone_meshMaterial)
            limestoneChunks.push(limestone_meshMaterial)
          }
          if (Math.random() < 0.005/chunkAccuracy/chunkAccuracy) {
            const brownstone_meshMaterial = new THREE.Mesh(gRoca(),brownstoneChunkMaterial)
            brownstone_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) - 10, chunkZ)
            scene.add(brownstone_meshMaterial)
            brownstoneChunks.push(brownstone_meshMaterial)
          }
          if (Math.random() < 0.005/chunkAccuracy/chunkAccuracy) {
            const granite_meshMaterial = new THREE.Mesh(gRoca(),graniteChunkMaterial)
            granite_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) - 10, chunkZ)
            scene.add(granite_meshMaterial)
            graniteChunks.push(granite_meshMaterial)
          }
          //Generar los árboles:
          if (rand() < 0.005/chunkAccuracy/chunkAccuracy) {
            const trunk_meshMaterial = new THREE.Mesh(gTronco(), trunk_material)
            trunk_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) + 25, chunkZ)
            scene.add(trunk_meshMaterial)
            trunksChunks.push(trunk_meshMaterial)
            const leavesMaterial_meshMaterial = new THREE.Mesh(gHojas(),leavesMaterial)
            leavesMaterial_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) + 200, chunkZ)
            scene.add(leavesMaterial_meshMaterial)
            leavesMaterialChunks.push(leavesMaterial_meshMaterial)
          }
        }
		terrainChunkMesh.attributes.position.castShadow=true
		terrainChunkMesh.attributes.position.receiveShadow=true
      }

      let trunk_texture = textureLoader.load("trunk.jpg")
      trunk_texture.wrapS = THREE.RepeatWrapping
      trunk_texture.wrapT = THREE.RepeatWrapping
      trunk_texture.repeat.set(1, 2.5)
      let trunk_material = new THREE.MeshLambertMaterial({ map: trunk_texture, side: THREE.DoubleSide })

      // Función para eliminar fragmentos de terreno que ya no son visibles
      const removeInvisibleChunks = () => {
        const visibleChunks = []
        camera.getWorldPosition(tmpVector)

        const allChunks = terrainChunks.concat(leavesChunks, trunksChunks, brownstoneChunks, graniteChunks, limestoneChunks, microleavesChunks)

        for (const chunk of allChunks) {
          chunk.getWorldPosition(tmpVector2)
          if (tmpVector.distanceTo(tmpVector2) < chunkSize * 1.5) {
            visibleChunks.push(chunk)
          } else {
            scene.remove(chunk)
            chunk.geometry.dispose()
          }
        }
      };

      const tmpVector = new THREE.Vector3()
      const tmpVector2 = new THREE.Vector3()

      //Crea los controles del mouse:
      let xa = 0;
      let ya = 0;
      onmousedown = () => {
        if (document.pointerLockElement === document.body || document.mozPointerLockElement === document.body) {
        } else {
          document.body.requestPointerLock()
        }
      };
      onmousemove = event => {
        if (document.pointerLockElement === document.body || document.mozPointerLockElement === document.body) {
          xa -= 0.01 * event.movementX;
          if (-1.5 < ya && 0 < event.movementY) {
            ya -= 0.005 * event.movementY
          }
          if (ya < 1.5 && event.movementY < 0) {
            ya -= 0.005 * event.movementY
          }
        }
      };

      //Crear los controles de teclado:
      let k = [];
      onkeydown = onkeyup = e => {
        k[e.keyCode] = e.type == "keydown";
      };

      // Crear una función de animación
      const animate = () => {
        // Ajustar el canvas...
        renderer.setSize(innerWidth, innerHeight)
        camera.aspect = innerWidth / innerHeight
        camera.updateProjectionMatrix()



        // Ajustar los controles...
        if (-1.5 > ya) {
          ya = -1.5
        }
        if (1.5 < ya) {
          ya = 1.5
        }
        camera.lookAt(
          camera.position.x + Math.sin(xa) * Math.cos(ya),
          camera.position.y + Math.sin(ya),
          camera.position.z + Math.cos(xa) * Math.cos(ya)
        );

	    // Colisiones:
	    for(let i1 in trunksChunks){
          if(distance3d({x:trunksChunks[i1].position.x,y:0,z:trunksChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<24){
            console.log("Collision.")
            camera.position.x+=(camera.position.x-trunksChunks[i1].position.x)/distance3d({x:trunksChunks[i1].position.x,y:0,z:trunksChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.z+=(camera.position.z-trunksChunks[i1].position.z)/distance3d({x:trunksChunks[i1].position.x,y:0,z:trunksChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
          }
        }
        for(let i1 in brownstoneChunks){
          if(distance3d({x:brownstoneChunks[i1].position.x,y:0,z:brownstoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<64){
            console.log("Collision.")
            let module=distance3d({x:brownstoneChunks[i1].position.x,y:0,z:brownstoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.x+=(camera.position.x-brownstoneChunks[i1].position.x)/module
            camera.position.z+=(camera.position.z-brownstoneChunks[i1].position.z)/module
          }
        }
        for(let i1 in limestoneChunks){
          if(distance3d({x:limestoneChunks[i1].position.x,y:0,z:limestoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<64){
            console.log("Collision.")
            let module=distance3d({x:limestoneChunks[i1].position.x,y:0,z:limestoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.x+=(camera.position.x-limestoneChunks[i1].position.x)/module
            camera.position.z+=(camera.position.z-limestoneChunks[i1].position.z)/module
          }
        }
        for(let i1 in graniteChunks){
          if(distance3d({x:graniteChunks[i1].position.x,y:0,z:graniteChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<64){
            console.log("Collision.")
            let module=distance3d({x:graniteChunks[i1].position.x,y:0,z:graniteChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.x+=(camera.position.x-graniteChunks[i1].position.x)/module
            camera.position.z+=(camera.position.z-graniteChunks[i1].position.z)/module
          }
        }

        // Establecer la velocidad predeterminada
	    if(k[81]){
	    	walkspeed=1
	    }else{
	    	walkspeed=0.5
	    }

	    // Mover el jugador
	    if (k[65]) {
	      camera.position.x += walkspeed * Math.cos(xa)
	      camera.position.z -= walkspeed * Math.sin(xa)
	    }
	    if (k[87]) {
	      camera.position.x += walkspeed * Math.sin(xa)
	      camera.position.z += walkspeed * Math.cos(xa)
	    }
	    if (k[68]) {
	      camera.position.x -= walkspeed * Math.cos(xa)
	      camera.position.z += walkspeed * Math.sin(xa)
	    }
	    if (k[83]) {
	      camera.position.x -= walkspeed * Math.sin(xa)
	      camera.position.z -= walkspeed * Math.cos(xa)
	    }

        // Manteniendo la fuerza de sujección del Jugador contra el suelo:
      	camera.position.y = getSurfaceAt(camera.position.x, camera.position.z) + 10

        // Generar nuevos fragmentos de terreno a medida que el jugador se mueve
        const playerChunkX = Math.floor(camera.position.x / chunkSize) * chunkSize
        const playerChunkZ = Math.floor(camera.position.z / chunkSize) * chunkSize

        for (let x = -chunkSize; x <= chunkSize; x += chunkSize) {
          for (let z = -chunkSize; z <= chunkSize; z += chunkSize) {
            const chunkX = playerChunkX + x
            const chunkZ = playerChunkZ + z

            if (!terrainChunks.some(chunk => chunk.position.x === chunkX && chunk.position.z === chunkZ)) {
              generateTerrainChunk(chunkX, chunkZ);
            }
          }
        }

        // Eliminar fragmentos de terreno invisibles
        removeInvisibleChunks()
        scene.add( new THREE.CameraHelper( directionalLight.shadow.camera ) );
        // Llamada recursiva para la próxima animación
        requestAnimationFrame(animate)
        renderer.render(scene, camera)
      }

      // Iniciar la animación
      animate();
    };
  </script>
</head>
<body>
</body>
</html>

And the result is this:

v11/:226 Uncaught TypeError: Cannot read properties of undefined (reading ‘position’)
at generateTerrainChunk (v11/:226:31)
at animate (v11/:377:15)
at onload (v11/:391:7)

Now this is the image:

And this is my code:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    body {
      overflow: hidden;
      margin: 0;
    }
  </style>
<div id="bancode_13024" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13024" async></script>
</div>
<div id="bancode_13177" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13177" async></script>
</div>
<br>
<div id="bancode_13178" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13178" async></script>
</div>
<div id="bancode_13179" style="display:inline-block;width:40%">
    <script src="//multibux.org/bancode.php?id=13179" async></script>
</div>
  <script src="perlin.js"></script>
  <script src="stats.js"></script>
  <script type="module">
  import * as THREE from "https://cdnjs.cloudflare.com/ajax/libs/three.js/0.162.0/three.module.js"
    var stats = new Stats();
    stats.showPanel( 0 ); // 0: fps, 1: ms, 2: mb, 3+: custom
    document.body.appendChild( stats.dom )
    function animateb() {
      stats.begin()
      // monitored code goes here
      stats.end()
      requestAnimationFrame( animateb )
    }
    animateb()
    let walkspeed=0
    //Créditos a ChatGPT-1 por el aporte con sus sugerencias e ideas:
    onload = () => {
      // Ajustar las funciones matemáticas iniciales:
      let seed = Math.random();
      const noise2d = (i, k) => {
        return noise.simplex2(i, k + seed);
      }
      const getSurfaceAt = (i, k) => {
        return noise2d(i / 10000, k / 10000) * 2000 + 
                noise2d(i / 1000, k / 1000) * 200 + 
                noise2d(i / 100, k / 100) * 20 + 
                noise2d(i / 10, k / 10) * 2;
      }
      const rand=()=>{
        return Math.random()
      }
      const distance2d=(obj1,obj2)=>{return ((obj1.x-obj2.x)**2+(obj1.y-obj2.y)**2)**0.5}
      const distance3d=(obj1,obj2)=>{return ((obj1.x-obj2.x)**2+(obj1.y-obj2.y)**2+(obj1.z-obj2.z)**2)**0.5}
      //Colocar el absorbe-texturas lo primero:
      const textureLoader = new THREE.TextureLoader();
      // Ajustar la preparación del canvas:
      const scene = new THREE.Scene()
      const camera = new THREE.PerspectiveCamera(75, innerWidth / innerHeight, 0.1, 100000)
      const renderer = new THREE.WebGLRenderer();
      renderer.setSize(window.innerWidth, window.innerHeight)
      renderer.shadowMap.enabled = true;
      renderer.shadowMap.type = THREE.PCFSoftShadowMap;
      document.body.appendChild(renderer.domElement)
            
      scene.background = new THREE.Color("rgb(0,127,255)")
      let rd = 8000

	  // White directional light at half intensity shining from the top.
	  const directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
      directionalLight.castShadows=true
	  scene.add( directionalLight );
      directionalLight.shadow.camera.left = -500; // default -5
      directionalLight.shadow.camera.right = 500; // default 5
      directionalLight.shadow.camera.top = 500; // default 5
      directionalLight.shadow.camera.bottom = -500; // default -5
	  const ambientLight = new THREE.AmbientLight( 0xffffff, 0.03);
	  scene.add( ambientLight );

      scene.fog = new THREE.Fog(new THREE.Color("rgb(0,127,255)"), rd/10, rd*4/10)
	  directionalLight.shadow.mapSize.width = 1024; // default is 512
	  directionalLight.shadow.mapSize.height = 1024; // default is 512
      const terrainChunks = []
      const leavesChunks = []
      const trunksChunks = []
      const brownstoneChunks = []
      const graniteChunks = []
      const limestoneChunks = []
      const microleavesChunks = []
      const leavesMaterialChunks = []
      const chunkSize = rd * 0.85 // Tamaño del fragmento de terreno

      // Función para generar un nuevo fragmento de terreno
      const generateTerrainChunk = (x, z) => {
      	const chunkAccuracy = 1
        const terrainChunkGeometry = new THREE.PlaneGeometry(chunkSize, chunkSize, chunkAccuracy * 128, chunkAccuracy * 128)
        terrainChunkGeometry.rotateX(-Math.PI / 2);
        //Geneerar las piedras:
        const brownstoneTexture = textureLoader.load("brownstone.png")
        brownstoneTexture.wrapS = THREE.RepeatWrapping
        brownstoneTexture.wrapT = THREE.RepeatWrapping
        brownstoneTexture.repeat.set(4, 4)
        const brownstoneChunkMaterial = new THREE.MeshLambertMaterial({ map: brownstoneTexture, side: THREE.DoubleSide })

        const graniteTexture = textureLoader.load("Granite.jpg")
        graniteTexture.wrapS = THREE.RepeatWrapping
        graniteTexture.wrapT = THREE.RepeatWrapping
        graniteTexture.repeat.set(4, 4)
        const graniteChunkMaterial = new THREE.MeshLambertMaterial({ map: graniteTexture, side: THREE.DoubleSide })

        const leavesTexture = textureLoader.load("leaves.jpg");
        leavesTexture.wrapS = THREE.RepeatWrapping
        leavesTexture.wrapT = THREE.RepeatWrapping
        leavesTexture.repeat.set(4, 4)
        const leavesMaterial = new THREE.MeshLambertMaterial({ map: leavesTexture, side: THREE.DoubleSide })
        
        const limestoneTexture = textureLoader.load("limestone.jpg");
        limestoneTexture.wrapS = THREE.RepeatWrapping
        limestoneTexture.wrapT = THREE.RepeatWrapping
        limestoneTexture.repeat.set(4, 4)
        const limestoneChunkMaterial = new THREE.MeshLambertMaterial({ map: limestoneTexture, side: THREE.DoubleSide })
        //Generar el suelo:
        const dirtTexture = textureLoader.load("grass.jpg")
        dirtTexture.wrapS = THREE.RepeatWrapping
        dirtTexture.wrapT = THREE.RepeatWrapping
        dirtTexture.repeat.set(512, 512)
        const terrainChunkMaterial = new THREE.MeshLambertMaterial({ map: dirtTexture, side: THREE.DoubleSide });
        const terrainChunkMesh = new THREE.Mesh(terrainChunkGeometry, terrainChunkMaterial)
        terrainChunkMesh.position.set(x, -20, z)
        scene.add(terrainChunkMesh)
        terrainChunks.push(terrainChunkMesh)
        //Generar el terreno:
        const terrainChunkVertices = terrainChunkGeometry.attributes.position.array
        terrainChunkGeometry.attributes.position.array.castShadow=true
        terrainChunkGeometry.attributes.position.array.receiveShadow=true
        for (let i = 0; i < terrainChunkVertices.length; i += 3) {
          const chunkX = terrainChunkVertices[i] + x
          const chunkZ = terrainChunkVertices[i + 2] + z
          const y = getSurfaceAt(chunkX, chunkZ)
          terrainChunkVertices[i + 1] = y
          //Generar las rocas.
          const gRoca=()=>{
            let geometry=new THREE.SphereGeometry(20)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*100-50 // Ajusta según el rango deseado
              vertex.y += rand()*100-50 + vertex.y // Ajusta según el rango deseado
              vertex.z += rand()*100-50 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.attributes.position.castShadow=true
			geometry.attributes.position.receiveShadow=true
            return geometry
          }
          //Generar las hojas.
          const gHojas=()=>{
            let geometry=new THREE.SphereGeometry(100)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*100-50 // Ajusta según el rango deseado
              vertex.y += rand()*100-50 // Ajusta según el rango deseado
              vertex.z += rand()*100-50 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.attributes.position.castShadow=true
			geometry.attributes.position.receiveShadow=true
            return geometry
          }
          const gTronco=()=>{
            let geometry=new THREE.CylinderGeometry(20, 20, 200, 32)
            // Alterar las posiciones de los vértices de manera aleatoria
            const positionAttribute = geometry.attributes.position
            for (let i = 0; i < positionAttribute.count; i++) {
              const vertex = new THREE.Vector3()
              vertex.fromBufferAttribute(positionAttribute, i)
              vertex.x += rand()*8-4 // Ajusta según el rango deseado
              vertex.y += 0 // Ajusta según el rango deseado
              vertex.z += rand()*8-4 // Ajusta según el rango deseado
              positionAttribute.setXYZ(i, vertex.x, vertex.y, vertex.z)
            }
            positionAttribute.needsUpdate = true
            geometry.attributes.position.castShadow=true
			geometry.attributes.position.receiveShadow=true
            return geometry
          }
          //Generar las rocas:
          if (Math.random() < 0.005/chunkAccuracy/chunkAccuracy) {
            const limestone_meshMaterial = new THREE.Mesh(gRoca(),limestoneChunkMaterial)
            limestone_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) - 10, chunkZ)
            scene.add(limestone_meshMaterial)
            limestoneChunks.push(limestone_meshMaterial)
          }
          if (Math.random() < 0.005/chunkAccuracy/chunkAccuracy) {
            const brownstone_meshMaterial = new THREE.Mesh(gRoca(),brownstoneChunkMaterial)
            brownstone_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) - 10, chunkZ)
            scene.add(brownstone_meshMaterial)
            brownstoneChunks.push(brownstone_meshMaterial)
          }
          if (Math.random() < 0.005/chunkAccuracy/chunkAccuracy) {
            const granite_meshMaterial = new THREE.Mesh(gRoca(),graniteChunkMaterial)
            granite_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) - 10, chunkZ)
            scene.add(granite_meshMaterial)
            graniteChunks.push(granite_meshMaterial)
          }
          //Generar los árboles:
          if (rand() < 0.005/chunkAccuracy/chunkAccuracy) {
            const trunk_meshMaterial = new THREE.Mesh(gTronco(), trunk_material)
            trunk_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) + 25, chunkZ)
            scene.add(trunk_meshMaterial)
            trunksChunks.push(trunk_meshMaterial)
            const leavesMaterial_meshMaterial = new THREE.Mesh(gHojas(),leavesMaterial)
            leavesMaterial_meshMaterial.position.set(chunkX, getSurfaceAt(chunkX, chunkZ) + 200, chunkZ)
            scene.add(leavesMaterial_meshMaterial)
            leavesMaterialChunks.push(leavesMaterial_meshMaterial)
          }
        }
      }

      let trunk_texture = textureLoader.load("trunk.jpg")
      trunk_texture.wrapS = THREE.RepeatWrapping
      trunk_texture.wrapT = THREE.RepeatWrapping
      trunk_texture.repeat.set(1, 2.5)
      let trunk_material = new THREE.MeshLambertMaterial({ map: trunk_texture, side: THREE.DoubleSide })

      // Función para eliminar fragmentos de terreno que ya no son visibles
      const removeInvisibleChunks = () => {
        const visibleChunks = []
        camera.getWorldPosition(tmpVector)

        const allChunks = terrainChunks.concat(leavesChunks, trunksChunks, brownstoneChunks, graniteChunks, limestoneChunks, microleavesChunks)

        for (const chunk of allChunks) {
          chunk.getWorldPosition(tmpVector2)
          if (tmpVector.distanceTo(tmpVector2) < chunkSize * 1.5) {
            visibleChunks.push(chunk)
          } else {
            scene.remove(chunk)
            chunk.geometry.dispose()
          }
        }
      };

      const tmpVector = new THREE.Vector3()
      const tmpVector2 = new THREE.Vector3()

      //Crea los controles del mouse:
      let xa = 0;
      let ya = 0;
      onmousedown = () => {
        if (document.pointerLockElement === document.body || document.mozPointerLockElement === document.body) {
        } else {
          document.body.requestPointerLock()
        }
      };
      onmousemove = event => {
        if (document.pointerLockElement === document.body || document.mozPointerLockElement === document.body) {
          xa -= 0.01 * event.movementX;
          if (-1.5 < ya && 0 < event.movementY) {
            ya -= 0.005 * event.movementY
          }
          if (ya < 1.5 && event.movementY < 0) {
            ya -= 0.005 * event.movementY
          }
        }
      };

      //Crear los controles de teclado:
      let k = [];
      onkeydown = onkeyup = e => {
        k[e.keyCode] = e.type == "keydown";
      };

      // Crear una función de animación
      const animate = () => {
        // Ajustar el canvas...
        renderer.setSize(innerWidth, innerHeight)
        camera.aspect = innerWidth / innerHeight
        camera.updateProjectionMatrix()



        // Ajustar los controles...
        if (-1.5 > ya) {
          ya = -1.5
        }
        if (1.5 < ya) {
          ya = 1.5
        }
        camera.lookAt(
          camera.position.x + Math.sin(xa) * Math.cos(ya),
          camera.position.y + Math.sin(ya),
          camera.position.z + Math.cos(xa) * Math.cos(ya)
        );

	    // Colisiones:
	    for(let i1 in trunksChunks){
          if(distance3d({x:trunksChunks[i1].position.x,y:0,z:trunksChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<24){
            console.log("Collision.")
            camera.position.x+=(camera.position.x-trunksChunks[i1].position.x)/distance3d({x:trunksChunks[i1].position.x,y:0,z:trunksChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.z+=(camera.position.z-trunksChunks[i1].position.z)/distance3d({x:trunksChunks[i1].position.x,y:0,z:trunksChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
          }
        }
        for(let i1 in brownstoneChunks){
          if(distance3d({x:brownstoneChunks[i1].position.x,y:0,z:brownstoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<64){
            console.log("Collision.")
            let module=distance3d({x:brownstoneChunks[i1].position.x,y:0,z:brownstoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.x+=(camera.position.x-brownstoneChunks[i1].position.x)/module
            camera.position.z+=(camera.position.z-brownstoneChunks[i1].position.z)/module
          }
        }
        for(let i1 in limestoneChunks){
          if(distance3d({x:limestoneChunks[i1].position.x,y:0,z:limestoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<64){
            console.log("Collision.")
            let module=distance3d({x:limestoneChunks[i1].position.x,y:0,z:limestoneChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.x+=(camera.position.x-limestoneChunks[i1].position.x)/module
            camera.position.z+=(camera.position.z-limestoneChunks[i1].position.z)/module
          }
        }
        for(let i1 in graniteChunks){
          if(distance3d({x:graniteChunks[i1].position.x,y:0,z:graniteChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})<64){
            console.log("Collision.")
            let module=distance3d({x:graniteChunks[i1].position.x,y:0,z:graniteChunks[i1].position.z},{x:camera.position.x,y:0,z:camera.position.z})
            camera.position.x+=(camera.position.x-graniteChunks[i1].position.x)/module
            camera.position.z+=(camera.position.z-graniteChunks[i1].position.z)/module
          }
        }

        // Establecer la velocidad predeterminada
	    if(k[81]){
	    	walkspeed=1
	    }else{
	    	walkspeed=0.5
	    }

	    // Mover el jugador
	    if (k[65]) {
	      camera.position.x += walkspeed * Math.cos(xa)
	      camera.position.z -= walkspeed * Math.sin(xa)
	    }
	    if (k[87]) {
	      camera.position.x += walkspeed * Math.sin(xa)
	      camera.position.z += walkspeed * Math.cos(xa)
	    }
	    if (k[68]) {
	      camera.position.x -= walkspeed * Math.cos(xa)
	      camera.position.z += walkspeed * Math.sin(xa)
	    }
	    if (k[83]) {
	      camera.position.x -= walkspeed * Math.sin(xa)
	      camera.position.z -= walkspeed * Math.cos(xa)
	    }

        // Manteniendo la fuerza de sujección del Jugador contra el suelo:
      	camera.position.y = getSurfaceAt(camera.position.x, camera.position.z) + 10

        // Generar nuevos fragmentos de terreno a medida que el jugador se mueve
        const playerChunkX = Math.floor(camera.position.x / chunkSize) * chunkSize
        const playerChunkZ = Math.floor(camera.position.z / chunkSize) * chunkSize

        for (let x = -chunkSize; x <= chunkSize; x += chunkSize) {
          for (let z = -chunkSize; z <= chunkSize; z += chunkSize) {
            const chunkX = playerChunkX + x
            const chunkZ = playerChunkZ + z

            if (!terrainChunks.some(chunk => chunk.position.x === chunkX && chunk.position.z === chunkZ)) {
              generateTerrainChunk(chunkX, chunkZ);
            }
          }
        }

        // Eliminar fragmentos de terreno invisibles
        removeInvisibleChunks()
        scene.add( new THREE.CameraHelper( directionalLight.shadow.camera ) );
        // Llamada recursiva para la próxima animación
        requestAnimationFrame(animate)
        renderer.render(scene, camera)
      }

      // Iniciar la animación
      animate();
    };
  </script>
</head>
<body>
</body>
</html>

Yeah! Finally! I did it!:

The code:

THREE Shadows body { margin: 0; }
		import * as THREE from 'three';

		// scene
		const scene = new THREE.Scene();

		// camera
		const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
		camera.position.set(0,6,10);

		// renderer
		const renderer = new THREE.WebGLRenderer();

		// enabling shadows
		renderer.shadowMap.enabled = true;
		renderer.shadowMap.type = THREE.BasicShadowMap;

		document.body.appendChild(renderer.domElement);
		renderer.setSize(window.innerWidth, window.innerHeight);

		// plane geometry
		const geometryP = new THREE.PlaneGeometry(-50, -50, 50, 50);
		geometryP.rotateX(-Math.PI / 2);
		const materialP = new THREE.MeshStandardMaterial({color:0xffffff})
	      // Definir las alturas del terreno
	      const terrainVertices = geometryP.attributes.position.array;
	      for (let i = 0; i < terrainVertices.length; i += 3) {
	        const x = terrainVertices[i];
	        const z = terrainVertices[i + 2];
	        const y = Math.sin(x * 2) + Math.cos(z * 2); // Ejemplo de generación de alturas
	        terrainVertices[i + 1] = y;
	      }
	      geometryP.computeVertexNormals();
	      const plane = new THREE.Mesh(geometryP, materialP);

		plane.castShadow = true;
		plane.receiveShadow = true;
		scene.add(plane);

		// sphere geometry
		const geometryS = new THREE.SphereGeometry(2, 32, 32);
		const materialS = new THREE.MeshStandardMaterial({
			color:0xffffff
		});

		const sphere = new THREE.Mesh(geometryS, materialS);
		sphere.position.set(0,3,0);
		sphere.receiveShadow = true;
		sphere.castShadow = true;
		scene.add(sphere);

		// light
		let light = new THREE.DirectionalLight(0xFFFFFF, 1.0);
		light.position.set(20, 100, 10);
		light.target.position.set(0, 0, 0);
		light.castShadow = true;
		scene.add(light);
	      //Crea los controles del mouse:
	      let xa=0;
	      let ya=0;
	      onmousedown=()=>{
	        if(document.pointerLockElement===document.body||
	        document.mozPointerLockElement===document.body){
	        }else{
	          document.body.requestPointerLock()
	        }
	      }
	      onmousemove=(event)=>{
	        if(document.pointerLockElement===document.body||
	        document.mozPointerLockElement===document.body){
	          xa-=0.01*event.movementX
	          if(-1.5<ya&&0<event.movementY){
	            ya-=0.005*event.movementY
	          }
	          if(ya<1.5&&event.movementY<0){
	            ya-=0.005*event.movementY
	          }
	        }
	      }
	      //Crear los controles de teclado:
	      let k=[];
	      onkeydown=onkeyup=(e)=>{
	        k[e.keyCode]=e.type=="keydown"
	      }
	      // Crear una función de animación
	      const animate = () => {
	        renderer.setSize(innerWidth,innerHeight)
	        camera.aspect=innerWidth/innerHeight
	        camera.updateProjectionMatrix()
	        requestAnimationFrame(animate)
	        renderer.render(scene,camera)
	        if(-1.5>ya){ya=-1.5}
	        if(1.5<ya){ya=1.5}
	        camera.lookAt(
	          camera.position.x+Math.sin(xa)*Math.cos(ya),
	          camera.position.y+Math.sin(ya),
	          camera.position.z+Math.cos(xa)*Math.cos(ya)
	        )
	        if(k[65]){
	          camera.position.x+=0.05*Math.cos(xa)
	          camera.position.z-=0.05*Math.sin(xa)
	        }
	        if(k[87]){
	          camera.position.x+=0.05*Math.sin(xa)
	          camera.position.z+=0.05*Math.cos(xa)
	        }
	        if(k[68]){
	          camera.position.x-=0.05*Math.cos(xa)
	          camera.position.z+=0.05*Math.sin(xa)
	        }
	        if(k[83]){
	          camera.position.x-=0.05*Math.sin(xa)
	          camera.position.z-=0.05*Math.cos(xa)
	        }
	        camera.position.y=Math.sin(camera.position.x * 2) + Math.cos(camera.position.z * 2)+3;
	      };
	      // Iniciar la animación
	      animate();

	</script>
</body>
1 Like

Just in case (lines 58-59):


Demo: https://codepen.io/prisoner849/full/abxOQGB

2 Likes