The Smudge API is still changing pretty often. Code on this post is out of date.

Building a brick texture as the first implementation of the Smudge API was a good exploration of its potential as well as a good indication of other functions from which it would benefit.

At this stage in the API there were only two basic features: (1) the ability to describe a material with color, transparency, metallic, smoothness, and height, as well as (2) the ability to draw a rectangle.

// describing a material with PBR channels
let exampleMaterial = new Material();
exampleMaterial.red = 1.0;
exampleMaterial.green = 0.0;
exampleMaterial.blue = 0.0;
exampleMaterial.transparency = 1.0;
exampleMaterial.height = 0.5;
exampleMaterial.metallic = 0.5;
exampleMaterial.smoothness = 0.25;

// drawing a rectangle
pbr.rect(10, 10, 100, 25, exampleMaterial);

These alone were the primary functions—used along with pure javascript—that were available to build the brick texture.

The general process to set up the grid was as follows:

  1. Define the dimensions of each brick and the mortar between them as variables, so they can be changed later.
  2. Loop through the canvas, and draw each brick using pbr.rect(). Every other row I subtracted half the width of a brick from the x-start, alternating the grid and giving it more of an organic brick “feel”.

In the first version of this sketch only two parts are being drawn: the canvas below the bricks (the mortar), and a base rectangle for each brick. This version uses two materials. The canvas/mortar material (1) was initially given a grey-ish color, and a height of 0.1. The bricks material (2) was also a simple color and height, but the loop gave the opportunity to randomly diversify the color of each brick.

Albedo Channel: Simple Brick Texture, showing grid and varying colors.

This brick texture is a good base, but needs some more detail and variety to be interesting. Observing the details of actual bricks, I took note of a few qualities to recreate: color alteration within each brick, speckles on some, edge “noise” (bricks aren’t usually perfect rectangles), surface flaws (randomized indents, roughness, etc).

For the first stab at making the brick details, I drew several randomly placed semi-transparent small rectangles over each brick base (each one a relative of the brick base color). The result was a watercolory blend of colors on each brick. I added speckles by a similar process, with a simple all-white semi-transparent material, applied randomly over each brick as 1x1 rects.

Misstep 1: Complex brick texture, erroneous heights.

This iteration had an issue: the mortar’s height was higher than the brick’s, even though the brick base material defined a higher height than the mortar’s. (shown below in “Misstep 1”).

The initial, correct height of the bricks was overwritten when the overlaid details were drawn. The embossing around the edges was the brick base height peaking out wherever a brick overlay was not drawn. The overlays were intended to change the only color of the brick, but they were drawing to the height channel as well. To fix this, I had to make sure that the overlay details were drawn with the same height as the brick below.

For this example, it was possible to match the height of the overlays to the height of the bricks, but similar solutions won’t always be possible. It would be better to just skip drawing to the height channel altogether. We plan on adding per-channel blending controls to allow just this.

Drawing the brick overlay details with the same height as the brick base fixed one issue, but caused the second misstep: the render lost its organic edge noise. Each brick—although now appropriately protruding from the mortar—was perfectly rectangular, which is unwanted for a realistic brick texture.

I came across the solution accidentally. I temporarily commented out the brick base, and bingo! organic, brick-ish shapes beautified the canvas. In retrospect, the solution was to not draw the brick base at all, and only draw the brick overlays at the same height that each brick would be (perhaps with some variation). This ensured a nice rough border variation for each brick.

Height Channel, Misstep 1: Height of "Bricks Overlay" as 0;
Height Channel, Misstep 2: Improved mortar-to-brick height relation, but lost edge roughness;
Height Channel, Solution: "Bricks Base" not drawn; "bricks overlay" assigned height and drawn above mortar height; achieves edge roughness as well as correct height.

Considering the final version is built with just two basic library functions, I am impressed with the likeness of the end-result. The library already shows great potential.

A few functions that would be useful for the future, as a reflection of some of the struggles as well as epiphanies of building the brick wall:

  1. If there were some sort of “mask,” it would have saved a lot of time calculating the areas on the canvas on which a brick was being drawn, so that some other details could be overlaid in the right place. Not only this, but a mask would allow for more complex shapes in the future.

  2. In addition to the option to make materials, perhaps a library of pre-sketched textures would be useful to a user, assuming he/she gets control over some parameters. As an example, the “speckles” function was called several times over with slight modifications each time. Perhaps something like the speckles function, as well as the multicolor overlay that went over each brick, could become more universal.

  3. In response to the misstep resulting in “negative bricks”: perhaps there is a solution to deactivate some of the channels within each material (as an example: material.height = undefined). Either this, or to automatically build on top of a previous material without having to replicate its parameters.