2
\$\begingroup\$

I'm making a game with OpenGL and would like to add dynamic sky colors with gradients. However, I don't know how to achieve this. Here's an example (in Minecraft) of what I would like to have:

Example

In this screenshot, we can see the blue sky gets gradually more orange-ish the closer it is to the sun.

My first idea to achieve this was to use a skybox and calculate the color of each pixel according to its position relative to the sun/moon. But I don't have any clues on how I could do the math for this, and I don't think this is the most optimal way to achieve a sky gradient.

I searched for similar questions but found nothing helpful. All the results I got were about Atmospheric Scattering, which is not really what I want (if my understanding of AS is correct).

So here's my questions: How can I implement a dynamic sky with color gradients related to the sun and moon position in OpenGL, like in the screenshot above?

\$\endgroup\$

2 Answers 2

1
\$\begingroup\$

You are going to need the (unit) direction vector for the point in the sky you need to shade.

Assuming the sky has no actual geometry, and it is supposed to have infinite size, then you get the direction from the camera and the fragment coordinates.

On the other hand, if the sky has actual geometry, position and size in the world, you can give it a texture that encodes the direction, so you can query it when shading.


Then, you need a (unit) direction vector for the pole of the gradient (e.g. the sun position), which I'm going to guess you can compute (e.g. form time of the day).

With those two vectors, you can get their dot product. The dot product of the vectors (assuming they are unit vectors) is the cosine of the angle between them. If you rather with with angles, you can go ahead an compute the inverse of the cosine (acos).

For dynamic orientation, it is a matter of updating the direction vector for the pole.

And for the color, you would take the angle (or dot product) as input for a function that picks the color.

And yes, you could have multiple poles, get the angle (or dot product) to their directions, and use them as arguments for the function that computes the color.


I guess from there it is optimization. For example, one idea is to use a 1D texture to lookup the angle instead of doing acos... In fact, if you are going to have 1D texture to lookup with the dot product, you might instead have a 1D texture with to lookup the colors directly, and that way you don't need a function for that either.

And, if you need extra arguments you could make it a 2D texture, or even a 3D texture (where the components to query the texture in the extra dimensions are your extra arguments).

\$\endgroup\$
4
  • \$\begingroup\$ Thanks a lot for your answer! I don't have access to my computer for the moment, but I'll make sure to mark your answer as accepted once I get to implement it! \$\endgroup\$
    – Vincent
    Jul 28, 2023 at 18:38
  • \$\begingroup\$ Hey, I'm currently implementing it but I don't understand what you mean with the first vector. I indeed assume the sky has no geometry. Does that mean the vector is from the origin to the point in world space? Or is it the vector from the camera position to the fragment coordinates? And how could I compute that? Thanks in advance! (PS: I implemented the rest of the algorithm already, I just have issues with the first vector.) \$\endgroup\$
    – Vincent
    Aug 7, 2023 at 23:02
  • 1
    \$\begingroup\$ @Vincent If you have the fragment coordinates, and knowing their range of values, you can take that as a position in the near plane, you want the direction from the camera to that position. I hope that makes sense. You might look at the setup for ray marching for how to get the ray direction (before even getting to the marching), it is the same idea. Addendum: if you output as color the x and y components of the direction in camera space (so without considering the rotation of the camera) it should be this: i.stack.imgur.com/dFyd2.png \$\endgroup\$
    – Theraot
    Aug 8, 2023 at 4:42
  • \$\begingroup\$ Thank you so much for your answer! I got it working now! The screenshot in your addendum was very helpful as I could compare with my result, and I got the exact same thing. \$\endgroup\$
    – Vincent
    Aug 8, 2023 at 13:27
1
\$\begingroup\$

The Skydome enables you to create the gradient effect and you can combine it with a texture. The Skydome is created using half of a sphere which is placed at the location of the camera so that the viewer is always in the center of it. The sphere itself can be created programmatically or offline using a tool like Blender. If the radius of the sphere is 1 you can simply forward the local space Y coordinate to the fragment shader and use it to interpolate between two color and achieve the gradient effect. I've recently published a video about this technique: https://youtu.be/I0jI_d1jORc.

\$\endgroup\$
2
  • \$\begingroup\$ This is currently a link-only answer. If the YouTube video ever goes offline, changes URLs, or if YouTube is blocked from a reader's location, then readers will not be able to apply the advice you're offering. Please edit this answer to at least briefly summarize the main points you hope a reader would glean from this video, so that the information is preserved even if the video itself is unavailable. \$\endgroup\$
    – DMGregory
    Aug 12, 2023 at 0:26
  • 1
    \$\begingroup\$ I've seen skydomes were a thing too, but I didn't know we could do gradient with it. Thanks for the answer! I might actually use a skydome to make a starry sky. Also, nice video! \$\endgroup\$
    – Vincent
    Aug 16, 2023 at 14:37

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .