Procedural Textures
What Are They?
In classic texturing, we use 2D images, often pictures that have been shaped specifically to match an object. Let’s imagine you are creating a medieval fantasy game and working on a dwarf pub with multiple large, "old school" wooden tables. With classic 2D texturing, you have three choices:
-
Create a single texture and use it on all of the tables (but every table is going to look the same)
-
Create a collection of various wood textures and apply them randomly to each table
-
Create a separate texture for each table, ensuring that they each look different
None of these choices seems ideal.
Enter procedural textures.
Procedural texturing is a way to programmatically create a texture. There are two types of procedural textures: code-only, and code that references some classic 2D images, sometimes called 'refMaps' or 'sampler' images.
One main advantage of procedural textures is that they are written using a fragment shader (using GLSL in the case of Babylon.js). That means the code generating the texture is executed by the GPU, not the CPU (that is to say, not in JavaScript code). This has a strongly positive performance impact.
Procedural textures can be generated:
-
Only once, to create a texture that is then cached
-
Every 1, 2, 3, 4, or more frames to create an animated texture (like fire)
See more about 'refresh rate' in the Custom Procedural Textures section... far below.
Procedural Textures in Babylon.js
Babylon.js offers you an easy out-of-the-box way to use this kind of texture. The engine itself provides you with standard default textures that you can use right now. It also gives you the ability to create custom procedural textures and package them in a simple way.
Using a Procedural Texture
Applying a procedural texture is the same as using a classic one. Let’s start with a simple mesh (a cylinder in this case) and attach it to your scene:
import { MeshBuilder } from "@babylonjs/core/Meshes/meshBuilder";const cylinder = MeshBuilder.CreateCylinder("mycylinder", { height: 7, diameterTop: 2, diameterBottom: 2, tessellation: 12, subdivisions: 1 }, scene);Then, you need to create a StandardMaterial:
import { StandardMaterial } from "@babylonjs/core/Materials/standardMaterial";const material = new StandardMaterial("material", scene);Now create a WoodProceduralTexture object, passing a name, the size of the generated texture, and the scene.
import { WoodProceduralTexture } from "@babylonjs/procedural-textures/wood/woodProceduralTexture";const texture = new WoodProceduralTexture("texture", 1024, scene);You are almost set! All you need to do now is associate the texture with the material as a diffuseTexture, for instance (or emissiveTexture, specularTexture, or any other texture), and then apply the material to the mesh.
material.diffuseTexture = texture;cylinder.material = material;You can optionally change the values of special default properties. Here is an example of setting two properties for the WoodProceduralTexture:
import { Color3 } from "@babylonjs/core/Maths/math.color";import { Vector2 } from "@babylonjs/core/Maths/math.vector";texture.woodColor = new Color3(0.49, 0.25, 0);texture.ampScale = new Vector2(1.0, 1.0);Noise Procedural Texture
The NoiseProceduralTexture is available out of the box with the core Babylon.js engine.
You can create one with the following code:
import { NoiseProceduralTexture } from "@babylonjs/core/Materials/Textures/Procedurals/noiseProceduralTexture";const noiseTexture = new NoiseProceduralTexture("perlin", 256, scene);The NoiseProceduralTexture exposes the following properties:
- brightness: Gets or sets a value between 0 and 1 indicating the overall brightness of the texture (default is 0.2)
- octaves: Defines the number of octaves to process (default is 3)
- persistence: Defines the level of persistence (0.8 by default)
- animationSpeedFactor: Gets or sets animation speed factor (default is 1)
Using Standard Procedural Textures
Babylon.js also has a number of pre-built procedural textures that are gathered in the Procedural Texture library: https://github.com/BabylonJS/Babylon.js/tree/master/packages/dev/proceduralTextures
You can use them in your project:
- Using npm with
npm install --save @babylonjs/procedural-textures - With a direct reference to: https://cdn.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js
All standard procedural textures can be used in the same way, but they each have specific properties: