I’m a godot beginner, but I’ve been working on a similar problem. You’re on the right track, I think, a cubemap will decrease the polar distortion from a projection to a sphere compared to the traditional equirectangular panorama, as it “pinches” at the corners but much less dramatically, and lends itself to a nice distant view. (One drawback is your pixels are essentially distorted across the whole sphere, pinched at the corners and stretched in the middle of the faces). The projection you’re doing onto the sphere is correctly applied, however the way that equirectangular projections work, is they tend to have pinching or distortion at the poles when mapped to a sphere.
I would recommend creating your cubemap texture offline rather than trying to map the equirectangular texture to a cubemap in realtime. This website will turn a panorama into six individual cubemap faces to easily test it out: Panorama to Cubemap
To display them in godot, you’ll need to arrange them correctly in a texture. The default 2x3 is a good balance for the overall texture sizes: Cubemap — Godot Engine (4.4) documentation in English
The filenames from the above tool correspond to where in the godot template you’ll need to stitch them: px is X+, ny is Y-, etc. I ended up writing a python script to do the projection (using numpy) and stitch them together into a texture. I haven’t used that spaceengine tool but it seems like a great way to automate the math behind it!
Lastly, to show them on your sphere you’ll need a shadermaterial to sample the cubemap, since you can’t just apply the cubemap directly to a standard material. Here’s a basic one that applies either a cubemap or a color (for planets or moons I don’t have a cubemap for).
shader_type spatial;
uniform samplerCube albedo_texture;
uniform bool has_albedo_cubemap = false;
uniform vec3 albedo_color = vec3(1.0);
varying vec3 direction_from_center;
void vertex() {
direction_from_center = normalize(VERTEX);
}
void fragment() {
vec3 calculated_albedo_color;
if (has_albedo_cubemap) {
vec3 albedo_color_cubemap = texture(albedo_texture, direction_from_center).rgb;
calculated_albedo_color = albedo_color_cubemap.rgb;
} else {
calculated_albedo_color = albedo_color;
}
// Apply the final color.
METALLIC = 0.0;
ROUGHNESS = 1.0; // tweak roughness how you would like for your particular planet
ALBEDO = calculated_albedo_color;
}
You’ll need to pass in the cubemap into the shader with set_shader_parameter, eg:
var cubemap = load(planet_data.mat_albedo_path)
planet_material.set_shader_parameter("albedo_cubemap_texture", cubemap)
planet_material.set_shader_parameter("has_albedo_cubemap", true)
And here’s the cubemap I used, converted from NASA’s blue marble equirectangular projections (note the rotation on the Y faces)
You could also use individual face textures, and load the higher detail ones as the camera got closer to a face, for example, to maximize the amount of detail for each loaded texture. If you used a “cube sphere” model rather than the standard godot sphere, you could use quadtrees to subdivide the mesh as the camera gets closer and even show DEM/elevation data in the vertices. (A cube sphere is essentially a cube mesh where the vertices are normalized to the sphere’s radius, which adds some distortion). Good luck! Hope this helps.