• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

Cloud shader problems

Seiko4169

Member
Hi,
I'm trying to translate a cloud shader from shader toy to GML and as a relative newbie to shaders I'm struggling.

The original is here...

My code so far is resulting in the sprite simply flickering from the sky blue to slight variations of the sky blue.
Code:
//
// Simple passthrough fragment shader
//
varying vec2   v_vPosition;
varying vec2      v_vTexcoord;
varying vec4      v_vColour;
uniform float     time;                  // Time
uniform sampler2D noiseChannel;             // Noise Texture

const float timeScale = 10.0;
const float cloudScale = 0.5;
const float skyCover = 0.6;
const float softness = 0.2;
const float brightness = 0.0;
const int noiseOctaves = 8;
const float curlStrain = 3.0;

float saturate(float num)
{
    return clamp(num,0.0,1.0);
}

float noise(vec2 uv)
{
   return texture2D(noiseChannel,uv).r;
}

vec2 rotate(vec2 uv)
{
    uv = uv + noise(uv*0.2)*0.005;
    float rot = curlStrain;
    float sinRot=sin(rot);
    float cosRot=cos(rot);
    mat2 rotMat = mat2(cosRot,-sinRot,sinRot,cosRot);
    return uv * rotMat;
}

float fbm (vec2 uv)
{
    float rot = 1.57;
    float sinRot=sin(rot);
    float cosRot=cos(rot);
    float f = 0.0;
    float total = 0.0;
    float mul = 0.5;
    mat2 rotMat = mat2(cosRot,-sinRot,sinRot,cosRot);
  
    for(int i = 0;i < noiseOctaves;i++)
    {
        f += noise(uv+time*0.00015*timeScale*(1.0-mul))*mul;
        total += mul;
        uv *= 3.0;
        uv=rotate(uv);
        mul *= 0.5;
    }
    return f/total;
}

void main(void)
{
 
    vec2 uv = v_vPosition.xy/(40000.0*cloudScale);
    float cover = 0.9;
    float bright = brightness*(1.8-cover);
  
    float color1 = fbm(uv-0.5+time*0.00004*timeScale);
    float color2 = fbm(uv-10.5+time*0.00002*timeScale);
  
    float clouds1 = smoothstep(1.0-cover,min((1.0-cover)+softness*2.0,1.0),color1);
    float clouds2 = smoothstep(1.0-cover,min((1.0-cover)+softness,1.0),color2);
  
    float cloudsFormComb = saturate(clouds1+clouds2);
  
    vec4 skyCol = vec4(0.6,0.8,1.0,1.0);
    float cloudCol = saturate(saturate(1.0-pow(color1,1.0)*0.2)*bright);
    vec4 clouds1Color = vec4(cloudCol,cloudCol,cloudCol,1.0);
    vec4 clouds2Color = mix(clouds1Color,skyCol,0.25);
    vec4 cloudColComb = mix(clouds1Color,clouds2Color,saturate(clouds2-clouds1));
  
    gl_FragColor = mix(skyCol,cloudColComb,cloudsFormComb);
}

I have set the texture to a noise texture (128x128) separate texture page (the same as the channel0 texture on Shadertoy) but simply don't get to see any clouds.

Having spent the last 5 hours reading tutorials and looking at other samples I still don't know why I'm getting the results I'm getting and would really appreciate some guidance.
 

Attachments

Last edited:
Make sure you set the texture to repeat.

You'll probably want to revert the "brightness" constant back to 1.0, instead of leaving it at 0.0.

Make sure you've passed in v_vPosition correctly from the vertex shader. It should be equal to in_Position.xy.

Since you're only using one texture here, you might as well make the noise texture the base texture.
 

Seiko4169

Member
Thanks yes I set the noise function to use gm_baseTexture.

I don't know how to set the texture to repeat though? Is this a shader setting or GM one?

Also, I notice that shader toy only looks good when filtering is set to mipmap? is this the same as gpu_set_tex_mip_filter(tf_linear);

I set the texture position using this..

Code:
void main()
{
    vec4 object_space_pos = vec4( in_Position.x, in_Position.y, in_Position.z, 1.0);
    gl_Position = gm_Matrices[MATRIX_WORLD_VIEW_PROJECTION] * object_space_pos;
    
    v_vColour = in_Colour;
    v_vTexcoord = in_TextureCoord;
    v_vPosition = in_Position.xy;
        
}

And this is my current position...
 

Attachments

use gpu_texture_repeat or gpu_texture_repeat_ext to set the texture to repeat.

yoyo hasn't added mipmap features to gms1 (I don't use GMS2), so I don't have sufficient experience to answer your question about mipmapping. I don't see any difference when I switch between linear and mipmap on shadertoy.
 

Seiko4169

Member
thanks that's a big help and I now at least see a starting point. I just need to turn on the filtering (note the shadrertoy one looks like mine if set to nearest). Once I get past that I think I might have something :-/
 
Okay, turn on linear texture filtering at least. gpu_set_texfilter or gpu_set_texfilter_ext.

EDIT:

if you find it helpful, here's the noise texture used in shadertoy:
 
Last edited:

Seiko4169

Member
Thanks, yes I already have been using that but something is still wrong with my sampling / cloud scale setting. I don't know how to scale the actual render. Too small and I see what looks like lots of the texture overlaid. Too big and the screen is simply white as if completely covered in cloud.
 
Top