Check out a free preview of the full Advanced Creative Coding with WebGL & Shaders course

The "Applying Images to Spheres" Lesson is part of the full, Advanced Creative Coding with WebGL & Shaders course featured in this preview video. Here's what you'd learn in this lesson:

Matt demonstrates how to map a sphere by applying an earth image file to a texture, and explains how different mesh types can help enhance a visual.


Transcript from the "Applying Images to Spheres" Lesson

>> So let's try to make this more of an Earth. So if you open up the repo, you're gonna see an asset inside the repo, inside the src/demos folder, and it's gonna be a JPG of the Earth, so earth.jpg. And let's just drag and drop this into our project folder that we created here, this webgl folder that we created on our desktop.

Just drag and drop it there, or save it there somehow. And now let's load this into our three.js scene and apply that to the sphere. So if we go here, we've dragged and dropped it in, make sure it's in the same folder as our sketch.js and as our project.

And then I'm gonna go up, and what I'm gonna do is, I'm gonna load a new texture somewhere just above my material here. So remember, material has to do with the surface quality, and so texturing has to do also with the material. So we're gonna do this, we're gonna say, const texture = new, and then we're gonna use an interface called TextureLoader.

So it's gonna be new THREE.TextureLoader().load, and then we're gonna just say earth.jpg, that's the URL to the file. So that's the line that we can use to load a texture from a file. It returns a THREE.TextureInterface, which is gonna be used for, it's kinda like an image. But it's actually an image that exists on the GPU as opposed to just an image that exists in memory.

And then whenever we create these materials, so we have to use a certain type of material. So MeshNormalMaterial is really good for debugging and for seeing the visualization of the sphere or of the object. But what we really want is, we want to texture this. So we're gonna use MeshBasicMaterial, and then we're gonna pass in, so instead of these options, we're gonna pass in a map, and we're gonna say texture.

So map is just the the name of the attribute that has to do with textures. And so now all of a sudden, if you get this, you should have a 3D Earth. And then maybe the next thing we'll do, cuz we're trying to create this little tiny solar system here.

Trying to create something animated, something that's running on its own, maybe an animation of some kind. The next thing we'll do is, we'll find a Moon image. I've already got one in the repo here, but you could have just as well found this online. So here in the repo, in the src/demos, I've got moon.jpg, and I'll just drag and drop this in as well.

So I'm just gonna drag and drop the JPG into our folder. And then I'm gonna do the same thing. Except, instead of copy-pasting this line, we could certainly do this line again and just create a new TextureLoader and load it. But what I'm actually gonna do is just reference the texture loader once, And I'm gonna use it twice, so I'm gonna reuse this texture loader.

And the benefit of that is that three.js, the TextureLoader here will be able to run these in parallel, at least theoretically. This is how it should be loading things under the hood. And it should be able to cache things a bit better and stuff like that. So it should just be a bit more optimized this way.

So now we're gonna say, moonTexture, then loader.load('moon.jpg'). So now we've loaded two textures, so we've loaded the Earth and the Moon texture. And now we're gonna create a new mesh that would be our Moon. So just like before, we have our mesh, but now we're gonna create another mesh.

We're gonna say, let's say const moonMesh = new THREE.mesh. And for now, let's just use the same parameters just to keep it simple. We'll we'll update this in a second. But for now, let's just use the same stuff, geometry and material. And we do scene.add(moonMesh), and so now, you're not gonna see anything different.

And that's because the Moon is, first of all, it's the same material, so it's actually also showing an Earth texture. And second of all, it's in the exact same position as the Earth. And so what we wanna do is, we wanna place this Moon further off into orbit, I guess you could say.

So we're gonna say moonMesh.position.set, maybe make it 1 along the x-axis, and then maybe 0.5 on the y, and maybe 0 along the z-axis. And now all of a sudden, we sort of see something emerging, it's like a tumorous growth. And then what we wanna do is make it a lot smaller because it's a Moon, not an Earth.

So we're gonna say moonMesh.scale.setScalar, maybe 0.25. None of this is very accurate to real measurements, but it's just for fun. Maybe we'll make it a bit further away from the Earth by saying, make the position a little bit larger. So the larger these position values, the further away it'll appear from the Earth.

And then maybe also here, if you're starting to edit your work, you might think, okay, the camera's a little too close, I wanna pull this camera out so we can scroll up. Go to our camera.position, maybe increase these values as well, just so that we're a little bit further away from the center of the world.

Okay, so now we've got two Earths, but that's not what we want, we want a Moon and an Earth. So we're gonna create a new material called moonMaterial. And we're gonna say, new THREE.MeshBasicMaterial. We're gonna pass in map and we're gonna say moonTexture instead of mapTexture. And then we're gonna update the mesh so that it's using the moonMaterial.

So now just with these few lines of code, we have this 3D Moon and Earth, which is kinda cool. But maybe what we'd really like is for it to rotate, for this moon to rotate, or even for the Earth to rotate. So we're just gonna scroll down into our render function.

We're gonna say mesh, because that's how we called our Earth, so mesh.rotation.y = time. And what that's gonna do is, it's gonna make the the rotation, which is in radians, this y-axis, it's gonna make it equal to the time in seconds. And time comes from canvas sketch, it's a property that we can use to create these animations that are very much locked to the framerate of whatever we're rendering.

Whether it's in the browser at 60 frames, or whether it's a GIF or MP4 at maybe 24 or 30 frames or something. So every second, it's increasing the rotation here in radians. I mean, we can slow it down by just multiplying that by a lower number, just so it's a nice, gradual rotation of the Earth.

And then maybe we'll do the same thing for the Moon mesh, cuz I guess technically the moon is rotating slowly as well. And so we'll use a slightly different value just so that they're not rotating perfectly in sync. Whatever you'd like there.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now