Hey my fellow coders and welcome back to the third part of this video series where we are creating a Minecraft clone in JavaScript why are we doing that because we can so what are we working on today let’s take a look there’s going to be three main parts that we’re working On here so the first you can see is resources so I have some Stone in the back here we have some coal here we can change the scarcity of these resources we can change the size of the deposits it’s a bit hard to see right now so We’ll peel back the terrain a little bit later you can see what these resources look like but we’re going to be using 3D noise to create these little pockets of resources underneath the terrain so that’ll be really fun the second thing that we’re working on as you’ve probably Noticed if you’re an astute Observer is textures so we have these beautiful pixelated Minecraft textures that look much better than the flat colors we had before so I’ve just loaded a classic Minecraft texture pack here and we’re applying these textures to the blocks and last but not least we’re going to be Adding some Shadows so you can see that we have some Shadows here being cast by this mountain and this just adds a lot of depth to the game and just makes everything look a lot sharper so those will be the three things that we’re working on in this video so without Further Ado let’s get to it all right so I’m picking up right where we left off in part two of this video series so let’s just jump right into it let’s add those resources first I’m going to open up our blocks file and we need to Add some Stone here so I’m going to add another entry to our block object here and let’s call this Stone give it an ID of three name Stone and we’ll just give that a little bit of a gray color so now that we have our new block type to find Let close out this file or done with that go into our world file now to begin with I’m going to be hiding our terrain because that’s just going to hide the resources that we’re generating um but we’ll need a new function here called generate resources and I’m going to Define that Right before generate terrain now generating our resources is going to be very similar to how we did the terrain generation with one minor difference in that we’re using 3D noise instead of 2D noise so what exactly is 3D noise and how does that compare to 2D noise with 2D noise the x and z coordinates correspond to the horizontal position in our world we pass these values into our 2D Simplex noise function to get a value which ultimately determines the height of the terrain at that location with 3D Noise We compute a noise value at each X Y and Z coordinate in our world we generate pockets of resources by thresholding these noise values any location where the noise value is above above the threshold we create a block and any value below the threshold is left empty we first need to define a triple Four Loop here where we iterate over the XY and the Z so let’s go ahead and compute the 3D noise value at this location so we’re going to need a Simplex noise generator and a random number generator now we want our world to always be the same each time we Generate it initi number we created this um special random number generator class where we can pass in a seed and it’ll always spit out the same sequence of random numbers so we want to reuse this same random number generator when we’re generating resources so that all the resources all the terrain everything is Going to be exactly the same each time we generate the world with a specific seed so I’m going to actually take this line here and we’re going to move that up to our main generate function and then we’re going to pass that in to generate resources and generate Terrain so let’s add that parameter here and here as well and then we’re going to define a new Simplex noise generator in each method so we’ll add a new one in here as well okay so now that we have a Simplex noise generator we can compute The value so we’ll do simplex and you see there’s a noise 3D function here and this takes in the X Y and Z so for each set of XYZ coordinates we get a unique noise value now what are we going to do with that value we’re going to threshold That so anything below the threshold will not be a block anything above the threshold will be a block so let’s just use some placeholder values for now for the scale and the scarcity just so we can kind of see what this looks like so if the Val value is greater than 0.5 then we will set the block ID at the set of XYZ coordinates to Stone and let’s scale our noise a little bit so it’s a bit more smoothed out and now if you go and look at our world we can see that we have our Stone resource Being generated so you can see we get kind of these blob structures here so by changing that threshold value the 0.5 it’s going to make those blobs bigger or make them smaller depending on what we set this to and the the scale values here are going to control the overall Size of those blobs so let’s add those parameters in let’s add some UI controls so we can tune that right from the UI so going back into our blocks file I’m going to add those parameters right in here so we’ll add a scale and this will be an object with an X Y and Z scale and then that threshold let’s call that scarcity so we’ll just set that to 0.5 now we need to add some UI controls for that so similarly to how we’re controlling the properties of our world object we can also import blocks here And we can tune the properties on our blocks so we can modify these properties in real time right from the UI so I’m going to add a new resources folder and then I’m going to go ahead and add some controls to uh T in those parameters all right so I went ahead and Added some UI controls for those parameters you can see we’re controlling scarcity as well as the X Y and Z scales so lastly let’s go into World here and let’s get rid of these hardcoded constants and instead we’ll do blocks. stone scale dox and and then we’re going To use the scarcity value here so now if we go back into our game here I can lower the scarcity and that’s going to make the resource less scarce AKA more abundant and it’s going to make the resource deposits bigger as I increase that the deposits will get smaller so We’ll set that to some value here and then you can see as I control these scales it’s going to control the size in that particular axis so now that we have our resources def find we need to go and add our terrain back in So how that is Going to work is that everything above grass level gets removed everything below we keep and fill in the empty space with dirt so let’s go add that terrain back in so let’s first uncomment our generate terrain function and then let’s go down and modify that a Bit so we need to modify this logic here so right here we only want to set the blocks to dirt if there’s not a resource block already there so we’ll just add to the condition here now we need to modify this case slightly because anything that doesn’t pass here is going to fall Through so if Y is greater than height then we want to set the blocks to empty so now we can go and look at our terrain here and we can see that we’re getting these resource deposits but everything that is at the height of the terrain is being set to Grass we now Have our resources fully integrated with our terrain and I think it’s time that we add a few more resource types in so we’ll add coal and we’ll add in Iron as well so back in our blocks file let’s create two more entries we’ll do one for coal ore and then another For iron ore and we’ll just go ahead and update these properties and then we’ll just tweak these parameters a bit to make it a little different from the stone so now that we have our coal ore and our iron or blocks to find we need To go back into our world file and we need to update generate resources to generate those blocks in in addition to the stone so right now this is sort of hardcoded into just generate the stone so we need to wrap everything here in one more for Loop to iterate over all Those resources so I’m actually going to define a separate array in this file at the bottom here so we’ll do export const resources and that is going to be equal to an array that contains blocks. stone blocks. coal ore and blocks. iron ore so then back in world let’s import The resources and now we can iterate over this array and generate all of those resources so going back down to our function here I’m going to do resources. for each and then for each resource we want to run all of this code so we’re basically going to be running this Resource generation code three times one for each of the resource types so all we need to do is to replace blocks. stone with resource so there we’ve app to generate resources to handle multiple resources now we need to update the UI code as well to expose controls for all of our Different block types so let’s go into our UI file and everywhere where we see Stone we’re going to have to update that as well so I’ve updated our UI code to handle multiple resources so really all I’ve done I’ve imported resources here at the top we don’t need blocks Anymore and then iterate over all those resources actually create another subfolder for each resource just to keep things a bit more organized and then all the code we had before is basically the same but we’re now adding that to the resource folder and we’re accessing the properties on resource instead of Blocks. stone so if we save this and then go back to our game here you can see we have a whole bunch of different controls on the side and you can already see that uh we have our coal resource to in here now everything’s a bit hidden by The terrain so I think I’m going to quickly disable terrain generation so we can see all of these resources hidden underneath here all right so I’ve just temporarily disabled terrain generation so we can see what’s going on under the hood here we have our three resource Subfolders so we have stone coal ore and iron ore so let’s say I want to increase the scarcity of the stone so we’ll make it a little less abundant and then I want to squash it down in the Y AIS so I’ll reduce the scale there And maybe spread it out in the X and the z-axis now we can go into coal let’s say I want to do little tiny pockets of coal ore so I’ll make the scales a bit smaller here and then I will just increase the scarcity a bit so we just Have these little pockets of coal in our terrain and then the iron ore is something that it’s going to be more scarce you got to mine a bit more to find that so let’s tweak that a bit the scarcity is already quite high and let’s reduce the scales a Bit and let’s say we have these kind of flat veins of iron ore that sort of dig down into the terrains so you can see that we can independently control the formation of all these different resources and it’s very easy if we want to go back and add more resources all we Need to do is go into our blocks file and we just need to add more block types here and then each block type that’s a resource will add it to the resources array so it’s a very extensible way of adding the resources into the game so in terms of Our first task of adding resources to our world we are completely done with that now we’ve added everything that we needed to can control the scarcity the scale and we can Define multiple resources so the next two tasks that we need to do are adding textures and Adding Shadows so let’s do the textures first and then we’ll finish up with the Shadows so before we add textures to our game we need textures that we can work with or image files Mojang who creates Minecraft actually has a GitHub repository that contains all the Minecraft assets for moniters to use so In this GitHub repository we can go under resource pack and we can go under textures and blocks and here you can see it has the PNG files for all of the different blocks in the game so this is what I’m using for the texture you are more than welcome to use any other Texture pack that you can find and I’ll be sure to provide a link to this repository in the description down below so we’re back in our code now and you can see under the public folder I’ve added a new directory called textures and under here I’ve added all the Different textures that we’re going to be using in the creation of this Minecraft clone so we’re going to be importing all of these textures using 3js and then we’re going to creating materials that use these textures and then adding those to the blocks so right now in our world file we’re defining the Material for our blocks it’s all the same because they’re all just a flat color so we just have one material that we’re using we’re going to be defining materials on each of our blocks now because they all have different textures so let’s go ahead and delete that Material now that’s going to pose some problems when we’re generating the meshes because our instance mesh expects that each instance has the same material so there’s a couple different approaches for handling this I’m going to take a kind of simple nonoptimal naive approach and we’re just going to Create a new instance mesh for each block type that we have now this works in the case of the game that we’re working on because we’re just going to have a few different block types but if I were to be making a full production Minecraft game there’s actually some Manipulation you can do to the default shaders so much like how we’re setting the color here we can modify the Shader code for instance mesh to set the texture for each block type but that’s a bit more advanced than I wanted to cover in this tutorial Series so we’re just Going to be using the multiple instance meshes for each block type now in order to load the textures we’re going to need to use a texture loader so first let’s import the 3Gs library and then let’s create a texture loader now let’s create a separate function here where we will Load the texture so we’ll pass in the path to the texture in our assets directory here and then we’ll create that texture by loading it using our texture loader and I’m going to be loading everything synchronously which is definitely not the best way of doing It um but it will keep things a bit simpler um but in production code I would use load async here so the client isn’t waiting for all of the textures to load now one additional thing that we need to do to our texture is we need to set the color Space 2 Three and that’ll be the srgb color space so I’m not going to get into color spaces that’s far too complex for this video so as of 3js version 152 you need to set the color space on your textures to the srgb color space for them to appear correctly or they will likely Look washed out so once we do that then we can return the texture now what we’re going to do next is we’re going to create an object that contains all of our textures that we need and then we’ll reference those textures as we create new materials for each of our blocks so I’ve defined all of our textures here you can see we’re loading in for now just the dirt the top of the grass block and then the sides of the grass block and then our stone coal and iron textures now for each of our block types we need to define a material property The grass block is actually going to be a little bit different because each side has a different texture on it so on the top it’s going to be grass on the bottom it’s going to be dirt and on the sides it’s going to be well I can just pull it Up here it’s going to be the kind of this little grass overhang on the side and then the rest will be dirt so the 3js g box geometry you can actually pass in an array of six materials and then we’ll apply a different material to each Side of that box so I’ll quickly Define the materials array for our grass block so you can see the the first entry here is for the right side then we have the left top bottom front and back so the top is set to Grass the bottom is set to Dirt so we just needed to Define these six different Lambert materials now the rest of our blocks all have the same texture on each side so they’ll be a bit simpler so we’ll just be doing a material for dirt and that’ll be a new mesh Lambert material and then we’ll set The map property so this Maps the texture to textures. dirt and I’m going to go Ahad head and add materials to the rest of our block types all right so we have textures for our stone coal and iron or blocks now so we’re all set to create our new instance Meshes and use these materials instead of the other material that we had to find in our world class so we’re going to start by creating a lookup table where the key is the block ID so that lookup table is going to be an object called meshes so to build out our lookup Table we’re going to get the values of our blocks object then let’s filter out the empty block and then for each of those we going to create an instance mesh the max count is a constant for all of the different meshes so we’ll just move that up Here and then let’s take this code and we’ll add it inside of our for Loop here now rather than using this material which we previously had defined at the top of the file we’re going to get the material associated with this particular block type and then for debug purposes Let’s set the name of our mesh to the name of the block type then finally we’re going to add this mesh to our lookup table our lookup table we’re using the block ID for the key so we’ll do block type. ID will be equal to mesh now we’ve defined all of these instance Meshes here so let’s go down into the inner loop here where we’re creating all of our instances so we can start by eliminating this line here we won’t need that and I’m actually going to move the empty block ID check up to the top here so if block ID is equal to block. Empty. ID then we’ll just continue there otherwise we’ll get the by using our lookup table and we’ll pass in the block ID um now we no longer need this line here since we’re using textures not colors so we can go ahead and remove that and then finally at the bottom here We need to add all of the instance meshes instead of just a single one so now if we go and look at our game now we should expect to have some textures and it looks like we do so I can see some grass here some dirt the stone the coal So everything is looking as expected um there is one issue though if we zoom in here we can see that our textures are really blurry and don’t have that sharp crisp look that we would expect and that’s because 3js is automatically applying filtering to our textures so we don’t want the type of Filtering that it’s using we just want to use nearest neighbor filtering so we need to go back into where we’re loading the textures so we want to locate our load texture function and we’re going to change the filtering that we’re using so do texture Min filter is equal to 3. nearest filter and we’ll use the same for the Meg filter so now if we go back to our game and zoom in on these blocks we can see we get nice crisp textures where we can see each individual pixel so the final thing that we need to do to Our scene is to add in some shadows and that’s really quite simple it just requires tuning a few specific parameters so let’s go into our our main file and set up the Shadows on the renderer so the first thing that we need to do when adding Shadows is we need to Enable the shadow map on the render and then for our instance meshes we also need to set those up so that they cast and receive Shadows so going back up in the code we wrote here where we create those instance meshes we’ll do mesh. cach Shadow equals true and mesh. Receive Shadow equals true so now that our meshes are set up to cast and receive Shadows we need to set up our lights to also cast Shadows so back in main I believe is where we have our lights set up here so I’m just going to use one directional light we’ll just Have one sun in the game and then we’ll set up this light so that cast Shadow equals true and this will enable Shadow casting for that light source I’m also going to rename this light to Sun just so it’s a bit clear what that light is so if we go to Our game now we should expect to see some shadows and things just don’t look quite right we’re not really seeing those Shadows being cast so in situations like this 3js has a really useful helper class so what we can do is we can create a shadow Helper and that’ll be a new 3. Camera Helper and then we’re going to pass in the camera associated with the Shadow on our sun Shadows are calculated kind of using a camera so you can actually take that camera pass it into this camera Helper and visualize it so we’ll add that shadow helper to the Scene and now when we go back and look at our world we can see what the issue is here our light source is sitting at the coordinates of 111 so if you go and look it’s sitting there and it’s casting towards the origin this box really should be Encapsulating our entire world we need to update the position of our light as well as the bounds of this box so first let’s set the position of our light to 50 5050 now eventually the light is going to be following the player as it moves around the world so that the Shadows are Always being cast where the player is in the world um but for now we’ll just use a static position and we need to set some of the Shadow properties on our light source so so we’ll do sun. Shadow and then we’ll set some properties on The camera so we need to set the left the right the top and the bottom bounds of that camera box and we’ll also set up the near and the far plane so if you go back to our game now we can see that there are indeed Shadows being Cast so if let’s zoom out a bit so we can see that our box is now completely encapsulating our world um picking 100 might have been a little bit too big so you actually want to optimize that value because right now our shadows are looking pretty blurry so if you get that Box tighter around the world it’s going to improve the resolution of our shadows so let’s go back and set these to 50 50 50 50 and 50 so you can see that box is much more closely sized to our world now and the Shadows also look much better so there’s Still a few artifacts that we need to work out here um you can kind of see some Shadow lines along here we’re getting this weird kind of grid along these flat parts so we can adjust the bias of our shadows and that we’ll remove that so we’ll set the bias on our Shadow to minus 005 want to pick very small values here um this has quite a significant effect when you pick larger values looks like we set that value quite a bit too big um we’re getting some weird artifacting here we’ll do 0.00005 and I think that’s pretty good Um it could still probably tweak in a bit more but um that’s better than what we had and I notice some of the artifacting is improved on the flat ground as well now just for your awareness there are different Shadow types that we can use so we can actually go to our Renderer go to Shadow map and the type so if I just type in 3. Shadow here so you can see there’s a basic Shadow map a PCF soft shadow vssm shadow and a PCF Shadow now the PCF soft Shadow is going to be the best looking one um That’s going to be the most performance intensive whereas basic is going to be the best performance but it’s going to look the worst so so you can see with the basic Shadow map we’re getting very jaged edges here doesn’t look very good I much prefer the smooth effect So let’s go and look at PCF Shadow and that looks pretty good we get a bit of smoothing on the edges so let’s try the PCF soft Shadow map a very soft looking Shadow and I think this really has the best look so we’ll go with with this for Now until we have some performance issues so one last thing that you can tweak to improve the either the performance or the quality of the Shadows is setting the resolution of the Shadow map so that is also set on the light source itself so we’ll do sun. Shadow and then you can set the map size and this will be a vector 2 so let’s set this to something really low for now and do 256 by 256 and you can see that it’s it’s very blurry and the Shadows almost don’t even show up in some cases now let’s go on The opposite extreme I’ll do 2048 by 2048 you should always um pick powers of two here and now you can see that we get a much sharper Shadow so it’s kind of depends on the look you want to go for here um I think we’ll probably choose Something in between so I’ll do maybe 52 x 512 let’s take a look at that um I kind of prefer the blurriness here it helps kind of reduce the harshness of all the jaged edges in the world so I think we’ll stick with that value and there’s probably a bit more tuning we Could do on the bias but I think that’ll suit us well enough for now so there you have it that’s all I planned on covering in this video we added in some some new block types we added in some resources added some textures and some shadows and our world is really starting To come together now and I think with the textures in there it really looks like Minecraft so in the next video we’re going to be adding a playable character that we can move around with the keyboard and mouse and then in the video after that the fifth video we’re Going to be adding Collision detections so the player will actually be interacting with the world they’ll be able to move around run into blocks jump up and down Hills I think that’ll really start to feel like a game at that point so thank you so much for watching The series if you want to be notified of the new lessons coming out be sure to hit the Subscribe button below and please like this video really helps out the channel so until next time take care everyone thanks for watching Video Information
This video, titled ‘Build a Minecraft Clone with Three.js // Part 3: Resources, Texture and Shadows’, was uploaded by Coffee Code Create on 2023-10-27 16:34:29. It has garnered 256 views and 15 likes. The duration of the video is 00:29:48 or 1788 seconds.
Do you want to learn how to create a Minecraft clone from scratch with JavaScript? In this 10 part video series, I’m going to show step-by-step how you can create a Minecraft clone with procedurally generated worlds, collision detection, terraforming and much more.
0:00 Intro 1:25 Adding Stone Resource 8:45 Adding Coal and Iron Resources 13:30 Textures 21:51 Shadows 29:10 Outro
🕹️ Demo: https://dgreenheck.github.io/minecraft-threejs-clone/ ⭐️ GitHub: https://github.com/dgreenheck/minecraft-threejs-clone ▶️ Playlist: https://www.youtube.com/playlist?list=PLtzt35QOXmkKALLv9RzT8oGwN5qwmRjTo