Skip to content

Instantly share code, notes, and snippets.

@andrevenancio
Last active October 29, 2015 23:40
Show Gist options
  • Save andrevenancio/aaf46b51e9ba451b7f28 to your computer and use it in GitHub Desktop.
Save andrevenancio/aaf46b51e9ba451b7f28 to your computer and use it in GitHub Desktop.
Skydome shader for integrating with THREE.ShaderMaterial
# clouds animation based on: https://www.shadertoy.com/view/XsjSRt
THREE.SkyDomeShader = {
uniforms:
offset: { type: 'f', value: -100 }
exponent: { type: 'f', value: 0.64 }
top_color: { type: 'c', value: new THREE.Color(0x99ccff) }
bottom_color: { type: 'c', value: new THREE.Color(0x719cc8) }
time: { type: 'f', value: 0.0 }
noiseTexture: { type: 't', value: null }
offsetScale: { type: 'f', value: -50.0 }
cloudScale: { type: 'f', value: 8.0 }
skyCover: { type: 'f', value: 0.2 }
softness: { type: 'f', value: 0.3 }
brightness: { type: 'f', value: 2.0 }
curlStrain: { type: 'f', value: 3.0 }
vertexShader: [
'varying vec2 v_uv;'
'varying vec3 vWorldPosition;'
'void main() {'
' vec4 worldPosition = modelMatrix * vec4( position, 1. );'
' v_uv = uv;'
' vWorldPosition = worldPosition.xyz;'
' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.);'
'}'
].join '\n'
fragmentShader: [
'const int noiseOctaves = 4;'
'uniform float offsetScale;'
'uniform float cloudScale;'
'uniform float skyCover;'
'uniform float softness;'
'uniform float brightness;'
'uniform float curlStrain;'
'uniform vec3 top_color;'
'uniform vec3 bottom_color;'
'uniform float offset;'
'uniform float exponent;'
'uniform float time;'
'uniform sampler2D noiseTexture;'
'varying vec2 v_uv;'
'varying vec3 vWorldPosition;'
'float saturate(float num) {'
' return clamp(num, 0., 1.);'
'}'
'float noise(vec2 uv) {'
' return texture2D(noiseTexture,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 = 0.78;'
' 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*offsetScale*(1.-mul))*mul;'
' total += mul;'
' uv *= 3.0;'
' uv=rotate(uv);'
' mul *= 0.5;'
' }'
' return f/total;'
'}'
'void main() {'
' vec4 clouds = vec4(1.);'
' vec4 grad = vec4(0.,0.,0.,1.);'
# clouds
' vec2 uv = v_uv/cloudScale;'
' float cover = skyCover;'
' float bright = brightness*(1.8-cover);'
' float color1 = fbm(uv-0.5+time*0.00004*offsetScale);'
' float color2 = fbm(uv-10.5+time*0.00002*offsetScale);'
' float clouds1 = smoothstep(1.-cover,min((1.-cover)+softness*2.,1.),color1);'
' float clouds2 = smoothstep(1.-cover,min((1.-cover)+softness,1.),color2);'
' float cloudsFormComb = saturate(clouds1+clouds2);'
' vec4 skyCol = vec4(0.6,0.8,1.,1.);'
' float cloudCol = saturate(saturate(1.-pow(color1,1.)*0.2)*bright);'
' vec4 clouds1Color = vec4(cloudCol,cloudCol,cloudCol,1.);'
' vec4 clouds2Color = mix(clouds1Color,skyCol,0.25);'
' vec4 cloudColComb = mix(clouds1Color,clouds2Color,saturate(clouds2-clouds1));'
' clouds = mix(skyCol,cloudColComb,cloudsFormComb);'
# gradients
' float h = normalize( vWorldPosition + offset ).y;'
' grad = vec4( mix( bottom_color, top_color, max( pow( max( h , 0.0), exponent ), 0.0 ) ), 1. );'
# just texture
# 'gl_FragColor = texture2D(noiseTexture, v_uv);'
# all together
' gl_FragColor = mix(grad, clouds, pow( max( h , 0.0), exponent ) );'
'}'
].join '\n'
}
@andrevenancio
Copy link
Author

Some random noise texture can be found here.

Example using CoffeeScript:

@CLOCK = new THREE.Clock()

#adding sphere
@skydome = new THREE.Mesh(
            new THREE.SphereBufferGeometry(2500, 32, 16),
            new THREE.ShaderMaterial({
                uniforms: SkyDomeShader.uniforms
                vertexShader: SkyDomeShader.vertexShader
                fragmentShader: SkyDomeShader.fragmentShader
                side: THREE.BackSide
            })
        )
loader = new THREE.TextureLoader();
texture = loader.load( 'someNoiseTexture.png' )
texture.repeat.set(2, 2)
texture.wrapS = texture.wrapT = THREE.RepeatWrapping;

#changing some settings
@skydome.material.uniforms['noiseTexture'].value = texture;
@skydome.material.uniforms['offset'].value = -40
@skydome.material.uniforms['exponent'].value = 0.25
@skydome.material.uniforms['top_color'].value = new THREE.Color 0xffffff
@skydome.material.uniforms['bottom_color'].value = new THREE.Color 0x719cc8
@skydome.material.uniforms['offsetScale'].value = -50
@skydome.material.uniforms['cloudScale'].value = 8.8
@skydome.material.uniforms['skyCover'].value = 0.38
@skydome.material.uniforms['softness'].value = 0.3
@skydome.material.uniforms['brightness'].value = 2

#adding sphere to scene
@scene.add @skydome

#on ur render loop
update: =>
    requestAnimationFrame @update
    @skydome.material.uniforms['time'].value = @CLOCK.getElapsedTime()
    null

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment