0 votes

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

Godot version 3.4.2
in Engine by (92 points)
edited by

1 Answer

+1 vote
Best answer

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)
by (28,880 points)
edited by

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

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read Frequently asked questions and How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to [email protected] with your username.