#procedural skybox shader

1 messages · Page 1 of 1 (latest)

stuck tinsel
#

I have been thinking about a skybox idea for a while and wanted to create a proof of concept in Unity but I sadly don't know where to start.

my idea is to have an array of points which are stars in the night sky. in this concept the stars are far enough to not need to be in the scene but close enough where parallax is something I want to think about instead of using a static texture.

to accomplish this, I would like to draw onto a cubemap where I can use the direction from the player to the pixel on the cubemap and the direction from the player to the star in a dot product. if the dot product falls within a certain margin it should draw the star on that pixel.
(ofc this would require optimization after the proof of concept but I first want to get this to work xD)

sadly I think this isn't possible in Shadergraph which is about the extend of my knowledge on shaders.

I was hoping if someone could point me in the right direction to get started on this shader.

mainly my questions are:

  • what kind of shader do I use? compute shader, unlit shader, etc.
  • how do I get the direction from the player to the cubemap pixel that is currently being calculated?
  • how do I get my list of star positions into the shader?

any tips on optimizing are also welcome since in this idea, every pixel would check every single point. rn my only idea is to use positive and negative directions of the ray to narrow down to 1/8th of the sky

sick stag
#

Shader graph sounds doable if you don't mind working with textures and feeding your shaders information through them.

#

Do the calcs on the CPU side then update your texture to where these stars would be

stuck tinsel
#

I thought Shader graph wasn't very good at iterrating over things

sick stag
#

It'll iterate per fragment so by giving it some instructions on where the star pixels will be located it'll compare for each pixel to where it would be on that texture

#

but if your stars are more than a single pixel, maybe like some clipart of a star, that would require a bit more work

acoustic jetty
#

In shadergraph you'll have to make a custom function node to loop over the star coordinates, but appart from this, it's doable.
You don't need to output to a cubemap, you can directly make a skybox shader.

As for the "distance to the star", in a skybox shader it's simply viewdir DOT starDir
In a cubemap shader (using a custom render texture ?) the by normalizing the output of the position node you'd have something similar to the viewdir.

If you want to stick with the cubemap approach, you can also use a compute shader, which would allow you to only draw on the pixels where the stars are instead of iterating over all the pixels.

Finaly, an other option is to use VFXGraph 😄
Draw the stars as particles, VFXGraph can handle quite a lot of particles before tanking performances.

sick stag
#

Another idea is you can set up a orthographic camera in a space where you'd populate the stars then blit that rendering every time the star map is updated and then insert it into the shader graph.

#

would solve the issue of using clip art if you decide to do that instead of pixel size stars

stuck tinsel
acoustic jetty
#

Warning : you can not resize the array once set without restarting the editor :/

stuck tinsel
#

what do you mean by include file mode?

acoustic jetty
#

The custom function node can either reference an HLSL file, or directly contain your code.
You can declare the array only by using the file reference method.

stuck tinsel
#

ah ok I had the file already so that'll be fine

strong vortex
#

I remember having issues using a shader graph shader for sky but this was in unity 2022. Is this resolved now?

stuck tinsel
#

I think so yea, I have to make this one work to be sure tho xD

stuck tinsel
#

I got it to work! :D it somehow runs pretty smoothly.
took me a while to figure out that I need to normalize vectors before doing a dot product on them XD
for anyone interested, here's the code, the graph and a little demo. I'll mark this thread as solved now. thanks a lot for the help everyone UnityChanCheer

StructuredBuffer<float3> stars;

void CalculateStars_float(float3 ViewDir, float3 OriginPos, out float DotResult)
{
    DotResult = -1;
    
#ifdef SHADERGRAPH_PREVIEW
        DotResult = dot(float3(0,1,0) - OriginPos, ViewDir);
        return;
#else
    for (int i = 0; i < 4096; i++)
    {
        if (all(stars[i] == float3(0, 0, 0)))
            continue;

        if (stars[i].x < 0 && ViewDir.x > 0 || stars[i].x > 0 && ViewDir.x < 0)
            continue;
        if (stars[i].y < 0 && ViewDir.y > 0 || stars[i].y > 0 && ViewDir.y < 0)
            continue;
        if (stars[i].z < 0 && ViewDir.z > 0 || stars[i].z > 0 && ViewDir.z < 0)
            continue;

        float dotAngle = dot(normalize(stars[i] - OriginPos), normalize(ViewDir));
        if (dotAngle > DotResult)
        {
            DotResult = dotAngle;
        }
    }
#endif
}
acoustic jetty
#

Nice !
Some things to improve even :

  • You don't have to expose the player pos, just use the camera node position output.
  • Avoid normalizing within the loop, normalize the star values in c# before storing in the buffer, and normalize the viewdir outside of the custom function node (it should however already be a normalized vector).

Be careful with the X/Y/Z direction checks, it might cut the dot value for stars that are near 0 in each direction.
Maybe instead consider skipping based on some rough frustum culling logic.

stuck tinsel
#

yea I found some bugs xD mainly the y and z of the player position not moving the stars while the x moves in all 3 directions at the same time.
also as u said the direction checks caused some silly stuff. I'll check out the frustum culling. and I'll see if I can normalize the stars but that might mess with the movement, I'd need to set the stars array every time the player position updates