Stylized Cloudy Sky (v2)
This is a stylized Spatial-shader for generating a cloudlayer. Two copies of a subdivided plane is needed for this solution, one for the top part of the clouds and one for the bottom.
Instructions : Import two copies of a subdivided plane, apply the top shader for one of them and the bottom part for the other one. (there are two shader codes in the shadercode window divided by a comment line)
When it comes to shader parameters you need to assign a noise to the Noise 1 texture slot.
I’ve screenshotted the parameters that worked good in my scene, depending on how high you want the clouds you need to change the discard height etc
Update 6/11/2024 – taking the world position of the node into account so that the discard height is based on the nodes position instead of worldspace, no more guessing where it should be discarded in worldspace. So now the discardheight should be much lower, like 10-25, doesnt take long to find it while playing around with the numbers.
Shader code
////////////// THIS IS THE SHADERCODE FOR THE TOP PART, BOTTOM PART CAN BE FOUND LOWER //////////////
////////////// THIS IS THE SHADERCODE FOR THE TOP PART, BOTTOM PART CAN BE FOUND LOWER //////////////
shader_type spatial;
render_mode blend_mix, cull_disabled;
//This is where we set up the shader parameters so we can tweak the shader in real time later.
uniform sampler2D Noise1;
uniform float timeScale1;
uniform float timeScale2;
uniform float cloud1worldScale;
uniform float cloud2worldScale;
uniform float displacementStrength;
//This is the vertexshader
void vertex()
{
//Time is multiplied by cloudSpeed1 & cloudSpeed2, to give us control to tweak how fast the clouds are moving.
float cloudSpeed1 = timeScale1 * TIME;
float cloudSpeed2 = timeScale2 * TIME;
//Here we set the UV for the texture to be world position stretched over X and Z axis
vec2 world_pos = (vec4(VERTEX,1.f) ).xz;
//Two different UV's are made here for the clouds, they will move in different directions in the world x-axis but in the same direction in world z-axis
vec2 Cloud1UV = vec2((world_pos.x * cloud1worldScale) + cloudSpeed1 ,(world_pos.y * cloud1worldScale) + cloudSpeed1);
vec2 Cloud2UV = vec2((world_pos.x * cloud2worldScale) - cloudSpeed2 ,(world_pos.y * cloud2worldScale) + cloudSpeed2);
//Noise-textures are sampled and assigned the UV's created earlier
vec4 Cloud1 = texture(Noise1, Cloud1UV) ;
vec4 Cloud2 = texture(Noise1, Cloud2UV) ;
//Multiplying the Cloud noise-textures here, this resulting in them seemingly "melting together". We then normalize the result to make sure it's between -1 and 1.
vec4 CloudCombined = normalize(Cloud1 * Cloud2);
//Position of the vertex in y-space is moved based on the combined clouds and the parameter displacementStrength so we can tweak it in real time.
VERTEX.y = VERTEX.y + CloudCombined.r * displacementStrength;
}
uniform float discardHeight;
//This is the pixelshader/fragmentshader
void fragment() {
//Pixels are taken from viewspace to worldspace by multiplying with the inverse view matrix.
vec4 worldVertex = INV_VIEW_MATRIX * vec4(VERTEX, 1.0);
float discardHeightWorldPos = discardHeight + NODE_POSITION_WORLD.y;
//Checking if the pixels world position is above the discardheight, if not we discard them since we dont want to render them.
if (worldVertex.y > discardHeight)
ALBEDO = vec3(1.f,1.f,1.f);
else
discard;
}
////////////// BELOW IS THE SHADER CODE FOR THE BOTTOM PART //////////////
shader_type spatial;
render_mode blend_mix, cull_disabled;
//This is where we set up the shader parameters so we can tweak the shader in real time later.
uniform sampler2D Noise1;
uniform float timeScale1;
uniform float timeScale2;
uniform float cloud1worldScale;
uniform float cloud2worldScale;
uniform float displacementStrength;
//This is the vertexshader
void vertex()
{
//Time is multiplied by cloudSpeed1 & cloudSpeed2, to give us control to tweak how fast the clouds are moving.
float cloudSpeed1 = timeScale1 * TIME;
float cloudSpeed2 = timeScale2 * TIME;
//Here we set the UV for the texture to be world position stretched over X and Z axis
vec2 world_pos = (vec4(VERTEX,1.f) ).xz;
//Two different UV's are made here for the clouds, they will move in different directions in the world x-axis but in the same direction in world z-axis
vec2 Cloud1UV = vec2((world_pos.x * cloud1worldScale) + cloudSpeed1 ,(world_pos.y * cloud1worldScale) + cloudSpeed1);
vec2 Cloud2UV = vec2((world_pos.x * cloud2worldScale) - cloudSpeed2 ,(world_pos.y * cloud2worldScale) + cloudSpeed2);
//Noise-textures are sampled and assigned the UV's created earlier
vec4 Cloud1 = texture(Noise1, Cloud1UV) ;
vec4 Cloud2 = texture(Noise1, Cloud2UV) ;
//Multiplying the Cloud noise-textures here, this resulting in them seemingly "melting together". We then normalize the result to make sure it's between -1 and 1.
vec4 CloudCombined = normalize(Cloud1 * Cloud2);
//Position of the vertex in y-space is moved based on the combined clouds and the parameter displacementStrength so we can tweak it in real time.
VERTEX.y = VERTEX.y + (1.f - CloudCombined.r) * displacementStrength;
}
uniform float discardHeight;
//This is the pixelshader/fragmentshader
void fragment() {
//Pixels are taken from viewspace to worldspace by multiplying with the inverse view matrix.
vec4 worldVertex = INV_VIEW_MATRIX * vec4(VERTEX, 1.0);
float discardHeightWorldPos = discardHeight + NODE_POSITION_WORLD.y;
//Checking if the pixels world position is above the discardheight, if not we discard them since we dont want to render them.
if (worldVertex.y < discardHeight )
ALBEDO = vec3(1.f,1.f,1.f);
else
discard;
}
Can you make a tutorial of how to implement this?
I just can’t guess what i’m doing wrong, it’s just don’t work, i only getting a floating plane and that’s all
It could have been because the shader was written with discardheight as in the general worldspace, I’ve updated it now so it takes the world position of the node into account, so you need a much lower discardheight and it should be visible on any height (if you also have the other values in that is)
Sorry had to rollback that change, will update it proper at a later date
im having the same issue hes having, instead of clouds its just two solid wavy planes, they dont look like clouds.