Elena Epstein
Elena Epstein

Reputation: 75

How to set up image background in three.js?

I am trying to set up image background for my scene with globe in three.js, but unfortunately, when I did it the main object of my scene also became black (the same colour with background.

I used method:

renderer = new THREE.WebGLRenderer({ antialias: false, alpha:true });

Which makes default background transparent. And then I added image-background in CSS part.

My whole script for the scene looks like this:

        var container, stats;
        var camera, scene, renderer;
        var group;
        var mouseX = 0, mouseY = 0;

        var windowHalfX = window.innerWidth / 2;
        var windowHalfY = window.innerHeight / 2;

        init();
        animate();


        function init() {

            container = document.getElementById( 'container' );

            camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 2000 );
            //closer
            camera.position.z = 500;

            scene = new THREE.Scene();

            group = new THREE.Group();
            scene.add( group );

            // earth

            var loader = new THREE.TextureLoader();
            loader.load( 'textures/mapnew1.jpg', function ( texture ) {

                var geometry = new THREE.SphereGeometry( 180, 32, 32 );

                var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );
                var mesh = new THREE.Mesh( geometry, material );
                group.add( mesh );

            } );



            // shadow

            var canvas = document.createElement( 'canvas' );
            canvas.width = 128;
            canvas.height = 128;

            var context = canvas.getContext( '2d' );
            var gradient = context.createRadialGradient(
                canvas.width / 2,
                canvas.height / 2,
                0,
                canvas.width / 2,
                canvas.height / 2,
                canvas.width / 2
            );
            gradient.addColorStop( 0.1, '#000000' );
            gradient.addColorStop( 1, '#000000' );

            context.fillStyle = gradient;
            context.fillRect( 0, 0, canvas.width, canvas.height );

            var texture = new THREE.CanvasTexture( canvas );

            var geometry = new THREE.PlaneBufferGeometry( 300, 300, 3, 3 );
            var material = new THREE.MeshBasicMaterial( { map: texture, overdraw: 0.5 } );


            var mesh = new THREE.Mesh( geometry, material );
            mesh.position.y = - 200;
            mesh.rotation.x = - Math.PI / 2;
            group.add( mesh );


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

            stats = new Stats();
            container.appendChild( stats.dom );

            document.addEventListener( 'mousemove', onDocumentMouseMove, false );

            //

            window.addEventListener( 'resize', onWindowResize, false );

        }

        function onWindowResize() {

            windowHalfX = window.innerWidth / 2;
            windowHalfY = window.innerHeight / 2;

            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();

            renderer.setSize( window.innerWidth, window.innerHeight );

        }

        function onDocumentMouseMove( event ) {

            mouseX = ( event.clientX - windowHalfX );
            mouseY = ( event.clientY - windowHalfY );

        }

        //

        function animate() {

            requestAnimationFrame( animate );

            render();
            stats.update();

        }


        function render() {

            camera.position.x += ( mouseX - camera.position.x ) * 0.08;
            camera.position.y += ( - mouseY - camera.position.y ) * 0.08;
            camera.lookAt( scene.position );

            group.rotation.y -= 0.003;

            renderer.render( scene, camera );


        }


    </script>

This is my CSS:

body {
  color: #ffffff;
  font-family:'Futura';
  font-size:20px;
  text-align: center;
  background-image: url(textures/starfield.png);
  background-color: black;
  margin: 0px;
  overflow: hidden;
}

Do you have any ideas how to fix it and make globe visible?

Thank you very much!

Upvotes: 2

Views: 6838

Answers (4)

Ismail
Ismail

Reputation: 75

The previous solutions didn't work for me, they miss the using of callback so at least from v.0.124 of the library, this is how you can set the background image for the scene:

  var texture_bg = new THREE.TextureLoader().load("img/bg.jpg", () => {
    scene.background = texture_bg;
  });

Upvotes: 0

Hitesh Sahu
Hitesh Sahu

Reputation: 45062

There are two ways to do it

1) Load a image using TextureLoader and set it as background. This will result into static background which may not look very realistic.

 var texture = new THREE.TextureLoader().load(
      "https://images.pexels.com/photos/110854/pexels-photo-110854.jpeg?auto=compress&cs=tinysrgb&dpr=2&h=650&w=940"
    );
   scene.background = texture;

2) Use skybox to load images for top, left, right bottom, front back sides. Then set them inside a cube or sphere geometry

var urls = [
      "https://images.pexels.com/photos/110854/pexels-photo-110854.jpeg",
      "https://images.pexels.com/photos/110854/pexels-photo-110854.jpeg",
      "https://images.pexels.com/photos/110854/pexels-photo-110854.jpeg",
      "https://images.pexels.com/photos/110854/pexels-photo-110854.jpeg",
      "https://images.pexels.com/photos/110854/pexels-photo-110854.jpeg",
      "https://images.pexels.com/photos/110854/pexels-photo-110854.jpeg"
    ];

    var materialArray = [];
    for (var i = 0; i < 6; i++)
      materialArray.push(
        new THREE.MeshBasicMaterial({
          map: new THREE.TextureLoader().load(urls[i]),
          side: THREE.BackSide
        })
      );

    var skyGeometry = new THREE.SphereGeometry(400, 32, 32);
    var skyMaterial = new THREE.MeshFaceMaterial(materialArray);
    var skybox = new THREE.Mesh(skyGeometry, skyMaterial);
    scene.add(skybox);

This will give a sphere with images as texture on backside. Just replace THREE.SphereGeometry with THREE.CubeGeometry and you can emulate envMap.

Upvotes: 2

edap
edap

Reputation: 1114

Since a while, there is:

var texture = new THREE.TextureLoader().load( "textures/bg.jpg" );
scene.background = texture;

I'm using three.js v 0.87

Upvotes: 2

TheJim01
TheJim01

Reputation: 8866

Regarding the background image, you are setting the alpha value for WebGLRenderer, which is correct. You didn't post your CSS, but ensure you're setting the background image on your container, not on the canvas.

Also, comment out this line:

renderer.setClearColor(0x000000, 0);

You don't need to set a clear color, since you are clearing to transparency, not a color. That should resolve the background image issue.

Regarding the all-black model, you need a light in your scene. Try adding this to your init method:

var light = new THREE.PointLight(0xffffff, 1, Infinity);
camera.add(light);

This will add a light source at the location of your camera (and will follow the camera as it moves).

Edit to add snippet:

var container, stats;
var camera, scene, renderer;
var group;
var mouseX = 0,
  mouseY = 0;

var windowHalfX = window.innerWidth / 2;
var windowHalfY = window.innerHeight / 2;

init();
animate();


function init() {

  container = document.getElementById('container');

  camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 2000);
  //closer
  camera.position.z = 500;
  
  var light = new THREE.PointLight(0xffffff, 1, Infinity);
  camera.add(light);

  scene = new THREE.Scene();

  group = new THREE.Group();
  scene.add(group);

  // earth

  var loader = new THREE.TextureLoader();
  loader.crossOrigin = '';
  loader.load('https://upload.wikimedia.org/wikipedia/commons/thumb/8/83/Equirectangular_projection_SW.jpg/640px-Equirectangular_projection_SW.jpg', function(texture) {
    var geometry = new THREE.SphereGeometry(180, 32, 32);

    var material = new THREE.MeshBasicMaterial({
      map: texture,
      overdraw: 0.5
    });
    var mesh = new THREE.Mesh(geometry, material);
    group.add(mesh);

  });



  // shadow

  var canvas = document.createElement('canvas');
  canvas.width = 128;
  canvas.height = 128;

  var context = canvas.getContext('2d');
  var gradient = context.createRadialGradient(
    canvas.width / 2,
    canvas.height / 2,
    0,
    canvas.width / 2,
    canvas.height / 2,
    canvas.width / 2
  );
  gradient.addColorStop(0.1, '#000000');
  gradient.addColorStop(1, '#000000');

  context.fillStyle = gradient;
  context.fillRect(0, 0, canvas.width, canvas.height);

  var texture = new THREE.CanvasTexture(canvas);

  var geometry = new THREE.PlaneBufferGeometry(300, 300, 3, 3);
  var material = new THREE.MeshBasicMaterial({
    map: texture,
    overdraw: 0.5
  });


  var mesh = new THREE.Mesh(geometry, material);
  mesh.position.y = -200;
  mesh.rotation.x = -Math.PI / 2;
  group.add(mesh);


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

  stats = new Stats();
  container.appendChild(stats.dom);

  document.addEventListener('mousemove', onDocumentMouseMove, false);

  //

  window.addEventListener('resize', onWindowResize, false);

}

function onWindowResize() {

  windowHalfX = window.innerWidth / 2;
  windowHalfY = window.innerHeight / 2;

  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();

  renderer.setSize(window.innerWidth, window.innerHeight);

}

function onDocumentMouseMove(event) {

  mouseX = (event.clientX - windowHalfX);
  mouseY = (event.clientY - windowHalfY);

}

//

function animate() {

  requestAnimationFrame(animate);

  render();
  stats.update();

}


function render() {

  camera.position.x += (mouseX - camera.position.x) * 0.08;
  camera.position.y += (-mouseY - camera.position.y) * 0.08;
  camera.lookAt(scene.position);

  group.rotation.y -= 0.003;

  renderer.render(scene, camera);


}
body {
  color: #ffffff;
  font-family: 'Futura';
  font-size: 20px;
  text-align: center;
  background-image: url(https://upload.wikimedia.org/wikipedia/commons/6/62/Starsinthesky.jpg);
  background-color: black;
  margin: 0px;
  overflow: hidden;
}
<script src="https://threejs.org/build/three.js"></script>
<script src="https://threejs.org/examples/js/renderers/Projector.js"></script>
<script src="https://threejs.org/examples/js/libs/stats.min.js"></script>
<div id="container"></div>

three.js r86

Upvotes: 2

Related Questions