Help getting set-up with VSCode and THREE.js

Good day. I have recently started learning js and THREE.js. I have done most of my projects on Codepen and am now trying to move over to VS Code so when I lose internet access I can still have something to play with.

Unfortunately I am struggling to figure out what I need to do to get it working properly. I can seem to get a basic geometry to render but once I add texture or images I get nothing but a black background.

I have an html file with my styles in it and a separate js file. I have the images in the same folder as those but still can’t get my cube to have texture (images). (I also have the three.js and OrbitControls.js file in the same folder too).

I installed http-server, for node, based on what I read on the THREE.js website and stackoverflow and am currently running it at the root folder to all of my projects. When I type in localhost I get a file/folder tree so I know it’s working. I read this was due to THREE.js not being able to host files from the local hard drive.

What could I be missing? Is there more to this than having just the html/css/js file?

Thank you in advance. This has been kicking my butt.

VS code, great place to be working.

  • In VSCode add your local directory into the workspace.
  • For the libraries, you have three choices.
  1. make a copy of three.js and store it locally in your folder <script src="./three.js"></script>
  2. use an online repository (Content Distribution Network, CDN). You would add the line <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r121/three.js">
  3. You can use the module methods, which use a new version of JavaScript ES6, but can be a bit overwhelming if you need to add other support tools/libraries which are not available in ES6 format.

Go slow, look at error messages, StackOverflow can be your buddy on lots of that stuff. Good luck on the journey.

This does sound like a server issue. Try this VSCode extension:

https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer

If you can see the list of file in the browser, what happens when you open index.html?

No rendering? Sounds like me trying to use the orthographiccamera instead of perspectiveCamera. Try both, see if either works…

I am currently running 5.6.1 which seems to be the newest version. When I open the index.html I get a black weboage and nothing else. here is my index.html

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <title>Skybox</title>
    <script src="three.min.js"></script>
    <script src="OrbitControls.js"></script>
    <script src="skybox.js"></script>
  </head>
  <style>
    body {
      margin:0;
    }
    canvas {
      width:100%;
      height:100%
    }
  </style>
  <body>
  </body>
</html>

and here’s the js. This is from a tutorial I was trying to do.

let scene, camera, renderer;

function init() {

            scene = new THREE.Scene();

            camera = new THREE.PerspectiveCamera(55,window.innerWidth / window.innerHeight, 45, 30000);
            camera.position.set(100,100,1000);

            renderer = new THREE.WebGLRenderer({antialias:true});
            renderer.setSize(window.innerWidth, window.innerHeight);
            document.body.appendChild(renderer.domElement);

            let controls = new THREE.OrbitalControls(camera);
            controls.addEventListener('change',renderer);

            let materialArray = [];
            let texture_ft = new THREE.TextureLoader().load('https://imgur.com/IM0AGHy');
            let texture_bk = new THREE.TextureLoader().load('https://imgur.com/IM0AGHy');
            let texture_up = new THREE.TextureLoader().load('https://imgur.com/IM0AGHy');
            let texture_dn = new THREE.TextureLoader().load('https://imgur.com/IM0AGHy');
            let texture_rt = new THREE.TextureLoader().load('https://imgur.com/IM0AGHy');
            let texture_lf = new THREE.TextureLoader().load('https://imgur.com/IM0AGHy');

            materialArray.push(new THREE.MeshBasicMaterial({map:texture_ft}));
            materialArray.push(new THREE.MeshBasicMaterial({map:texture_bk}));
            materialArray.push(new THREE.MeshBasicMaterial({map:texture_up}));
            materialArray.push(new THREE.MeshBasicMaterial({map:texture_dn}));
            materialArray.push(new THREE.MeshBasicMaterial({map:texture_rt}));
            materialArray.push(new THREE.MeshBasicMaterial({map:texture_lf}));

            let skyboxGeo = new THREE.BoxGeometry(10000,10000,10000);
            let skybox = new THREE.Mesh(materialArray, skyboxGeo);
            scene.add(skybox);

            animate();
            
};
        function animate() {
            renderer.render(scene,camera);
            requestAnimationFrame(animate);
        }
        init();

NOTE: I currently have imgur links in there because I wanted to see if that would change anything. It’s the same pic for all links because I was testing. Also in imgur there are two different links I can copy and I tried both.

I have also tried,

 let materialArray = [];
            let texture_ft = new THREE.TextureLoader().load('bay_ft.jpg');
            let texture_bk = new THREE.TextureLoader().load('bay_bk.jpg');
            let texture_up = new THREE.TextureLoader().load('bay_up.jpg');
            let texture_dn = new THREE.TextureLoader().load('bay_dn.jpg');
            let texture_rt = new THREE.TextureLoader().load('bay_rt.jpg');
            let texture_lf = new THREE.TextureLoader().load('bay_lf.jpg');

which are how the images are labled and are in the same folder as the html and js. Like I said before I do have access to the images through my browser by typing in localhost and navigating the file tree.

here’s a basic yellow cube that does render for me

			var mesh;

			init();
			animate();

			function init() {

				camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 1, 1000 );
				camera.position.z = 400;

				scene = new THREE.Scene();

				var geometry = new THREE.BoxBufferGeometry( 200, 200, 200 );
				var material = new THREE.MeshBasicMaterial( { color: 0xffee00 } );

				mesh = new THREE.Mesh( geometry, material );
				scene.add( mesh );

				renderer = new THREE.WebGLRenderer( { antialias: true } );
				renderer.setPixelRatio( window.devicePixelRatio );
				renderer.setSize( window.innerWidth, window.innerHeight );
        document.body.appendChild( renderer.domElement );
        
        //

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

			}

			function onWindowResize() {

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

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

			}

			function animate() {

				requestAnimationFrame( animate );

				mesh.rotation.x += 0.005;
				mesh.rotation.y += 0.01;

				renderer.render( scene, camera );

			}

Not really sure where to go from here.

I appreciate the tips. I can get THREE.js to work but not with images.

that’s not an image, its a web page. Instead, check out, https://i.imgur.com/IM0AGHy.jpg . That is an image. Note the suffix.

You can use your browsers inspection tools to figure out the actually image address from any website you visit… Plus console.log(scene)in the browser is a great way to see what’s going on under the covers of your three.js project.

1 Like

Yup tried that link also. Here’s what I currently have:

let materialArray = [];
            let texture_ft = new THREE.TextureLoader().load('https://i.imgur.com/rdFkiq3.jpg');
            let texture_bk = new THREE.TextureLoader().load('https://i.imgur.com/rPWagYx.jpg');
            let texture_up = new THREE.TextureLoader().load('https://i.imgur.com/KrBJRPZ.jpg');
            let texture_dn = new THREE.TextureLoader().load('https://i.imgur.com/2sLBvMz.jpg');
            let texture_rt = new THREE.TextureLoader().load('https://i.imgur.com/IM0AGHy.jpg');
            let texture_lf = new THREE.TextureLoader().load('https://i.imgur.com/WgIjEaQ.jpg');

Still just getting a blank black screen.

Here’s a Codepen I can’t get to work either. The code is copied straight from the tutorial and then I added my image links.

Is the source code jacked up?

I don’t see a script for “three.js” in there.

try adding this to the html:

that didn't seem to work. I will say I'm not a jsfiddle or codepen fan. I much prefer CodeSandbox. Their integration to github is pretty amazing.

It’s under settings on Codepen. I just threw the OrbitControl script into the html body. The three.js script is there though.

Don’t forget browser, right click, inspect, check console for errors.

Uncaught ReferenceError: THREE is not defined
at OrbitControls.js:10
pen.js:10 Uncaught TypeError: THREE.OrbitControls is not a constructor
at init (pen.js:10)
at pen.js:41

Where is the fricking run button in that sandbox? oops. Apparently they restart the box after any editing. Add a blank character to the end of a line to restart anything. But I don’t think THREE is loading up (at least I can’t do a console.log(THREE) at the console.

I strongly recommend https://codesandbox.io/ They have a “local” console there that just applies to the particular sandbox. Additionally they have a system where you can send your work directly to a github repo. There are a lot of canned threejs sandboxes ready to go…

Ok so it was an issue with OrbitControls. Instead os adding it to a script I used the import method and changed the controls to

controls = new OrbitControls( camera, renderer.domElement );

based on this stackoverflow https://stackoverflow.com/questions/59769090/three-js-uncaught-typeerror-three-orbitcontrols-is-not-a-constructor

still having issues with getting vscode to work though

I saw that made the change, but I’m still seeing black screen. try a virgin threejs codesandbox.io as a starting point.

three js example ES6 by VComics works fine

The Codepen is working fine now. My files on my ssd are not though. I am getting these two errors:

Uncaught SyntaxError: Cannot use import statement outside a module OrbitControls.js:1

skybox.js:9 Uncaught ReferenceError: OrbitControls is not defined
at init (skybox.js:9)
at skybox.js:40

Something related to the OrbitControls.js but I don’t know what exactly it is. I’ve been searching for an answer and have tried different fixes but no luck.

Yup. That’s where I started the conversation. Decide if you are going to do the old way or the new ES6 module way. Normally I say go with the new stuff, BUT there are other libraries you will want to use that haven’t gotten into the new module method yet, sigh. And there are a whole ton CDN networks for threejs and OrbitControls…

Step #1. Open the file on your local drive in the browser (files you are serving up via http-server) Right click open inspector, then go to console… and type in these words: console.log(THREE)
what do you see? Then try console.log(scene) what do you see?

Its like trying to learn how to play baseball. All the lessons are telling you how to swing the bat, but you are in the car, three miles from the stadium saying ‘where do I park?’ which door do I use to get into the locker room, etc… ha.

/cc

@jfirestorm44 if you’d like to stick with codepen, here’s a tiny boilerplate you can base on (includes OrbitControls):

Three.js Codepen Boilerplate

  1. Instead of using import in codepen, it’s easier to fetch using <script> tags in the HTML section. So if you’d like to use https://threejs.org/examples/jsm/controls/OrbitControls.js as a source of OrbitControls, add the following import to the HTML tab:
<script src="//threejs.org/examples/js/controls/OrbitControls.js" />

(Remember to change /jsm to /js in the URL)

  1. Then, if you go to the source code of the script you import, you can see that it appends OrbitControls to the global THREE object (line 10). So to add the OrbitControls you can simply use:
const controls = new THREE.OrbitControls(props);

As for the local setup - can you please share what code (if it changed since the 5th post) and project structure (could be a screenshot) you are using?

console.log(THREE) gives me this followed by a long list of items:

{ACESFilmicToneMapping: 4, AddEquation: 100, AddOperation: 2, AdditiveAnimationBlendMode: 2501, AdditiveBlending: 2, …}

and console.log(scene) gives this followed by more items:

I do plan on sticking with CodePen but my profession has me leaving for months on end without internet access so I need to become familiar with VS Code and doing this type of stuff without internet.

For Codepen I will definitely use external websites that host the files.

Here’s my curent html and js:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <title>Skybox</title>
  </head>
  <style>
    body {
      margin:0;
    }
    canvas {
      width:100%;
      height:100%
    }
  </style>
  <body>
    <script src="three.min.js"></script>
    <script src="OrbitControls.js"></script>
    <script src="skybox.js"></script>
  </body>
</html>

and the skybox.js

let scene, camera, renderer;
      function init() {
        scene = new THREE.Scene();
        camera = new THREE.PerspectiveCamera(55,window.innerWidth/window.innerHeight,45,30000);
        camera.position.set(-900,-200,-900);
        renderer = new THREE.WebGLRenderer({antialias:true});
        renderer.setSize(window.innerWidth,window.innerHeight);
        document.body.appendChild(renderer.domElement);
        let controls = new OrbitControls( camera, renderer.domElement );
        controls.addEventListener('change', renderer);
        controls.minDistance = 500;
        controls.maxDistance = 1500;

            let materialArray = [];
            let texture_ft = new THREE.TextureLoader().load('https://i.imgur.com/rdFkiq3.jpg');
            let texture_bk = new THREE.TextureLoader().load('https://i.imgur.com/rPWagYx.jpg');
            let texture_up = new THREE.TextureLoader().load('https://i.imgur.com/KrBJRPZ.jpg');
            let texture_dn = new THREE.TextureLoader().load('https://i.imgur.com/2sLBvMz.jpg');
            let texture_rt = new THREE.TextureLoader().load('https://i.imgur.com/IM0AGHy.jpg');
            let texture_lf = new THREE.TextureLoader().load('https://i.imgur.com/WgIjEaQ.jpg');

            materialArray.push(new THREE.MeshBasicMaterial({map:texture_ft}));
            materialArray.push(new THREE.MeshBasicMaterial({map:texture_bk}));
            materialArray.push(new THREE.MeshBasicMaterial({map:texture_up}));
            materialArray.push(new THREE.MeshBasicMaterial({map:texture_dn}));
            materialArray.push(new THREE.MeshBasicMaterial({map:texture_rt}));
            materialArray.push(new THREE.MeshBasicMaterial({map:texture_lf}));

            for (let i = 0; i < 6; i++)
           materialArray[i].side = THREE.BackSide;
        let skyboxGeo = new THREE.BoxGeometry( 10000, 10000, 10000);
        let skybox = new THREE.Mesh( skyboxGeo, materialArray );
        scene.add( skybox );  
        animate();
      }
      function animate() {
        renderer.render(scene,camera);
        requestAnimationFrame(animate);
      }
      init();

All files are in the same folder. What I don’t understand is this error:

Uncaught SyntaxError: Cannot use import statement outside a module OrbitControls.js:1

so line 1 of that file is an import yet the browser doesn’t like it for some reason. Why would that be? It came straight out of the main download zip from THREE.js.

Thank you