Hi @JerryB,

The first thing to know is that a pattern can have multiple render functions and has variants for 1D, 2D, and 3D.

You have the original `render(index)`

for 1D strips, most patterns have this method.

If a 2D map is installed, it will also look for a `render2D(index, x, y)`

exported function and use that instead.

Likewise, if a 3D map is installed, it will look for a `render3D(index, x, y, z)`

exported function. This is probably what you want, though you could also treat it as a 2D shape (like a bit of paper wrapped around in a cylinder shape).

The pixel coordinates on the Mapper tab is fed to the pattern through those x, y, and z parameters. They are scaled to “world units” so that a pattern will scale to any map, so x will range between 0 and 1.0.

To test/verify 3D patterns, I’d load up Roger’s excellent RGB-XYZ sweep pattern:

RGB-XYZ 3D Sweep.epe (8.3 KB) - keep in mind though, this ONLY has a `render3D`

so will not draw anything until you have a 3D map set up. You can load it in the editor while you adjust things on the mapper tab.

This is also available on the pattern sharing site, along with more awesome 3D capable patterns (look for 3D in the name, or a render3D function in the code).

I’m going to assume you are going 3D, using @jeff’s map from the 2nd post in this topic.

Adjust the `layers`

and `pixPerRing`

for your setup. Just like the pattern editor, the changes in the mapper are live. You should see a cylinder pop up in the preview.

You should get something like this:

If you are running the XYZ sweep pattern, you should see one color travel up the cylinder, another wash through it from the front to back, and other from left to right.

If you want something to travel around the outer circumference of each ring instead of through it, you can get the angle from the (x,y) and use that. Something like this, which will paint a gradient traveling clockwise, with a different color for each step up the cylinder:

```
function arctan2(y, x) {
if (x > 0) return atan(y/x)
if (y > 0) return PI / 2 - atan(x/y)
if (y < 0) return -PI / 2 - atan(x/y)
if (x < 0) return PI + atan(y/x)
return 1.0
}
//return the angle in radians, can be negative
function getAngleInRads(x, y) {
//center the coordinate, then get the angle
return arctan2(x - .5, y - .5)
}
//return the angle as a value between 0 and 1.0
//most of Pixelblaze's animation language uses this range
//it also happens to rotate the angle so that 0 is north
function getUnitAngle(x, y) {
return (PI + arctan2(x - .5, y - .5))/PI2
}
export function beforeRender(delta) {
t1 = time(.1)
}
export function render3D(index, x, y, z) {
//get the angle of the pixel, and move it clockwize over time
//pass that into triangle() to turn into a gradient
v = triangle(getUnitAngle(x, y) + t1)
v = v*v //square it up for contrast
h = z //each step in height should get a different color
s = 1
hsv(h, s, v)
}
//for broad compatibility, support 2D maps as well
export function render2D(index, x, y) {
render3D(index, x, y, 0)
}
```