Tiling / repeating shader image texture

Hi, I’m new to p5.js and I’ve just ported a shader from shadertoy. It works fine, however, the image that I’m using as a texture is defaulting to CLAMP when I want it to REPEAT.

I’ve tried to use textureWrap(REPEAT) as per the documentation but I get the error message sketch.js:11 Uncaught ReferenceError: textureWrap is not defined.

sketch.js code:

let theShader;
let tex;

function preload() {
  theShader = loadShader("shader.vert", "shader.frag");
  tex = loadImage("texture.jpg");
}

function setup() {
  createCanvas(windowWidth, windowHeight, WEBGL);
  textureWrap(REPEAT);
  noStroke();
}

function draw() {
  shader(theShader);
  theShader.setUniform("iResolution", [width, height]);
  theShader.setUniform("iTime", frameCount * 0.01);
  theShader.setUniform("iMouse", [mouseX, map(mouseY, 0, height, height, 0)]);
  theShader.setUniform("iChannel0", tex);

  rect(0, 0, width, height);
}

function windowResized() {
  resizeCanvas(windowWidth, windowHeight);
}

shader.frag:

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 iResolution;
uniform float iTime;
uniform sampler2D iChannel0;
uniform vec4 iMouse;

// Maximum number of cells a ripple can cross.
#define MAX_RADIUS 2

// Set to 1 to hash twice. Slower, but less patterns.
#define DOUBLE_HASH 0

// Hash functions shamefully stolen from:
// https://www.shadertoy.com/view/4djSRW
#define HASHSCALE1.1031
#define HASHSCALE3 vec3(.1031,.1030,.0973)

float hash12(vec2 p)
{
  vec3 p3=fract(vec3(p.xyx)*HASHSCALE1);
  p3+=dot(p3,p3.yzx+19.19);
  return fract((p3.x+p3.y)*p3.z);
}

vec2 hash22(vec2 p)
{
  vec3 p3=fract(vec3(p.xyx)*HASHSCALE3);
  p3+=dot(p3,p3.yzx+19.19);
  return fract((p3.xx+p3.yz)*p3.zy);
  
}

void main()
{
  float resolution=10.*exp2(-3.*iMouse.x/iResolution.x);
  vec2 uv=gl_FragCoord.xy/iResolution.y*resolution;
  vec2 p0=floor(uv);
  
  vec2 circles=vec2(0.);
  for(int j=-MAX_RADIUS;j<=MAX_RADIUS;++j)
  {
    for(int i=-MAX_RADIUS;i<=MAX_RADIUS;++i)
    {
      vec2 pi=p0+vec2(i,j);
      #if DOUBLE_HASH
      vec2 hsh=hash22(pi);
      #else
      vec2 hsh=pi;
      #endif
      vec2 p=pi+hash22(hsh);
      
      float t=fract(.3*iTime+hash12(hsh));
      vec2 v=p-uv;
      float d=length(v)-(float(MAX_RADIUS)+1.)*t;
      
      float h=1e-3;
      float d1=d-h;
      float d2=d+h;
      float p1=sin(31.*d1)*smoothstep(-.6,-.3,d1)*smoothstep(0.,-.3,d1);
      float p2=sin(31.*d2)*smoothstep(-.6,-.3,d2)*smoothstep(0.,-.3,d2);
      circles+=.5*normalize(v)*((p2-p1)/(2.*h)*(1.-t)*(1.-t));
    }
  }
  circles/=float((MAX_RADIUS*2+1)*(MAX_RADIUS*2+1));
  
  float intensity=mix(.01,.15,smoothstep(.1,.6,abs(fract(.05*iTime+.5)*2.-1.)));
  vec3 n=vec3(circles,sqrt(1.-dot(circles,circles)));
  vec3 color=texture2D(iChannel0,uv/resolution-intensity*n.xy).rgb+5.*pow(clamp(dot(n,normalize(vec3(1.,.7,.5))),0.,1.),6.);
  gl_FragColor=vec4(color,1.);
}

If anyone can help I would very grateful as I’ve been trying to solve this issue for a while with no success.

Many thanks,

Andy

1 Like

Given textureWrap() exists & it’s working on its online reference:
p5js.org/reference/#/p5/textureWrap

Most likely you’re using some old p5.js version. Get latest 1 like this:
<script defer src=https://cdn.JsDelivr.net/npm/p5></script>

3 Likes

Thank you, that did the trick!