Applying a texture to a RingGeometry

Hello, I’m building a representation of Saturn’s rings in THREE.js using a RingGeometry. I have a texture that is 2048x1, with each pixel representing the color of Saturn’s rings at a given radius.

As expected, it is not enough to simply apply this texture to the RingGeometry:

I don’t know too much about graphics but I understand I need to adjust the UVs. I found a similar example and attempted to do this in the Codepen but did not have success.

Am I on the right track? Is there a better way to adjust the texture?

Intended result looks like this:

Codepen here:

THREE.RingGeometry already comes with the UVs pre-set in a “billboard” fashion. I guess you could change the way they’re mapped to all be [0, y] on the inside vertices, and [1, y] on the outside vertices. However, it would be much faster and simpler to just change your texture to be a ring with Photoshop’s Polar Coordinates filter:

1 Like

Not so difficult to re-calculate UVs (like @marquizzo said) , having a buffer geometry:

const geometry = new THREE.RingBufferGeometry(3, 5, 64);
var pos = geometry.attributes.position;
var v3 = new THREE.Vector3();
for (let i = 0; i < pos.count; i++){
    v3.fromBufferAttribute(pos, i);
    geometry.attributes.uv.setXY(i, v3.length() < 4 ? 0 : 1, 1);

Thanks to both of you for the tips.

While you were replying, I was also able to get it working via ShaderMaterial (codepen).

@prisoner849 yours looks much better… so maybe there is something wrong with my coloration somehow.

In my visualization, I may wind up using a ShaderMaterial anyway for other reasons. Is one approach better than the other?

Add this to your THREE.ShaderMaterial():

transparent: true

to get the same result when you use THREE.MeshBasicMaterial()

Thanks so much! I appreciate your help on this.

@ianw You’re welcome :slight_smile: :beers:

One more follow-up question for the BufferGeometry approach. Is there anything I must do to make the geometry cast and receive shadows?

I updated your Codepen with a light and am noticing the ring doesn’t cast or receive shadows on a sphere.

Using the ShaderMaterial approach, I was successful in writing a custom shader that applies shadows (Codepen here).

Because meshes are treated as solid from the point of view of the light, I realized I would need a customDepthMaterial on the ring mesh in order for it to cast striped shadows on the sphere.

Wondering what’s easier - fixing shadows + custom depth material using THREE.js-supplied materials or doing it on my own in custom shaders.

From the MeshBasicMaterial docs: “This material is not affected by lights”.

Try using Lambert, Phong, or MeshStandardMaterial instead. Also, using THREE.DoubleSide might give you bad shadow artifacts because one face is affected by the light, but the opposite face is in its shadow. You might need to create two ring planes that are separated by a tiny bit of space.

1 Like

Oops, that was a mistake on my part. Thank you!