threejs glslshader 没有出现在 gltf 模型上

Posted

技术标签:

【中文标题】threejs glslshader 没有出现在 gltf 模型上【英文标题】:threejs glslshader not appearing on gltf model 【发布时间】:2022-01-22 13:42:54 【问题描述】:

大家好,我是three.js 的新手,我正在尝试导入一个着色器程序,使我的gltf 模型纹理变成瀑布图案,我从https://shadered.org/view?s=6Gny24_ojD 获取了glsl 代码。但是,我无法显示着色器,而是让我的 gltf 模型消失而没有任何错误,gltf 模型和着色器都已加载,但我不知道如何将它们一起显示。有什么原因以及如何解决它?提前致谢。我附上了下面的 sn-p 和完整代码。谢谢

我认为这里的某些部分代码出错了

          var textureLoader = new THREE.TextureLoader();

          mesh = gltf.scene.children[0]

          console.log(mesh)

          var texture = textureLoader.load('blue1.jpg');
          texture.flipY = false;

          const customMaterial = new THREE.ShaderMaterial(
          uniforms: 
              time:  value: 1.0 ,
              map:  value: texture ,
              resolution:  value: new THREE.Vector2() 
          ,
          vertexShader:  document.getElementById('vertexShader').textContent,
          fragmentShader:  document.getElementById('fragmentShader').textContent,
      );

      console.log(customMaterial)




          var matcapMaterial = new THREE.MeshMatcapMaterial( skinning: true ,matcap: texture )

            obj = scene.add( mesh );

            obj.traverse((o) => 
            if (o.isMesh) o.material = matcapMaterial
            o.material = customMaterial;

            ;


            )

            ;

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>3d model</title>

  </head>
    
<script id="vertexShader" type="x-shader/x-vertex">
  varying vec2 vUv;
  
  void main()
  
      vUv = uv;
      vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
      gl_Position = projectionMatrix * mvPosition;
  
  </script>
  
  <script id="fragmentShader" type="x-shader/x-fragment">
  uniform vec2 u_mouse;
  uniform vec2 u_resolution;
  uniform sampler2D u_helmet_texture;
  
  varying vec2 vUv;
  
  void main() 
    vec2 st = gl_FragCoord.xy/u_resolution;
    float pct = 1.0 - distance(st, u_mouse);
    
    vec4 heatmap = vec4(pct*2.0, 0.1, 0.1, 0.7);
    vec4 helmet = texture2D(u_helmet_texture, vUv);
    
    vec4 color = mix(heatmap, helmet, .60);
    
    gl_FragColor = color;
  
  </script>
    <script type="module">
        import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.114/build/three.module.js';
        
        import  OrbitControls  from 'https://cdn.jsdelivr.net/npm/three@0.114/examples/jsm/controls/OrbitControls.js';
        import  GLTFLoader  from 'https://cdn.jsdelivr.net/npm/three@0.114/examples/jsm/loaders/GLTFLoader.js';
        import  RGBELoader  from 'https://cdn.jsdelivr.net/npm/three@0.114/examples/jsm/loaders/RGBELoader.js';
        
        var container, controls;
        var camera, scene, renderer, mixer, clock;
        var obj , material , texture , mesh
        
        init();
        animate();
        
        function init() 
        
          container = document.getElementById( 'test' );
          document.body.appendChild( container );
          
          

          camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.01, 1000 );
          camera.position.x = 0
          camera.position.y = 2
          camera.position.z = 10 


        
          scene = new THREE.Scene();
        //   scene.background = new THREE.Color(0xffffff);
          var light = new THREE.HemisphereLight(0xffffff,0x000000,10);
          scene.add(light);
            

          clock = new THREE.Clock(); 
              
              var loader = new GLTFLoader();

               // Load a glTF resource

    
              loader.load('scene.gltf', function ( gltf ) 
                
              var textureLoader = new THREE.TextureLoader();

              mesh = gltf.scene.children[0]

              console.log(mesh)

              var texture = textureLoader.load('blue1.jpg');
              texture.flipY = false;

              const customMaterial = new THREE.ShaderMaterial(
              uniforms: 
                  time:  value: 1.0 ,
                  map:  value: texture ,
                  resolution:  value: new THREE.Vector2() 
              ,
              vertexShader:  document.getElementById('vertexShader').textContent,
              fragmentShader:  document.getElementById('fragmentShader').textContent,
          );

          console.log(customMaterial)


             

              var matcapMaterial = new THREE.MeshMatcapMaterial( skinning: true ,matcap: texture )

                obj = scene.add( mesh );

                obj.traverse((o) => 
                if (o.isMesh) o.material = matcapMaterial
                o.material = customMaterial;
                
                ;

                
                )
               
                ;

        
                mixer = new THREE.AnimationMixer( mesh );
                
                gltf.animations.forEach( ( clip ) => 
                  
                    mixer.clipAction( clip ).play();
                  
                 );
        
               );



        
        
          renderer = new THREE.WebGLRenderer(  antialias: true  );
          renderer.setPixelRatio( window.devicePixelRatio );
          renderer.setSize( window.innerWidth, window.innerHeight );
          renderer.toneMapping = THREE.ACESFilmicToneMapping;
          renderer.toneMappingExposure = 0.8;
          renderer.outputEncoding = THREE.sRGBEncoding;
          container.appendChild( renderer.domElement );
        
       
        
        function onWindowResize() 
          camera.aspect = window.innerWidth / window.innerHeight;
          camera.updateProjectionMatrix();
        
          renderer.setSize( window.innerWidth, window.innerHeight );
        
        
        //
        
        function animate() 
          requestAnimationFrame( animate );
          var delta = clock.getDelta();
          if ( mixer ) mixer.update( delta );
          renderer.render( scene, camera );
        
        

        </script>



<body>
  <div id="test">

  </div>
  
    </body> 
</html>

【问题讨论】:

【参考方案1】:

材质创建中的制服与片段着色器中的制服不匹配。分辨率统一也设置为 0、0,因为您从不为 Vector2 赋值。

【讨论】:

有什么办法解决这个问题? 有没有办法将纹理与着色器一起使用?

以上是关于threejs glslshader 没有出现在 gltf 模型上的主要内容,如果未能解决你的问题,请参考以下文章

threejs 绘制多段虚线

ThreeJS——窗口变化自适应渲染

ThreeJS——窗口变化自适应渲染

如何使用 Threejs 更改对象的 zOrder?

如何在 ThreeJS 中将网格旋转 90 度?

设备像素比知多少(threejs踩坑之旅)