【问题标题】:three.js set background image三.js设置背景图片
【发布时间】:2013-11-20 20:17:27
【问题描述】:

如何创建静态背景图片?

默认背景:

scene = new THREE.Scene();

// ...

renderer = new THREE.WebGLRenderer( { antialias: false } );
renderer.setClearColor( scene.fog.color, 1 );

如何为scene.fog设置图片,或者为clearcolor设置不透明度?

【问题讨论】:

    标签: image background static three.js set


    【解决方案1】:

    如果您尝试设置静态背景图像(即使您旋转主摄像头,背景也不会改变),您必须创建 2 个场景和 2 个摄像头。
    第一个场景将由一个应用了纹理的基本平面组成。
    第二个场景将包含您的所有对象。
    这是一个可以做到的代码:

    <html>
        <body>
    
        <script src="Three.js"></script>
        <script>
            var color = 0x000000;
    
            // Create your main scene
            var scene = new THREE.Scene();
    
            // Create your main camera
            var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
    
            // Create lights
            var light = new THREE.PointLight(0xEEEEEE);
            light.position.set(20, 0, 20);
            scene.add(light);
    
            var lightAmb = new THREE.AmbientLight(0x777777);
            scene.add(lightAmb);
    
            // Create your renderer
            var renderer = new THREE.WebGLRenderer();
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);
    
            // Create a cube
            var geometry = new THREE.BoxGeometry(1, 1, 1);
            var material = new THREE.MeshLambertMaterial({
                color: 0xff00ff,
                ambient: 0x121212,
                emissive: 0x121212
             });
    
            var cube = new THREE.Mesh(geometry, material);
            scene.add(cube);
    
            // Set up the main camera
            camera.position.z = 5;
    
            // Load the background texture
            var texture = THREE.ImageUtils.loadTexture( '1.jpg' );
            var backgroundMesh = new THREE.Mesh(
                new THREE.PlaneGeometry(2, 2, 0),
                new THREE.MeshBasicMaterial({
                    map: texture
                }));
    
            backgroundMesh .material.depthTest = false;
            backgroundMesh .material.depthWrite = false;
    
            // Create your background scene
            var backgroundScene = new THREE.Scene();
            var backgroundCamera = new THREE.Camera();
            backgroundScene .add(backgroundCamera );
            backgroundScene .add(backgroundMesh );
    
            // Rendering function
            var render = function () {
                requestAnimationFrame(render);
    
                // Update the color to set
                if (color < 0xdddddd) color += 0x0000ff;
    
                // Update the cube color
                cube.material.color.setHex(color);
    
                // Update the cube rotations
                cube.rotation.x += 0.05;
                cube.rotation.y += 0.02;
    
                renderer.autoClear = false;
                renderer.clear();
                renderer.render(backgroundScene , backgroundCamera );
                renderer.render(scene, camera);
           };
    
           render();
       </script>
       </body>
    </html>
    

    **Demo right here **

    希望这会有所帮助。

    注意 (2014/06/28): 此代码适用于 Three.js 的最新版本:R67

    【讨论】:

    • 这个例子没有做任何事情,因为“new THREE.Camera()”是抽象类。您需要改用“THREE.PerspectiveCamera”。
    • 但它不适用于 OBJLoder、OBJMTLLoder 等对象加载器
    • @BorutTomazin :请查看更新答案中的现场演示。它已经使用最新版本的 Three.js 进行了测试:R67。感谢您的反馈
    【解决方案2】:

    使用纹理加载器将任何图像加载为纹理,然后将其应用于场景,如下所示:

    //Load background texture
    const loader = new THREE.TextureLoader();
    loader.load('https://images.pexels.com/photos/1205301/pexels-photo-1205301.jpeg' , function(texture)
                {
                 scene.background = texture;  
                });
    

    结果:

    演示:

    请参阅 CodePen 上 Hitesh Sahu (@hiteshsahu) 的 Pen Flat Earth Three.JS

    【讨论】:

      【解决方案3】:

      这次运行:

      renderer = new THREE.WebGLRenderer({ antialias: false,alpha:true });
      renderer.setSize( window.innerWidth, window.innerHeight );
      renderer.setClearColor(0x000000, 0);
      

      【讨论】:

      • 这是一种简单的方法,然后当然可以将{ background-image: url('whatever.jpg') } css 到您的画布元素或其容器上。
      • 这对我有用——而其他人没有。使用renderer = new THREE.CanvasRenderer({alpha:true });
      • 这是迄今为止最好的答案(简单有效)!
      【解决方案4】:

      可以通过设置THREE.Scenescene.background属性来设置背景图片:

      scene = new THREE.Scene();
      bgTexture = loader.load("https://i.stack.imgur.com/vDUZz.jpg",
          function ( texture ) {
              var img = texture.image;
              bgWidth= img.width;
              bgHeight = img.height;
              resize();
          } );
      scene.background = bgTexture;
      bgTexture.wrapS = THREE.MirroredRepeatWrapping;
      bgTexture.wrapT = THREE.MirroredRepeatWrapping;
      

      图像的纵横比可以像这样调整到画布的纵横比:

      var aspect = window.innerWidth / window.innerHeight;
      var texAspect = bgWidth / bgHeight;
      var relAspect = aspect / texAspect;
      
      bgTexture.repeat = new THREE.Vector2( 
          Math.max(relAspect, 1),
          Math.max(1/relAspect,1) ); 
      bgTexture.offset = new THREE.Vector2(
          -Math.max(relAspect-1, 0)/2,
          -Math.max(1/relAspect-1, 0)/2 ); 
      

      见代码sn-p:

      (function onLoad() {
        var container, loader, camera, scene, renderer, controls, bgTexture, bgWidth, bgHeight;
        
        init();
        animate();
      
        function init() {
          container = document.getElementById('container');
          
          renderer = new THREE.WebGLRenderer({
            antialias: true
          });
          renderer.setPixelRatio(window.devicePixelRatio);
          renderer.setSize(window.innerWidth, window.innerHeight);
          renderer.shadowMap.enabled = true;
          container.appendChild(renderer.domElement);
      
          camera = new THREE.PerspectiveCamera(70, window.innerWidth / window.innerHeight, 1, 100);
          camera.position.set(0, -4, -1.5);
      
          loader = new THREE.TextureLoader();
          loader.setCrossOrigin("");
      
          scene = new THREE.Scene();
          bgTexture = loader.load("https://raw.githubusercontent.com/Rabbid76/graphics-snippets/master/resource/texture/background.jpg",
              function ( texture ) {
                  var img = texture.image;
                  bgWidth= img.width;
                  bgHeight = img.height;
                  resize();
              }
          );
          scene.background = bgTexture;
          bgTexture.wrapS = THREE.MirroredRepeatWrapping;
          bgTexture.wrapT = THREE.MirroredRepeatWrapping;
        
          scene.add(camera);
          window.onresize = resize;
          
          var ambientLight = new THREE.AmbientLight(0x404040);
          scene.add(ambientLight);
      
          var directionalLight = new THREE.DirectionalLight( 0xffffff, 0.5 );
          directionalLight.position.x = -0.75;
          directionalLight.position.y = -0.5;
          directionalLight.position.z = -1;
          scene.add( directionalLight );
      
          controls = new THREE.OrbitControls(camera, renderer.domElement);
      		
          createModel();
        }
      
        function createModel() {
      
          var material = new THREE.MeshPhongMaterial({color:'#b090b0'});
          var geometry = new THREE.BoxGeometry( 1, 1, 1 );
          var mesh = new THREE.Mesh(geometry, material);
      
          scene.add(mesh);
        }
      
        function resize() {
          
          var aspect = window.innerWidth / window.innerHeight;
          var texAspect = bgWidth / bgHeight;
          var relAspect = aspect / texAspect;
      
          bgTexture.repeat = new THREE.Vector2( Math.max(relAspect, 1), Math.max(1/relAspect,1) ); 
          bgTexture.offset = new THREE.Vector2( -Math.max(relAspect-1, 0)/2, -Math.max(1/relAspect-1, 0)/2 ); 
      
          renderer.setSize(window.innerWidth, window.innerHeight);
          camera.aspect = aspect;
          camera.updateProjectionMatrix();
        }
      
        function animate() {
          requestAnimationFrame(animate);
          render();
        }
      
        function render() {
          renderer.render(scene, camera);
        }
      })();
      <script src="https://threejs.org/build/three.min.js"></script>
      <!--script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/89/three.min.js"></script-->
      <script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
      
      <div id="container"></div>

      【讨论】:

      • 使用 scene.background 似乎是添加背景图像的最简单方法。但是,您的代码会呈现扭曲的背景图像(因为它与窗口分辨率匹配)。知道如何解决这个问题吗?
      【解决方案5】:

      谢谢你))

      我找到了另一个解决方案:

      <!DOCTYPE html>
      <head>
          <title>three.js webgl - orbit controls</title>
          <meta charset="utf-8">
          <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
          <style>
              body {
                  color: #000;
                  font-family:Monospace;
                  font-size:13px;
                  text-align:center;
                  font-weight: bold;
                  background-image:url(./foto.jpg);
      
                  margin: 0px;
                  overflow: hidden;
              }
      
              #info {
                  color:#000;
                  position: absolute;
                  top: 0px; width: 100%;
                  padding: 5px;
      
              }
      
              a {
                  color: red;
              }
          </style>
      </head>
      
      <body>
          <div id="container"></div>
          <div id="info">
      
              <a href="http://threejs.org" target="_blank">three.js</a> 
          </div>
      
          <script src="./three.min.js"></script>
          <script src="js/loaders/OBJLoader.js"></script>
          <script src="js/controls/OrbitControls.js"></script>
      
          <script src="js/Detector.js"></script>
          <script src="js/libs/stats.min.js"></script>
          <!--используем для вывода информации fps-->
      
          <script>
              if ( ! Detector.webgl ) Detector.addGetWebGLMessage();
              var container, stats;
              var camera, controls, scene, renderer;
              var cross;
      
              init();
              animate();
      
              function init() {       
      
                  camera = new THREE.PerspectiveCamera( 90, window.innerWidth / window.innerHeight, 0.1, 2000 );
                  camera.position.z = 100;
                  controls = new THREE.OrbitControls( camera );
                  controls.addEventListener( 'change', render );
                  scene = new THREE.Scene();
      
                  var manager = new THREE.LoadingManager();
                  manager.onProgress = function ( item, loaded, total ) {
      
                      console.log( item, loaded, total );
      
                  };
      
                  var texture = new THREE.Texture();
                  var loader = new THREE.ImageLoader( manager );
                  loader.load( './kos.jpg', function ( image ) {
      
                      texture.image = image;
                      texture.needsUpdate = true;
      
                  } );
      
                  // model
      
                  var loader = new THREE.OBJLoader( manager );
                  loader.load( './skull.obj', function ( object ) {
                      object.traverse( function ( child ) {
                          if ( child instanceof THREE.Mesh ) {
                              child.material.map = texture;
                          }
                      } );
                      object.position.y = 10;
                      scene.add( object );
                  } );
      
      
                  // lights
      
                  light = new THREE.DirectionalLight( 0xffffff );
                  light.position.set( 1, 1, 1 );
                  scene.add( light );
      
                  light = new THREE.DirectionalLight( 0xffffff  );
                  light.position.set( -1, -1, -1 );
                  scene.add( light );
      
                  light = new THREE.AmbientLight( 0xffffff );
                  scene.add( light );
      
      
                  renderer = new THREE.WebGLRenderer( { antialias: false } );
                   renderer.setSize(window.innerWidth, window.innerHeight);
                  document.body.appendChild(renderer.domElement);
      
                  container = document.getElementById( 'container' );
                  container.appendChild( renderer.domElement );
                  stats = new Stats();
                  stats.domElement.style.position = 'absolute';
                  stats.domElement.style.top = '0px';
                  stats.domElement.style.zIndex = 100;
                  container.appendChild( stats.domElement );
                  window.addEventListener( 'resize', onWindowResize, false );
              }
      
      
              function onWindowResize() {
                  camera.aspect = window.innerWidth / window.innerHeight;
                  camera.updateProjectionMatrix();
                  renderer.setSize( window.innerWidth, window.innerHeight );
                  render();
      
              }
      
              function animate() {
                  requestAnimationFrame( animate );
                  controls.update();
      
              }
      
              function render() {
      
                  renderer.render( scene, camera );
                  stats.update();
              }
      
      
          </script>
      
      </body>
      

      【讨论】:

      • 很遗憾,您的代码不适用于three.js r78,您可能在构建webgl渲染时忘记将alpha设置为true,这是查看body背景图像的关键点。
      • @user2969890 我喜欢您的解决方案 (+1),因为您只是在使用纹理清除缓冲区。我尝试了相同的方法,但要么我收到关于纹理不是 2 的幂以及缩小或不正确的纵横比的警告。您是如何解决在使用纹理作为场景背景时保持纵横比的问题的?
      【解决方案6】:

      今天似乎很晚才向这个线程添加任何贡献,但这是我的“hap'orth”:

          <head>
              <meta charset=utf-8>
              <title>Temple7</title>
              <style>
                  body { margin: 0;
                       }
                  canvas { width: 100%; height: 100%;
                        background-image:url(Clouds.jpg);
                      }
              </style>
          </head>
      

      这种相当简单的方法有其局限性。 .jpg 图像保留其像素尺寸,因此对于不同大小的浏览器窗口,人们可以看到不同数量的图像。如果画布大小超过 .jpg 的大小,则会发生平铺。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-25
        • 2018-10-09
        • 1970-01-01
        • 2020-11-21
        • 2015-05-09
        • 2012-03-07
        • 2020-07-03
        相关资源
        最近更新 更多