How to create the rings of Saturn using a single texture?

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By marcorexo

Hi,

I’m building a model of Saturn and need to create the ring. I’m doing this by trying to texture a plane using the this resource here.

How can I use this texture to create a ring?

This is what I have so far:

Thanks

:bust_in_silhouette: Reply From: Zylann

I dont think Godot has a built-in way to do this. It is easy to do, though.

Assuming you really want to use this texture, a first way is to create a ring in a modeling program like Blender. Then give UVs to that ring, such that the inner border uses the left of the image, and the right border uses the right of the image, while the whole ring uses the same Y coordinate.

Another way is to use a shader and some math to obtain a perfect ring. I don’t have much time to write an example unfortunately. This can be done with a quad, but a ring geometry will still perform a bit better if it matches the shape of the rings so less pixels will need to be processed.

An extra way to create the geometry is to use CSGPolygon Spin mode. By default it uses a quad, but if you lower vertices thinner you can reproduce a ring. However, I don’t know if you can make it generate the appropriate UVs, so IMO you might have more control using a 3D modeler.

There is yet another way which can cost a bit of loading time, but you can also generate the mesh from a script:

#tool
extends MeshInstance

var _segments = 64
var _inner_radius = 1
var _outer_radius = 1.5


func _ready():
	var positions = []
	var uvs = []

	for si in _segments + 1:
		var angle = TAU * float(si) / _segments
		var dir = Vector3(cos(angle), 0, sin(angle))
		var inner_pos = _inner_radius * dir
		var outer_pos = _outer_radius * dir
		positions.append(inner_pos)
		positions.append(outer_pos)
		uvs.append(Vector2(0,0.5))
		uvs.append(Vector2(1,0.5))

	var indices = []
	var quad_count = _segments
	for qi in quad_count:
		var i = qi * 2
		var i0 = i
		var i1 = i + 1
		var i2 = i + 2
		var i3 = i + 3
		indices.append(i0)
		indices.append(i1)
		indices.append(i2)
		indices.append(i2)
		indices.append(i1)
		indices.append(i3)
	
	var surface = []
	surface.resize(Mesh.ARRAY_MAX)
	surface[Mesh.ARRAY_VERTEX] = PoolVector3Array(positions)
	surface[Mesh.ARRAY_TEX_UV] = PoolVector2Array(uvs)
	surface[Mesh.ARRAY_INDEX] = PoolIntArray(indices)
	mesh = ArrayMesh.new()
	mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, surface)

Thanks Zylann for taking the time to explain - much appreciated. I’ll have to read up and digest the information. Thanks so much.

marcorexo | 2022-02-21 14:58