How To

Apply Material to Individual Faces


How To Map Material to Individual Mesh Faces

This method is only available when creating a mesh using the MeshBuilder method.

The following meshes have identifiable faces: box; cylinder; extruded polygon and polyhedron have identifiable faces and have the faceUV and faceColors parameters in the options using the MeshBuilder method to create them. This means that each of their faces can have a different texture or color. For colors a particular color is mapped to a particular face. For textures part of the image file is mapped to a particular face. This can be done with any image and it is often useful to use a texture atlas containing a number of images combined into one image file.

When you are concerned about the orientation of the images on the faces then it can be necessary to have different orientations of the seperate images in the image file.

Using these methods on the above meshes there is no need for submaterials or submeshes.

Texture Atlas

A texture atlas also know as a sprite sheet or sprite atlas contains a range of images as in the example below.

Sprite Altlas

In this atlas there are 24 different images in a 4 rows of 6 a way of mapping each sprite onto an individual face is needed.

This map will just follow the way texture images are mapped onto a mesh usually.

The U coordinate goes horizontally left to right from 0 to 1.

The V coordinate goes vertically bottom to top from 0 to 1.

To map part of the image the bottom left coordinates and top right coordinates are used.

As there are six sprites in a row and four in a column divide the image into a grid and mark the axes as below

Sprite Atlas with Grid

Consider the sprite in the grid space marked with a *, this has bottom left coordinates of (2/6, 1/4) and top right coordinates of (3/6, 2/4). Counting the columns as 0, 1, 2, 3, 4, 5 and the rows as 0, 1, 2, 3 it is in column 2 and row 1.

Bottom left is (2 1/6, 1 1/4) and top right is ((2 + 1) 1/6, (1 + 1) 1/4)

In general for this texture atlas a sprite in column c and row r will have coordinates bottom left (c 1/6, r 1/4) and top right ((c + 1) 1/6, (r + 1) 1/4).

With faces of the mesh numbered from 0 when you want to map face f to the sprite at grid (c, r) take an array faceUV and put

faceUV[f] = (c * 1/6, r * 1/4, (c + 1) * 1/6, (r + 1) * 1/4);

To pass which texture atlas is to be assigned to the mesh a texture material is formed as usual.

var mat = new BABYLON.StandardMaterial("mat", scene);
var texture = new BABYLON.Texture("URL of Texture Atlas", scene);
mat.diffuseTexture = texture;

mesh.material = mat;

Colors

To apply a color to a face f just use an array faceColors and assign a color.

faceColors[f] = new BABYLON.Color4(r,g,b,a);

For colors only no material is needed.

These colors are BJS Color4-class values. The Color4 alpha values become active if we set hasVertexAlpha = true :

Combine Colors and Textures

You can even combine the vertex colors with a colored material.

faceUV[f] = (c * 1/6, r * 1/4, (c + 1) * 1/6, (r + 1) * 1/4);
faceColors[f] = new BABYLON.Color4(r,g,b,a);

How To Apply faceUV and faceColors - Examples

A box is used as an example of how to use the full scope of this feature and at least one example is provided for each of the other meshes that can use faceUV and facecolors

Box - faceUV

A box has six faces so only the bottom row, row 0, of the texture atlas above is used on the box in these examples.

To map sprites 0 to 5 onto faces 0 to 5 it is sufficient for the face number to match the column number and to set the row number to 0.

  var columns =  6;  // 6 columns
  var rows =  4;  // 4 rows

  var faceUV = new Array(6);

  for (var i = 0; i < 6; i++) {
    faceUV[i] = new BABYLON.Vector4(i/columns, 0, (i+1)/columns, 1/rows);
  }

Then this array is passed to the faceUV option to be used in the MeshBuilder.CreateBox() method along with any options for the size of the box and the material formed with the given texture atlas.


var options = {
   width: 10,
   height: 3,
   depth: 5,
   faceUV: faceUV
};

var box = BABYLON.MeshBuilder.CreateBox('box', options, scene);

var mat = new BABYLON.StandardMaterial("mat", scene);
var texture = new BABYLON.Texture("URL of Texture Atlas", scene);
mat.diffuseTexture = texture;
box.material = mat;

Playground Example Different Sprite on Each Face of Box -


You do not have to map all the faces. When you just want one face with an image then just map that one face.

Take the alien sprite on row 0 and column 3 and just map this sprite to face 1.

  var columns =  6;  // 6 columns
  var rows =  4;  // 4 rows

  var faceUV = new Array(6);

  faceUV[1] = new BABYLON.Vector4(3/columns, 0, (3+1)/columns, 1/rows);

Playground Example One Sprite One Face -


As you view this box from different angles you will notice that the whole texture atlas is applied to all the other faces, that is the default value (0, 0, 1, 1) is applied to the other faces. When you want to display just the one sprite on the one face and leave the others blank then you need to set all the other faceUV values to (0, 0, 0, 0).

  var columns =  6;  // 6 columns
  var rows =  4;  // 4 rows

  var faceUV = new Array(6);

  //set all values to zero
  for (var i = 0; i < 6; i++) {
    faceUV[i] = new BABYLON.Vector4(0, 0, 0, 0);
  }

  //overwrite wanted face with sprite coordinates
  faceUV[1] = new BABYLON.Vector4(3/columns, 0, (3+1)/columns, 1/rows);

Playground Example One Sprite One Face other Faces Blank -


Of course you can do this with one, two, three, four, or five the box faces.

Want add some all over color to the box then just add in adiffuseColor to your material.

Playground Example Individual Face with Colored Box -


You can also use one texture atlas to apply two different images from the same altlas onto two different meshes.

Playground Example Two Meshes Two Images -


Looking closer at the face images around the sides you will see some images are at 90 degrees to others. Unfortunately should you want to have all images around the side to have the same orientation this is not possible by only adjusting UV coordinates. What can be done by swapping coordinates is considered next, followed by a method using an adjustment to the texture atlas to orientate images on the sides.

How To Orientate a Sprite on a Face with faceUV

Because of how UV coorinates are interpreted it is possible to reflect a sprite horizontally, vertically or both (which is the ame as an 180 degree rotation). Any other rotation has to be dealt with by rotating the sprite within the texture atlas.

Consider the alien with bottom left and top right coordinates for UV as shown.

alien sprite

To set this to face one in its current orientation you would use

faceUV[1] = new BABYLON.Vector4(Ubottom_left, Vbottom_left, Utop_right, Vtop_right);

To reflect in a vertical line swap the horizontal, U, coordinates.

faceUV[1] = new BABYLON.Vector4(Utop_right, Vbottom_left, Ubottom_left, Vtop_right);

To reflect in a horizontal line swap the vertical, V, coordinates.

faceUV[1] = new BABYLON.Vector4(Ubottom_left, Vtop_right, Utop_right, Vbottom_left);

To reflect in both horizontal and vertical lanes swap the U coordinates and also swap the V coordinates.

faceUV = new BABYLON.Vector4(Utop_right, Vtop_right, Ubottom_left, Vbottom_left);

You can use the images on the other faces in the following playground to check the change on orientation of the alien sprite in all the reflections.

Playground Example Reflecting One Face Sprite -


Since a Vector4 has the properties x, y, z, w, (in that order) setting

faceUV[1] = new BABYLON.Vector4(Ubottom_left, Vbottom_left, Utop_right, Vtop_right);

means

faceUV[1].x = Ubottom_left;
faceUV[1].y = Vbottom_left;
faceUV[1].z = Utop_right;
faceUV[1].w = Vtop_right;

which gives another way to swap coordinates. For example to reflect in a vertical line do

  var temp = faceUV[1].x;
  faceUV[f].x = faceUV[f].z;
  faceUV[f].z = temp;

How To Orientate a Sprite on a Face with the Texture Atlas

Here consider just the orientation of the sides as viewed in the playground below.

Take the following texture atlas

letters

and apply it to a cube to give this playground -


.

Looking at the playground tells you two things

  1. Which face is number 0, which is number 1 and so on by matching letter to number
  2. Going round the sides the orientations vary by 90 degrees.

As you saw in the previous section it is possible to doubly reflect A so it is the right way up. It is not possible to do this with C and D. To have A, B, C, and D all the same way up the texture atlas itself has to be changed.

A is rotated 180 degrees and C and D are rotated 90 degrees counter clockwise. Taking this into account change the texture atlas to

rotated letters

resulting in this playground -


.

Box - faceColors

For this no material is needed.

Define a 6 element array faceColors (6 box faces) and just set the color of the faces we want with Colors4.

  var faceColors = new Array(6);

  faceColors[4] = new BABYLON.Color4(1,0,0,1);   // red top
  faceColors[1] = new BABYLON.Color4(0,1,0,1);   // green front

Then pass this array to the MeshBuilder.CreateBox() method with the new faceColors parameter of options.

  var options = {
    width: 10,
    height: 3,
    depth: 5,
    faceColors : faceColors
  };

  var box = BABYLON.MeshBuilder.CreateBox('box', options, scene);

Playground Example Two Colored Faces -


These colors are BJS Color4-class values. The Color4 alpha values become active if you set hasVertexAlpha = true for the box.

Playground Example Transparent Colors -


Box - Mix Face Textures and Colors

Finally you can also mix per-face colors with per-face textures, and/or mix either with the material's standard colors.

Playground Example Mixed Textures and Colors -


Cylinder

A cylinder has three surfaces, the top, the bottom and the tube joining them. For the face options face 0 is the bottom, face 1 is the tube and face 2 the top.

The following texture image is split into two parts, an approximation to a top and the label. The bottom will be colored just using faceColors and so the bottom face uv coordinates will be 0, 0, 0, 0.

can label and top

The label part has width 866 pixels and height 319 pixels.

So you need to tube surface to have the same height to width ratio.

When you create a cylinder with default diameter of 1 then the rectangle wrapping around the tube surface will have a width of π.

Letting h be the height of the cylinder then to not distort the aspect ration of the image wrapped around the cyclinder keep the ratios h/π and 319/866 the same.

So make h = π * 319/866 = 1.16 to 2 decimal places.

Also note that because of how a cylinder's mesh is constructed the horizontal coordinates (U) are swapped in faceUV[1] for the wrapped around image to correct the reflection of the image.

Playground Example Cylinder Surfaces -


Extruded Polygon

An extruded polygon has three surfaces top, bottom and extruded sides, face 0 is the top, face 1 the extruded sides and face 2 the bottom.

Playground Example of Extruded Polygons for a House -


Polyhedra.

You can use a texture atlas with all the polyhedra however without very careful consideration of the nature of the texture atlas the results can be a little random looking.

Playground Example Polyhedra with Face Pictures -


Having each sprite as a texture rather than a picture makes more sense.

Playground Example Polyhedra with Face Textures -


Just colors works well.

Playground Example Polyhedra with Face Colors -