I'm trying to make moon with a cubemap texture in shadergraph.

I made it, but the texture is incorrect.

I'm using a cubemap from NASA as a texture and it works, but it's bigger than moon shape and thee larger I make the radius, the more of the texture appears.

I want to fit the cubemap within the moon shape.

Shader graph: Shadergraph

Rendered result

the texture is bigger than moon shape


1 Answer 1


The problem with this shader graph is that you're sampling the moon's surface cubemap with your view direction vector (the green vector on the left). What you want is the red vector on the right.

Triangle diagram

We can get that vector with a little trigonometry. I'll spare you the full derivation and just jump straight to the shader graph code that implements it:

Graph overview

In this first section, we transform the view vector into a coordinate space where z+ is the "to moon" direction. (You can rotate the mesh this shader is being rendered on to change where the moon sits in the sky, or replace this with your own preferred coordinate transformation)

We then break down that vector into components that get us the trig ratios we need for angle \$a\$ in the diagram above, and use that to get some trig ratios for angle \$c\$.

Initial ratios

Then we do some math on those to get the tangent ratio of angle \$b\$, and use that to construct a vector in the moon surface direction. That's the vector we'll use to sample the moon cubemap. You can also normalize it to get a surface normal vector for lighting calculations, like rendering the phases of the moon.

(By default, this setup will give you a moon that's tidally locked: the same side always points toward the viewer. If you don't want this, you can rotate the moon surface direction vector before passing it to the Sample Cubemap node)

Moon surface sampling

Of course, all this math is only valid for view rays that actually hit the moon. For pixels outside that narrow cone, we want to skip as much of that calculation as we can and just draw stars, then do a light feathered blend between the two. Here are the nodes that do that:


As you can see, this lets you control the size of the moon in the sky, and the moon's features scale with the moon - when the moon gets smaller, it doesn't crop the surface texture, it shrinks the whole thing together.

Moon scaling

  • \$\begingroup\$ Yes, you are right. I applied wrongly and corrected it, but I noticed a difference in the scale of the moon I use moon radius= minimum 0 and maximum 2.5 and you used distance so how can I control the scale with radius? \$\endgroup\$
    – user171926
    Commented Aug 9, 2023 at 15:10
  • \$\begingroup\$ You can replace the node that multiplies Sine(a) by MoonDistance with a node that divides Sine(a) by MoonRadius. The floating point division is slightly more expensive than the multiplication, so that's why I chose to parametrize this shader in terms of distance instead, but it's a trivial change if you prefer to tune it in terms of radius. The radius units will then be measured in orbital radii. If you know the angular radius you want, you can take the tangent ratio of that angle and use it as the radius parameter. (You can do that tan() in the shader, but again, more expensive). \$\endgroup\$
    – DMGregory
    Commented Aug 9, 2023 at 16:44

You must log in to answer this question.