Map an image to have coordinates to get access of the image

Hi!

I want to show this image in a sphere, like a sky dome:

I want to show the part of the milky way that it is visible at this moment. You know that you can see different parts of the milky way depending on the month we are.

Is there a way to map the image, applied to a static mesh, to rotate it?

If I could have a reference to the hole of image, or a part of it. I could rotate it and show the visible part of it depending of the month the player is.

Sorry, but I don’t know how to explain it better. Basically is have a reference inside the image to know how much I have to rotate it. My problem is that I don’t know how to have that reference.

Thanks!

This is polar coordinates mapping, and this is HDRI texture. So make sure you import it as HDRI.
You can also google for free HDRI textures, there is nice website with ton of those.

Now solutions:

  • get (i think) any template from architectural visualisation
  • they all have hdri blueprint for skybox.
  • migrate that skybox blueprint into your project and change texture for one you want

Or.
-get that project from template and just recreate skybox material

However i am not sure if that material uses polar coordinates.

This is how you use reflection vector on skybox image, if you use this you do not need UVs on skybox sphere. And this reflection vector method uses polar coordinates just like texture you have:

For rotating this image, you need to rotate that camera vector before using Transform vector (or maybe after) :smiley:

And to know how you rotate. Hmm You kind of need to calculate UP vector on earth in place where is your camera/player at time. then rotate camera vector in material to match that earth vector. You can calculate earth up vector in blueprints, then pass it as parameter into material.

Follow up:

I am lazy so i asked my yellow rubber duck (chatgpt). And here is its answer, and because it is deep AI, check everything below (sometimes it makes silly mistakes that look like THE truth):

  1. Compute Up Vector (Zenith)

Given latitude (ϕϕ) and longitude (λλ), the up vector in ECEF (Earth-Centered, Earth-Fixed) coordinates is:
UpVector=(cos⁡(ϕ)cos⁡(λ),cos⁡(ϕ)sin⁡(λ),sin⁡(ϕ))
UpVector=(cos(ϕ)cos(λ),cos(ϕ)sin(λ),sin(ϕ))

Where:

ϕϕ = Latitude in radians.
λλ = Longitude in radians.
  1. Compute Local Sidereal Time (LST) for Correct Skybox Rotation

To align the skybox properly with the stars, we need Local Sidereal Time (LST).
Step 1: Compute Julian Date (JD)

First, convert UTC date and time to Julian Date (JD) using:
JD=367Y−⌊7(Y+⌊M+912⌋)4⌋+⌊275M9⌋+D+1721013.5+UT24
JD=367Y−⌊47(Y+⌊12M+9​⌋)​⌋+⌊9275M​⌋+D+1721013.5+24UT​

Where:

Y,M,DY,M,D = Year, month, and day.
UTUT = Universal Time (hours, fraction included).
Example: If it's February 3, 2025, at 12:00 UTC, calculate JD for that timestamp.

Step 2: Compute Greenwich Mean Sidereal Time (GMST)
GMST=280.46061837+360.98564736629(JD−2451545)
GMST=280.46061837+360.98564736629(JD−2451545)

This gives the GMST in degrees.

Step 3: Convert GMST to Local Sidereal Time (LST)
LST=GMST+λ
LST=GMST+λ

λλ is longitude in degrees (positive east, negative west).
  1. Compute Skybox Rotation

    The HDRI skybox rotation (Yaw) should match LST in degrees.
    Convert to radians if needed:

Yaw=LSTmod 360
Yaw=LSTmod360

The up vector gives the correct tilt, and the LST gives the proper skybox rotation.

Final Steps in UE5

Up Vector: Controls the HDRI tilt.
Yaw (LST): Controls the HDRI rotation.
Use SetActorRotation on the skybox.

This should correctly align your HDRI skybox to time and location on Earth. :rocket:

ps.
Use this reply from out future overlords as guide, you have all keywords, and algorithm how to calculate it. So use google for more reliable articles.

And pps:
I already found derp mistake in last step: do not use set actor rotation for the skybox, instead rotate camera vector in material just like i posted in previous reply.

and C++ (Again deep ai reply):

  1. Compute Julian Date (JD)
double GetJulianDate(int Year, int Month, int Day, double UT_Hours) {
    return 367 * Year 
        - floor((7 * (Year + floor((Month + 9) / 12.0))) / 4.0) 
        + floor((275 * Month) / 9.0) 
        + Day + 1721013.5 
        + (UT_Hours / 24.0);
}
  1. Compute Greenwich Mean Sidereal Time (GMST)
double GetGMST(double JulianDate) {
    return fmod(280.46061837 + 360.98564736629 * (JulianDate - 2451545.0), 360.0);
}
  1. Compute Local Sidereal Time (LST)
double GetLST(double GMST, double LongitudeDegrees) {
    return fmod(GMST + LongitudeDegrees, 360.0);
}
  1. Compute Up Vector (ECEF Zenith)
FVector GetUpVector(double LatitudeDegrees, double LongitudeDegrees) {
    double LatRad = FMath::DegreesToRadians(LatitudeDegrees);
    double LonRad = FMath::DegreesToRadians(LongitudeDegrees);

    return FVector(
        cos(LatRad) * cos(LonRad),  // X
        cos(LatRad) * sin(LonRad),  // Y
        sin(LatRad)                 // Z
    );
}
  1. Compute HDRI Rotation (Final Function)

This function calculates the up vector at a specific location and time.

FVector GetUpVectorAtTimeAndLocation(int Year, int Month, int Day, double UT_Hours, double Latitude, double Longitude) {
    // Step 1: Compute Julian Date
    double JD = GetJulianDate(Year, Month, Day, UT_Hours);

    // Step 2: Compute GMST
    double GMST = GetGMST(JD);

    // Step 3: Compute Local Sidereal Time
    double LST = GetLST(GMST, Longitude);

    // Step 4: Get Up Vector
    FVector UpVector = GetUpVector(Latitude, Longitude);

    return UpVector;
}

Usage Example

FVector SkyUpVector = GetUpVectorAtTimeAndLocation(2025, 2, 3, 12.0, 40.0, -74.0); // New York, UTC 12:00

This gives you the correct up vector, which you can then use to rotate the HDRI skybox in Unreal Engine 5.

ps.
Again i did not tested this code yet, not even looked at it. It is too early and i need my coffee now. This is product of me waiting for it to brew. :wink:

pps.
Waking up, and i just had idea.
Instead of making this code in C++ or bluepritns, make this code in custom material shader. Those are simple float calculations. You can code that in HLSL (shader language) and have whole math as material node.

@Nawrot

Wow!

Thank you very much for all of your answers!

I have to read them carefully. By the way, the images are in OpenEXR format. I don’t know if this format could store information interesting to use it here. You can find the images here: NASA SVS | Deep Star Maps 2020.

Don’t worry about all the astronomical calculations. I’ve already done them using a book and C++.

I’ll come back later when I find how to do it.

Thanks!

Great, so all you need to do is find how to rotate CAMERA Vector To match local up vector on surface of earth. And add it in that reflection vector part of material.

As to extracting info from OpenExR format i think you need to code it in C++. But then creating own importer is probably qquite complicated, and anything less is basically adding that info manually.

Edit:
I just found this great tut about some nice material tricks (like rotating mesh inside material shader, and not blueprints). Which is great for this sky sphere problem.

1 Like

I have a lot of questions:

  1. How do you know that the texture I have has polar coordinates?

  2. Where did you get that Blueprint code from, is it from a template?

  3. I have tried several templates and I can’t find a template with a blueprint for skybox. I have only find it a material:

  4. How can I know if a material uses polar coordinates? Polar coordinate system - Wikipedia

Thanks!

1: Texture has polar coordinates, if you see horizon line form something that looks like sinus function (wave), not all HDRI textures use polar coordinates (so you need different reflection calculations for projecting them on sky). On that NASA page with sky textures, “milky way” texture uses polar coordinates.

2: that blueprint is in most architectural visualization templates, its called light studio i think. Howevr just now (while looking for tut i seen) I found that there is HDRI backdrop plugin for unreal now.

  1. I think first material pic i posted here requires polar coordinates texture (it is how that reflection vector will work). And you need skybox/spehere mesh to apply material to it, and material does not use UVS of that mesh, reflection vector calculation maps it instead.
1 Like