Three.js - Vertex Shader UV variable return only 0,0

喜你入骨 提交于 2020-01-15 09:19:28

问题


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.


回答1:


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.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://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
<script src="https://threejs.org/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>


来源:https://stackoverflow.com/questions/53681200/three-js-vertex-shader-uv-variable-return-only-0-0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!