godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.13k stars 71 forks source link

Expose viewport size to sky shaders #8019

Open Andicraft opened 11 months ago

Andicraft commented 11 months ago

Describe the project you are working on

A sky shader with volumetric clouds

Describe the problem or limitation you are having in your project

In creating a volumetric cloud shader for my skybox, I've run into an issue where the only way to not have noticeable banding for the clouds is to run the raymarch at a very high step count. This is obviously not great for performance - if I run at a lower step cound, banding becomes immediately clear:

image

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Add in vec2 VIEWPORT_SIZE to the sky shader built-ins. This will let me map noise textures to the screen at a per-pixel level, which will in turn let me offset the raymarch start by a random value per pixel to avoid banding. It would massively cut down the rendering cost of the shader in exchange for some noise.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

in vec2 VIEWPORT_SIZE should be in the list of built-ins for sky shaders.

If this enhancement will not be used often, can it be worked around with a few lines of script?

You could run a script that grabs the viewport size and outputs it as a shader global, but the convenience factor isn't high for something that a lot of different types of shaders could use. You would also have to pass in a different size for the radiance cubemap renders.

Is there a reason why this should be core and not an add-on in the asset library?

This built-in already exists for spatial shaders. It should be added to sky shaders for parity reasons, and simply for the fact that it's useful.

OhiraKyou commented 11 months ago

I just ran into this as well while adding blue noise dithering to counter banding in my gradient-based sky. I need the viewport size to calculate pixel-perfect repeating noise UV coordinates.

Although, a screen pixel coordinate built-in would also work.

Calinou commented 11 months ago

I just ran into this as well while adding blue noise dithering to counter banding in my gradient-based sky.

There is already built-in debanding in sky shaders :slightly_smiling_face: You can enable it using render_mode use_debanding; in a sky shader.

This is what's internally used for debanding: https://github.com/godotengine/godot/blob/b1371806ad3907c009458ea939bd4b810f9deb21/servers/rendering/renderer_rd/shaders/environment/sky.glsl#L285-L287 It doesn't use viewport size, but the fragment coordinates instead.

OhiraKyou commented 11 months ago

Wait a minute... Although it's not stated in the sky shader tutorial docs, you do have access to FRAGCOORD (the screen pixel coordinates) in sky shaders, which is good. And, for some reason, SCREEN_UV is equal to FRAGCOORD.xy instead of SCREEN_UV being in the [0, 1] range.

Edit: Sampling noise with FRAGCOORD.xy worked perfectly for my use case. Hope that stays. So, I no longer have a horse in this race. But, some people may still also need the proper [0, 1] SCREEN_UV and pixel VIEWPORT_SIZE. Although, for a sky shader, specifically, I find it a lot harder imagine uses for those now that I know FRAGCOORD.xy is available.

For reference, I'm using Godot v4.1.2.stable and the Compatibility renderer.

There is already built-in debanding in sky shaders 🙂

I dither by offsetting sampling of a color palette rather than directly modifying output colors.