# 2d Nebula Shader

I am still a beginner at shading, but I tried to put together something pretty.

Stars rendered using https://godotshaders.com/shader/stars-shader/ by https://godotshaders.com/author/gerardogc2378/

Using FBM on perlin noise to generate clouds, and parallax scrolling through in a circle.

##### Shader code
``````shader_type canvas_item;

//uniform vec3 color_replace = vec3(1.0,1.0,0.0);
uniform int OCTAVE = 12;
uniform float timescale = 5.0;
uniform vec4 CLOUD1_COL: hint_color = vec4(0.41,0.64,0.78,0.4);
uniform vec4 CLOUD2_COL: hint_color = vec4(0.99,0.79,0.46,0.2);
uniform vec4 CLOUD3_COL: hint_color = vec4(0.81,0.31,0.59,1.0);
uniform vec4 CLOUD4_COL: hint_color = vec4(0.27,0.15,0.33,1.0);
uniform vec4 SPACE: hint_color = vec4(0.09,0.06,0.28,0.3);
uniform float zoomScale = 6.0;
uniform float size = 10.0;
uniform float starscale = 20.0;
uniform float prob: hint_range(0.0,1.0) = 0.98;

float rand(vec2 input){
return fract(sin(dot(input,vec2(23.53,44.0)))*42350.45);
}

float perlin(vec2 input){
vec2 i = floor(input);
vec2 j = fract(input);
vec2 coord = smoothstep(0.,1.,j);

float a = rand(i);
float b = rand(i+vec2(1.0,0.0));
float c = rand(i+vec2(0.0,1.0));
float d = rand(i+vec2(1.0,1.0));

return mix(mix(a,b,coord.x),mix(c,d,coord.x),coord.y);
}

float fbm(vec2 input){
float value = 0.0;
float scale = 0.5;

for(int i = 0; i < OCTAVE; i++){
value += perlin(input)*scale;
input*=2.0;
scale*=0.5;
}
return value;
}

float fbmCloud(vec2 input, float minimum){
float value = 0.0;
float scale = 0.5;

for(int i = 0; i < OCTAVE; i++){
value += perlin(input)*scale;
input*=2.0;
scale*=0.5;
}
return smoothstep(0.,1.,(smoothstep(minimum,1.,value)-minimum)/(1.0-minimum));
}

float fbmCloud2(vec2 input, float minimum){
float value = 0.0;
float scale = 0.5;

for(int i = 0; i < OCTAVE; i++){
value += perlin(input)*scale;
input*=2.0;
scale*=0.5;
}
return (smoothstep(minimum,1.,value)-minimum)/(1.0-minimum);
}

void fragment(){
vec4 originalColor = texture(TEXTURE, UV);
float timescaled = TIME * timescale;
//vec2 zoomUV = vec2(zoomScale * UV.x + UV.x*0.04*TIME*sin(0.07*TIME), zoomScale * UV.y + UV.y*0.05*TIME*cos(0.06*TIME));
vec2 zoomUV2 = vec2(zoomScale * UV.x + 0.03*timescaled*sin(0.07*timescaled), zoomScale * UV.y + 0.03*timescaled*cos(0.06*timescaled));
vec2 zoomUV3 = vec2(zoomScale * UV.x + 0.027*timescaled*sin(0.07*timescaled), zoomScale * UV.y + 0.025*timescaled*cos(0.06*timescaled));
vec2 zoomUV4 = vec2(zoomScale * UV.x + 0.021*timescaled*sin(0.07*timescaled), zoomScale * UV.y + 0.021*timescaled*cos(0.07*timescaled));
float tide = 0.05*sin(TIME);
float tide2 = 0.06*cos(0.3*TIME);
//if(color_replace == originalColor.rgb){
vec4 nebulaTexture = vec4(SPACE.rgb, 0.5+0.2*sin(0.23*TIME +UV.x-UV.y));
nebulaTexture += fbmCloud2(zoomUV3, 0.24 + tide)*CLOUD1_COL;
nebulaTexture += fbmCloud(zoomUV2*0.9, 0.33 - tide)*CLOUD2_COL;
nebulaTexture = mix(nebulaTexture,CLOUD3_COL,fbmCloud(vec2(0.9*zoomUV4.x,0.9*zoomUV4.y), 0.25+tide2));
nebulaTexture = mix(nebulaTexture,CLOUD4_COL,fbmCloud(zoomUV3*0.7+2.0, 0.4+tide2));
vec2 zoomstar = starscale*zoomUV2;
vec2 pos = floor(zoomstar / size);
float starValue = rand(pos);
if(starValue>prob){
vec2 center = size * pos + vec2(size, size) * 0.5;
float t = 0.9 + 0.2 * sin(TIME * 8.0 + (starValue - prob) / (1.0 - prob) * 45.0);
float color = 1.0 - distance(zoomstar, center) / (0.5 * size);
nebulaTexture = mix(nebulaTexture, vec4(1.0,1.0,1.0,1.0),smoothstep(0.,1.,color * t / (abs(zoomstar.y - center.y)) * t / (abs(zoomstar.x - center.x))));
} else {
zoomstar *= 5.0;
pos = floor(zoomstar / size);
float starValue2 = rand(pos + vec2(13.0,13.0));
if(starValue2 >= 0.95){
vec2 center = size * pos + vec2(size, size) * 0.5;
float t = 0.9 + 0.2 * sin(TIME * 8.0 + (starValue - prob) / (1.0 - prob) * 45.0);
float color = 1.0 - distance(zoomstar, center) / (0.5 * size);
nebulaTexture = mix(nebulaTexture, vec4(1.0,1.0,1.0,1.0),fbmCloud(pos,0.0)*smoothstep(0.,1.,color * t / (abs(zoomstar.y - center.y)) * t / (abs(zoomstar.x - center.x))));
}
}
COLOR = vec4(nebulaTexture.rgb, 1.0);
//COLOR = vec4(nebulaTexture.rgb,nebulaTexture.a * 1.2)
//} else {
//	COLOR = originalColor;
//}
}``````
###### Tags
2d, space
The shader code and all code snippets in this post are under CC0 license and can be used freely without the author's permission. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

## Related shaders

### Spectrum Displaying Shader

Subscribe
Notify of

5 Comments
Inline Feedbacks
View all comments
maulinux
9 months ago

cool shader, i use it

Seqxxxx
6 months ago

doesn’t seem to work with Godot 4.0? I get weird blocky artifacts. Was wondering if anybody has managed to fix this? I never really touch shaders.

Shadowblitz16
5 months ago

your shader works differently depending on whether it’s ran in the editor or in game