2

I am using dynamic texture on threejs. When i use different shapes object, texture not working fine. But, When i use boxGeometry , it's working fine.

setCanvas =()=>{
    this.canvas = window.document.getElementById("canvas");
    var ctx = this.canvas.getContext("2d");
    ctx.font = "20pt Arial";
    ctx.fillStyle = "red";
    ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
    ctx.fillStyle = "white";
    ctx.fillRect(10, 10, this.canvas.width - 20, this.canvas.height - 20);
    ctx.fillStyle = "yellow";
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText("asdasdasd", this.canvas.width / 2, this.canvas.height / 2);
  }

different shapes object creator

threeObjectCreator(mesh, position, color) {

    const object = this.objectLoader.parse(mesh);
    object.position.set(position.x, position.z, position.y);

    object.rotation.x = Math.PI / 2;
    let texture = new THREE.Texture(this.canvas);
    object.material = new THREE.MeshPhongMaterial({
      color,
      side: THREE.DoubleSide,
      shininess: 30,
      //flatShading: THREE.FlatShading,
      transparent: false,
      map:texture
    });
    texture.needsUpdate = true;
    return object;
  }

enter image description here

with box geometry

let geometry = new THREE.BoxGeometry( 200, 200, 200 );
    let mesh = new THREE.Mesh(geometry, material);
    this.scene.add(mesh);

enter image description here

How can i solve this problem ?

Ahmet emre CETIN
  • 321
  • 1
  • 4
  • 22
  • 1
    If you want to use textures, you require UV coordinates for every face that has a texture. Depending on how you load your resources, they may or may not come with this mapping, so you need to make/generate your own UV mapping, an example: https://stackoverflow.com/questions/20774648/three-js-generate-uv-coordinate (an UV map tells how to transform the texture to the face) – Ferrybig Nov 05 '19 at 08:45
  • Thank you for comment. Can you send it again as Answer. I would like to give point to you. – Ahmet emre CETIN Nov 05 '19 at 10:26

1 Answers1

1

When using textures in OpenGL (ThreeJS uses this via WebGL), its important that you properly set the UV parameters on your faces.

These UV parameters tell how to morph and transform an 2d texture into 3d space.

Lets see the UV parameters on our simple box model (new THREE.BoxGeometry()):

[[
    [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
    [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}]
]]

This looks scary

To understand these coordinates, you have to understand that our box is made up of 12 "faces", or triangles in this case, 2 triangles per side.

Interesting things happen when we modify 1 of the coordinates in the UV grid:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );

var renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );

var geometry = new THREE.BoxGeometry( 3,3,3 );
var material = new THREE.MeshBasicMaterial( { color: 0xffffff } );

new THREE.TextureLoader().load( "https://threejs.org/examples/textures/uv_grid_opengl.jpg", (texture) => {     
    material.map = texture;
    renderer.render( scene, camera );
});

geometry.faceVertexUvs = 
    [[
        [{"x":0,"y":1},{"x":0,"y":-1},{"x":2,"y":1}],
        [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":1},{"x":0,"y":0},{"x":1,"y":1}],
        [{"x":0,"y":0},{"x":1,"y":0},{"x":1,"y":1}]
    ]]


var cube = new THREE.Mesh( geometry, material );
cube.rotation.x = Math.PI / 3
cube.rotation.y = 0
cube.rotation.z = Math.PI / 3
scene.add( cube );

camera.position.z = 5;
body { margin: 0; font-size: 0; }
   canvas { width: 100%; height: 100% }
<script src="https://threejs.org/build/three.js"></script>

Notice how the texture shifts? This is how UV coordinates help you apply a 2d texture to any 3d surface. (Try to also play around with Texture.wrapS)

The problem

At the moment, inside your code, you are loading your objects from an external source, most likely an OBJ file (based on the fact that you are using an ObjectLoader), and since an MAT file was not present, there is no information present about the properties of the materials.

This means that the objects you are trying to render to screen, don't have any "texture coordinates", and we need to "provide" this information in some way.

While its possible to hand craft this data, this isn't always so saleable, so we have to fallback to another alternative, generating this data based on the position of the item.

Generating UV coordinates is a complex topic, as there are many different mappings for this, and I recommend you find and use one of the solutions at "THREE.js generate UV coordinate - StackOverflow" for this.

Ferrybig
  • 18,194
  • 6
  • 57
  • 79