1

I loaded an object with OBJLoader. I want to use a Shader Material with a texture. I pass my texture to the uniforms parameters of the material. I pass the UV variable from the vertex shader to the fragment shader.

But when I use the uv coordinate for mapping my texture I get always 0,0 or at least this is what it looks like. The whole object is coloured with the bottom left pixel of the texture.

Here are my shaders:

  <script type='x-shader/x-vertex' id='vertex-shader'>
    uniform float u_time;
    varying vec2 vUv;
    void main() {
      vUv = uv;
      vec4 pos = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
      gl_Position = pos;
    }
  </script>
  <script type='x-shader/x-fragment' id='fragment-shader'>
    precision highp float;
    uniform float u_time;
    uniform vec2 u_resolution;
    uniform sampler2D texture;
    varying vec2 vUv;
    void main(){
      vec2 st = vUv;
      vec4 tex = texture2D(texture, st);
      gl_FragColor = tex;
     }
  </script>

And here is how I load the object and assign the material

var loader = new THREE.OBJLoader();
loader.load(
    'assets/standing.obj',
    function (object){

    main.man = object;
    main.man.position.set(0,-600,400);

    main.texture = new THREE.TextureLoader().load( 'assets/na_00004c.jpg' );

    main.texture_needsUpdate = true;
    var uniforms = {
      u_time:{type:'f', value:0.0},
      u_mouse:{type:'v2', value: new THREE.Vector2()},
      u_resolution: {type: 'v2', value: {x:2048.,y:1024.}},
      texture: {type: 't', value: main.texture}
    }

    main.material = new THREE.ShaderMaterial({  
      uniforms: uniforms,
      vertexShader: document.getElementById('vertex-shader').textContent,
      fragmentShader: document.getElementById('fragment-shader').textContent,
      transparent: true
    });

    main.material.needsUpdate = true;
    main.material.side = THREE.DoubleSide;

    main.man.traverse(function(child){
      if(child instanceof THREE.Mesh){
        child.material = main.material;
        child.material.needsUpdate = true;
        child.geometry = new THREE.Geometry().fromBufferGeometry( child.geometry );  
        child.geometry.computeVertexNormals();
        child.geometry.elementsNeedUpdate = true;
        child.geometry.mergeVertices(); 
        child.verticesNeedUpdate = true;
        child.normalsNeedUpdate = true;
        child.uvsNeedUpdate = true;
        child.material.flatShading = THREE.SmoothShading;
      } 
    });

        main.scene.add(main.man);

    },
    function (xhr){
        console.log((xhr.loaded/xhr.total*100)+'% loaded');
    },
    function (error){
        console.log(error,'An error happened');
    }
);

Here there is the full example http://cmt.re/dev/na/

This is the image that I want to use as a texture http://cmt.re/dev/na/assets/na_00004c.jpg

Does somebody know why this is happening?

Thanks a lot.

nbl7
  • 511
  • 4
  • 14
  • Does the object even have texture coordinates? – Rabbid76 Dec 08 '18 at 09:42
  • How can I check? – nbl7 Dec 08 '18 at 10:16
  • The [Wavefront OBJ](https://de.wikipedia.org/wiki/Wavefront_OBJ) file (*.obj* file) is a text file. Does it have `vt` entries? – Rabbid76 Dec 08 '18 at 10:26
  • I tested your code with an simple model and it works fine for me. Use a simple model like that one of this question: [`Map not applying to loaded Obj`](https://stackoverflow.com/questions/48212648/map-not-applying-to-loaded-obj), to test your code. – Rabbid76 Dec 08 '18 at 10:32
  • No. It doesn't have it. Thanks. – nbl7 Dec 08 '18 at 10:34

1 Answers1

3

Your code works fine, but your *.obj file doesn't contain any texture coordinates. The Wavefront OBJ file (.obj file) is a text file, texture coordinates are the entries with the key vt, if this entries are missing, the mesh doesn't have any texture coordinates.

Your code works fine, see the example, where I used your original code with a simple model:

var main = new function(){
  
  this.init = function(){
    
    this.initThree();
    
  }
  
  this.initThree = function(){
    
    main.scene = new THREE.Scene();
    main.scene.background = new THREE.Color(0xCCCCCC);
    
    var aspectRatio = window.innerWidth / window.innerHeight;
    main.camera = new THREE.PerspectiveCamera(75, aspectRatio, 0.1, 100000);
    //main.camera.position.set(-40, 0, 512);
    main.camera.position.set(1,2,0);
    
    main.renderer = new THREE.WebGLRenderer({antialias: true});
    main.renderer.setPixelRatio(window.devicePixelRatio);
    main.renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(main.renderer.domElement);

    main.controls = new THREE.OrbitControls(main.camera, main.renderer.domElement);
    main.controls.enableDamping = true;
    main.controls.dampingFactor = 0.1;
    main.controls.screenSpacePanning = false;

    var helper = new THREE.GridHelper(2000, 100);
    helper.material.opacity = 0.25;
    helper.material.transparent = true;
    main.scene.add(helper);

    var axis = new THREE.AxesHelper();
    main.scene.add(axis);
    
    makeTextFile = function (text) {
      var data = new Blob([text], {type: 'text/plain'});
      var textFile = window.URL.createObjectURL(data);
      return textFile;   
    }
    var textbox_obj = document.getElementById('plane_obj');
    var obj_url = makeTextFile(textbox_obj.value);

    var loader = new THREE.OBJLoader();
    loader.load(
     obj_url,
     function (object){
        
        main.man = object;
        //main.man.position.set(0,-600,400);
        main.man.position.set(0,0,0);
        
        main.texture = new THREE.TextureLoader().load( 'https://raw.githubusercontent.com/Rabbid76/graphics-snippets/master/resource/texture/Gominolas.png' );
        
        main.texture_needsUpdate = true;
        var uniforms = {
          u_time:{type:'f', value:0.0},
          u_mouse:{type:'v2', value: new THREE.Vector2()},
          u_resolution: {type: 'v2', value: {x:2048.,y:1024.}},
          texture: {type: 't', value: main.texture}
        }
        
        main.material = new THREE.ShaderMaterial({  
          uniforms: uniforms,
          vertexShader: document.getElementById('vertex-shader').textContent,
          fragmentShader: document.getElementById('fragment-shader').textContent,
          transparent: true
        });
        
        main.material.needsUpdate = true;
        main.material.side = THREE.DoubleSide;
        
        // main.material = new THREE.MeshNormalMaterial();
        
        main.man.traverse(function(child){
          if(child instanceof THREE.Mesh){
            child.material = main.material;
            child.material.needsUpdate = true;
            child.geometry = new THREE.Geometry().fromBufferGeometry( child.geometry );  
            child.geometry.computeVertexNormals();
            child.geometry.elementsNeedUpdate = true;
            child.geometry.mergeVertices(); 
            child.verticesNeedUpdate = true;
            child.normalsNeedUpdate = true;
            child.uvsNeedUpdate = true;
            child.material.flatShading = THREE.SmoothShading;
          } 
        });
        
      main.scene.add(main.man);
        
     },
     function (xhr){
      console.log((xhr.loaded/xhr.total*100)+'% loaded');
     },
     function (error){
      console.log(error,'An error happened');
     }
    );
    
    window.onresize = main.onResize;

    this.render();
    
  }
  
  this.render = function(){

    var time = Date.now();
    main.controls.update();
    requestAnimationFrame(main.render);
    main.renderer.render(main.scene, main.camera);
    
  }
  
  this.onResize = function(event) {
    
    main.renderer.setSize(window.innerWidth, window.innerHeight);
    main.camera.aspect = window.innerWidth / window.innerHeight;
    main.camera.updateProjectionMatrix();
    
  }

}

 main.init();
<script src="https://cdn.jsdelivr.net/npm/three@0.115/build/three.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.115/examples/js/controls/OrbitControls.js"></script>
<script src="https://rawgit.com/mrdoob/three.js/dev/examples/js/loaders/OBJLoader.js"></script>

<textarea id="plane_obj" style="display:none;">
    v -1.000000 0.000000 1.000000
    v 1.000000 0.000000 1.000000
    v -1.000000 0.000000 -1.000000
    v 1.000000 0.000000 -1.000000
    
    vt 0.000000 0.000000
    vt 1.000000 0.000000
    vt 0.000000 1.000000
    vt 1.000000 1.000000
    
    vn 0.0000 1.0000 0.0000
    
    f 1/1/1 2/2/1 4/4/1 3/3/1
</textarea>

<script type='x-shader/x-vertex' id='vertex-shader'>
uniform float u_time;
varying vec2 vUv;
void main() {
    vUv = uv;
    vec4 pos = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
    gl_Position = pos;
}
</script>

<script type='x-shader/x-fragment' id='fragment-shader'>
precision highp float;
uniform float u_time;
uniform vec2 u_resolution;
uniform sampler2D texture;
varying vec2 vUv;
void main(){
    vec2 st = vUv;
    vec4 tex = texture2D(texture, st);
    gl_FragColor = tex;
}
</script>
Rabbid76
  • 202,892
  • 27
  • 131
  • 174