Procedural Texturing
Exercise Adapt other patterns from the book of shaders (refer also to the shadertoy collection) and map them as textures onto other 3D shapes.

Introduction #

The goal in procedural texturing is to procedurally generate a texture using an algorithm in such a way that the result can be mapped onto a shape as a texture. Procedural texturing requires the use of a frame buffer object which in p5.js is implemented as a p5.Graphics object.

Note

All the code developed in this section is based on Great book of shaders. Patricio Gonzales and Jen Lowe. Their work made possible a better understanding about thsi subject.

Previous Work #

Apparently procedural texturing is widely used to generate surface textures, given its low space and time cost. Here we can see a texture of roughness being applied to a sphere, roughness being one of the most straightforward, procedural texture

Roughness procedural texture

We can see other textures being applied such as Leather, Wood or Marble

nTop. How to create procedural textures for design and engineering

Offset patterns #

What we want to draw here are several rows of a given shape(in this case bricks), and every other row will have a offset in the X axis giving this view:

Wall

Great book of shaders. Patricio Gonzales and Jen Lowe. https://thebookofshaders.com/09/

Then we will map this pattern into a 3D shape, in this case we chose a cone

Implementation #

Solution #

Here we are creating the brick pattern, it is made calculating what row are we into, thhis determines how offset the bricks will be. Odd rows will have 0.5 unit offset.

vec2 brickTile(vec2 _st, float _zoom){
    _st *= _zoom;

    // Here is where the offset is happening
    _st.x += step(1., mod(_st.y,2.0)) * 0.5;

    return fract(_st);
}

Code #

Code
let pg;
let truchetShader;

function preload() {
  // shader adapted from here: https://thebookofshaders.com/09/
  truchetShader = readShader('offset.frag');
}

function setup() {
  createCanvas(400, 400, WEBGL);
  // create frame buffer object to render the procedural texture
  pg = createGraphics(400, 400, WEBGL);
  textureMode(NORMAL);
  noStroke();
  pg.noStroke();
  pg.textureMode(NORMAL);
  // use truchetShader to render onto pg
  pg.shader(truchetShader);
  // emitResolution, see:
  // https://github.com/VisualComputing/p5.treegl#macros
  pg.emitResolution(truchetShader);
  // https://p5js.org/reference/#/p5.Shader/setUniform
  truchetShader.setUniform('u_zoom', 3);
  // pg NDC quad (i.e., x, y and z vertex coordinates ∈ [-1..1])
  pg.quad(-1, -1, 1, -1, 1, 1, -1, 1);
  // set pg as texture
  texture(pg);
}

function draw() {
  background(33);
  orbitControl();
  cone(100, 200);
}

function mouseMoved() {
  // https://p5js.org/reference/#/p5.Shader/setUniform
  truchetShader.setUniform('u_zoom', int(map(mouseX, 0, width, 1, 30)));
  // pg NDC quad (i.e., x, y and z vertex coordinates ∈ [-1..1])
  pg.quad(-1, -1, 1, -1, 1, 1, -1, 1);
}

Conclusions #

Procedural texturing is a very powerful way to create textures we want to recreate in our animations, it allows to create a nice level of detail through a generally light algorithmic process. That would probably take a lot more under other circumstances

References #