Cloud Shader Problem

Okay, I read @Ignatz’s Ebook on Shaders and I nearly perfected a cloud shader I’ve been working on, but here’s the problem;
It only works in the following circumstances:

  1. the "uniform sampler2D texture; is set to a background image like SpaceCute:Background, and
  2. When the keyboard is up, limiting the visible space of the shader.

Here’s the Vertex:

//
//  CloudShader.vsh
//  created with Shaderific
//


attribute vec4 position;
attribute vec3 normal;

uniform mat4 modelViewProjectionMatrix;
uniform mat4 modelViewMatrix;
uniform mat3 normalMatrix;
uniform float time;

varying vec3 eyespaceNormal; 
varying vec4 eyespacePosition;
varying vec3 noiseVector;


void main(void)
{
    
    vec3 translation = vec3(1.0, 1.0, 1.0) * time / 20.0;
    noiseVector = position.xyz + translation;
    
    eyespaceNormal = normalMatrix * normal;
    eyespacePosition = modelViewMatrix * position;
    gl_Position = modelViewProjectionMatrix * position;
    
}

Here’s the Fragment:

//
//  CloudShader.fsh
// 
//
//
//  Description : Array and textureless GLSL 2D/3D/4D simplex 
//                  noise functions.
//       Author : Original Heat Shader By: Ian McEwan
//       Cloud Conversion By: Austin Wiltse/CodeaNoob
// 


precision highp float;
precision highp int;
uniform lowp sampler2D texture;
varying vec3 eyespaceNormal;
varying vec4 eyespacePosition;
varying vec3 noiseVector;

uniform vec4 materialDiffuseColor0;
uniform vec4 materialDiffuseColor;
vec3 mod289(vec3 x) {
    return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec4 mod289(vec4 x) {
    return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec4 permute(vec4 x) {
    return mod289(((x*34.0)+1.0)*x);
}

vec4 taylorInvSqrt(vec4 r)
{
    return 1.79284291400159 - 0.85373472095314 * r;
}

float snoise(vec3 v)
{ 
    const vec2  C = vec2(1.0/6.0, 1.0/3.0) ;
    const vec4  D = vec4(0.0, 0.5, 1.0, 2.0);
    
    // First corner
    vec3 i  = floor(v + dot(v, C.yyy) );
    vec3 x0 =   v - i + dot(i, C.xxx) ;
    
    // Other corners
    vec3 g = step(x0.yzx, x0.xyz);
    vec3 l = 1.0 - g;
    vec3 i1 = min( g.xyz, l.zxy );
    vec3 i2 = max( g.xyz, l.zxy );
    
    //   x0 = x0 - 0.0 + 0.0 * C.xxx;
    //   x1 = x0 - i1  + 1.0 * C.xxx;
    //   x2 = x0 - i2  + 2.0 * C.xxx;
    //   x3 = x0 - 1.0 + 3.0 * C.xxx;
    vec3 x1 = x0 - i1 + C.xxx;
    vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
    vec3 x3 = x0 - D.yyy;      // -1.0+3.0*C.x = -0.5 = -D.y
    
    // Permutations
    i = mod289(i); 
    vec4 p = permute( permute( permute( 
                                       i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
                              + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) 
                     + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
    
    // Gradients: 7x7 points over a square, mapped onto an octahedron.
    // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
    float n_ = 0.142857142857; // 1.0/7.0
    vec3  ns = n_ * D.wyz - D.xzx;
    
    vec4 j = p - 49.0 * floor(p * ns.z * ns.z);  //  mod(p,7*7)
    
    vec4 x_ = floor(j * ns.z);
    vec4 y_ = floor(j - 7.0 * x_ );    // mod(j,N)
    
    vec4 x = x_ *ns.x + ns.yyyy;
    vec4 y = y_ *ns.x + ns.yyyy;
    vec4 h = 1.0 - abs(x) - abs(y);
    
    vec4 b0 = vec4( x.xy, y.xy );
    vec4 b1 = vec4( x.zw, y.zw );
    
    //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
    //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
    vec4 s0 = floor(b0)*2.0 + 1.0;
    vec4 s1 = floor(b1)*2.0 + 1.0;
    vec4 sh = -step(h, vec4(0.0));
    
    vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
    vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
    
    vec3 p0 = vec3(a0.xy,h.x);
    vec3 p1 = vec3(a0.zw,h.y);
    vec3 p2 = vec3(a1.xy,h.z);
    vec3 p3 = vec3(a1.zw,h.w);
    
    //Normalise gradients
    vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
    p0 *= norm.x;
    p1 *= norm.y;
    p2 *= norm.z;
    p3 *= norm.w;
    
    // Mix final noise value
    vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
    m = m * m;
    return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), 
                                 dot(p2,x2), dot(p3,x3) ) );
}


void main(void)
{
    
    float intensity = (snoise(noiseVector * 5.0) +
                             0.5 * snoise(noiseVector * 10.0) +
                             0.25 * snoise(noiseVector * 20.0) + 1.75) / 3.5;                             
                             
    float exponent = intensity - 0.35;
    
    if (exponent < 0.0)
        exponent = 0.0;
    
    intensity = 1.0 - pow(0.1, exponent); 

    float attenuation = dot(eyespaceNormal, -normalize(eyespacePosition.xyz)); 
    
    if (attenuation < 0.5)
        attenuation = 3.0 - 4.0 * attenuation;
    else
        attenuation = 1.0;
    

    vec3 color = mix(attenuation * vec3(0.2, 0.2, 0.6), vec3(1.0, 1.0, 1.0), intensity);
    gl_FragColor = vec4(color, 1.0);
    
}

I assume it’s too complicated of a shader to do, but that is whats confusing me! The ripple example shader works, but not a simple cloud one?Also, Please explain to me why It doesn’t move, that’s this shaders one job, otherwise i’d use a sprite.

Wow, that’s a big one!

It is definitely not simple, though. The problem could be in several places, and I don’t understand the algorithms being used.

I presume you got all this stuff from somewhere. I’d check it very carefully.

The most annoying part is that it’s supposed to move! I might just have to use a sprite until I (or someone else) can figure it out.

Also, I got base help from the Shaderific app and their tutorials

Yes, I just looked at that, it’s very cool!

Can you post the Codea part of the code too.

By the way, you shouldn’t replace the author’s name with yours, since you are basically copying his code. Better to say, "Original shader by XXX, mods by Codeanoob "

Oh, sorry, Changed it. Thanks for pointing that out

I can’t seem to find the mesh file, it’s here somewhere. I’ll find it though soon.

Try this

function setup()
    m=mesh()
    
    --add blank retangle close to camera (so it is very small)
    m:addRect(0,0,1.2,1)
    m:setColors(color(255))
    
    --attach shader
    m.shader=shader(cloudShader.v,cloudShader.f)
    m.shader.materialDiffuseColor0=color(0,0,255)
    m.shader.materialDiffuseColor1=color(255)
    
    --set normals facing the front
    local n={} for i=1,6 do n[i]=vec3(0,0,1) end  m.normals=n
    pos=vec3(-100,-100,2)
end

function draw()
    background(0)
    perspective()
    camera(0,0,0,0,0,-10)
    m.shader.modelViewMatrix=viewMatrix()
    m.shader.normalMatrix= modelMatrix()    
    m.shader.time=ElapsedTime
    pushMatrix()
    translate(0,0,-1)
    m:draw()
    popMatrix()
end

cloudShader={
v=[[

//
//  CloudShader.vsh
//  created with Shaderific
//


attribute vec4 position;
attribute vec3 normal;

uniform mat4 modelViewProjection;
uniform mat4 modelViewMatrix;
uniform mat4 normalMatrix;

uniform float time;

varying vec3 eyespaceNormal; 
varying vec4 eyespacePosition;
varying vec3 noiseVector;


void main(void)
{
    
    vec3 translation = vec3(1.0, 1.0, 1.0) * time / 20.0;
    noiseVector = position.xyz + translation;
    
    eyespaceNormal = (normalMatrix * vec4(normal,0.0)).xyz;
    eyespacePosition = modelViewMatrix * position;
    gl_Position = modelViewProjection * position;
    
}    
]],
f=[[

//
//  CloudShader.fsh
//  created with Shaderific
//
//
//  Description : Array and textureless GLSL 2D/3D/4D simplex 
//                  noise functions.
//       Author : Ian McEwan, Ashima Arts.
//   Maintainer : ijm
//      Lastmod : 20110822 (ijm)
//      License : Copyright (C) 2011 Ashima Arts. All rights reserved.
//               Distributed under the MIT License. See LICENSE file.
//               https://github.com/ashima/webgl-noise
// 


precision highp float;
precision highp int;

varying vec3 eyespaceNormal;
varying vec4 eyespacePosition;
varying vec3 noiseVector;

uniform vec4 materialDiffuseColor0;
uniform vec4 materialDiffuseColor1;


vec3 mod289(vec3 x) {
    return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec4 mod289(vec4 x) {
    return x - floor(x * (1.0 / 289.0)) * 289.0;
}

vec4 permute(vec4 x) {
    return mod289(((x*34.0)+1.0)*x);
}

vec4 taylorInvSqrt(vec4 r)
{
    return 1.79284291400159 - 0.85373472095314 * r;
}

float snoise(vec3 v)
{ 
    const vec2  C = vec2(1.0/6.0, 1.0/3.0) ;
    const vec4  D = vec4(0.0, 0.5, 1.0, 2.0);
    
    // First corner
    vec3 i  = floor(v + dot(v, C.yyy) );
    vec3 x0 =   v - i + dot(i, C.xxx) ;
    
    // Other corners
    vec3 g = step(x0.yzx, x0.xyz);
    vec3 l = 1.0 - g;
    vec3 i1 = min( g.xyz, l.zxy );
    vec3 i2 = max( g.xyz, l.zxy );
    
    //   x0 = x0 - 0.0 + 0.0 * C.xxx;
    //   x1 = x0 - i1  + 1.0 * C.xxx;
    //   x2 = x0 - i2  + 2.0 * C.xxx;
    //   x3 = x0 - 1.0 + 3.0 * C.xxx;
    vec3 x1 = x0 - i1 + C.xxx;
    vec3 x2 = x0 - i2 + C.yyy; // 2.0*C.x = 1/3 = C.y
    vec3 x3 = x0 - D.yyy;      // -1.0+3.0*C.x = -0.5 = -D.y
    
    // Permutations
    i = mod289(i); 
    vec4 p = permute( permute( permute( 
                                       i.z + vec4(0.0, i1.z, i2.z, 1.0 ))
                              + i.y + vec4(0.0, i1.y, i2.y, 1.0 )) 
                     + i.x + vec4(0.0, i1.x, i2.x, 1.0 ));
    
    // Gradients: 7x7 points over a square, mapped onto an octahedron.
    // The ring size 17*17 = 289 is close to a multiple of 49 (49*6 = 294)
    float n_ = 0.142857142857; // 1.0/7.0
    vec3  ns = n_ * D.wyz - D.xzx;
    
    vec4 j = p - 49.0 * floor(p * ns.z * ns.z);  //  mod(p,7*7)
    
    vec4 x_ = floor(j * ns.z);
    vec4 y_ = floor(j - 7.0 * x_ );    // mod(j,N)
    
    vec4 x = x_ *ns.x + ns.yyyy;
    vec4 y = y_ *ns.x + ns.yyyy;
    vec4 h = 1.0 - abs(x) - abs(y);
    
    vec4 b0 = vec4( x.xy, y.xy );
    vec4 b1 = vec4( x.zw, y.zw );
    
    //vec4 s0 = vec4(lessThan(b0,0.0))*2.0 - 1.0;
    //vec4 s1 = vec4(lessThan(b1,0.0))*2.0 - 1.0;
    vec4 s0 = floor(b0)*2.0 + 1.0;
    vec4 s1 = floor(b1)*2.0 + 1.0;
    vec4 sh = -step(h, vec4(0.0));
    
    vec4 a0 = b0.xzyw + s0.xzyw*sh.xxyy ;
    vec4 a1 = b1.xzyw + s1.xzyw*sh.zzww ;
    
    vec3 p0 = vec3(a0.xy,h.x);
    vec3 p1 = vec3(a0.zw,h.y);
    vec3 p2 = vec3(a1.xy,h.z);
    vec3 p3 = vec3(a1.zw,h.w);
    
    //Normalise gradients
    vec4 norm = taylorInvSqrt(vec4(dot(p0,p0), dot(p1,p1), dot(p2, p2), dot(p3,p3)));
    p0 *= norm.x;
    p1 *= norm.y;
    p2 *= norm.z;
    p3 *= norm.w;
    
    // Mix final noise value
    vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
    m = m * m;
    return 42.0 * dot( m*m, vec4( dot(p0,x0), dot(p1,x1), 
                                 dot(p2,x2), dot(p3,x3) ) );
}


void main(void)
{
    
    float intensity = (snoise(noiseVector * 5.0) +
                             0.5 * snoise(noiseVector * 10.0) +
                             0.25 * snoise(noiseVector * 20.0) + 1.75) / 3.5;                            
                             
    float exponent = intensity - 0.35;
    
    if (exponent < 0.0)
        exponent = 0.0;
    
    intensity = 1.0 - pow(0.1, exponent); 

    float attenuation = dot(eyespaceNormal, -normalize(eyespacePosition.xyz)); 
    
    if (attenuation < 0.5)
        attenuation = 3.0 - 4.0 * attenuation;
    else
        attenuation = 1.0;
    

    vec3 color = mix(attenuation * vec3(0.2, 0.2, 0.6), vec3(1.0, 1.0, 1.0), intensity);
    gl_FragColor = vec4(color, 1.0);
    
}

]]

}

@Ignatz. How smooth does this run on your ipad? I am on a ipad2 and it stutters as the clouds move. Just curious if it is my ipad or if the display is normal?

@Aalok - it’s a bit stuttery, but it is the same way in the Shaderific app. This means it’s not really practical for use with anything else.

Here is a cloud shader I’ve used hidden in some code using some of my UI code.

https://gist.github.com/tnlogy/5024809

Clouds =  [[
precision mediump float;
 
#define CLOUD_COVER        0.75
#define CLOUD_SHARPNESS        0.035
 
uniform float         time;
uniform vec2          resolution;
uniform vec2          direction;
 
float hash( float n )
{
    return fract(sin(n)*43758.5453);
}
 
float noise( in vec2 x )
{
    vec2 p = floor(x);
    vec2 f = fract(x);
        f = f*f*(3.0-2.0*f);
        float n = p.x + p.y*57.0;
        float res = mix(mix( hash(n+  0.0), hash(n+  1.0),f.x), mix( hash(n+ 57.0), hash(n+ 58.0),f.x),f.y);
        return res;
}
 
float fbm( vec2 p )
{
        float f = 0.0;
        f += 0.50000*noise( p ); p = p*2.02;
        f += 0.25000*noise( p ); p = p*2.03;
        f += 0.12500*noise( p ); p = p*2.01;
        f += 0.06250*noise( p ); p = p*2.04;
        f += 0.03125*noise( p );
        return f/0.984375;
}
 
// Entry point
void main( void ) {
    // Wind - Used to animate the clouds
    vec2 wind_vec = direction +vec2(0.001, 0.003 + time);
    
    // Set up domain
    vec2 q = ( gl_FragCoord.xy / resolution.xy );
    vec2 p = -1.0 + 3.0 * q + wind_vec;
    
    // Fix aspect ratio
    p.x *= resolution.x / resolution.y;
     
    // Create noise using fBm
    float f = fbm( 4.0*p );
 
    float cover = CLOUD_COVER;
    float sharpness = CLOUD_SHARPNESS;
    
    float c = f - (1.0 - cover);
    if ( c < 0.0 ) c = 0.0;
    
    f = 1.0 - (pow(sharpness, c));
    gl_FragColor = vec4( f, f, 1.0/f, f );
}
]]