Skip to content

Instantly share code, notes, and snippets.

@jhnsnc
Created September 16, 2021 05:25
Show Gist options
  • Save jhnsnc/7d30c9f44aba8e8d9e4cedef52961e2c to your computer and use it in GitHub Desktop.
Save jhnsnc/7d30c9f44aba8e8d9e4cedef52961e2c to your computer and use it in GitHub Desktop.
<script id="vertexShader" type="x-shader/x-vertex">
varying vec2 vUv;
void main()
{
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
</script>
<script id="fragmentShader" type="x-shader/x-fragment">
uniform float time;
uniform vec2 resolution;
varying vec2 vUv;
#define PI 3.14159265359
#define T (time*0.5)
// Sineless hash - Dave Hoskins ( https://www.shadertoy.com/view/4djSRW )
// License: CC BY-SA v4.0 (this function only)
float hash11(float p)
{
const float HASHSCALE1 = .1031;
vec3 p3 = fract(vec3(p) * HASHSCALE1);
p3 += dot(p3, p3.yzx + 19.19);
return fract((p3.x + p3.y) * p3.z);
}
// cf. http://www.iquilezles.org/www/articles/palettes/palettes.htm
vec3 cosPal(float t)
{
// return clamp(vec3(0.5) + vec3(0.5)*cos( 2.*PI*(vec3(1.0)*t+vec3(0.00,0.33,0.67)) ),0.,1.);
// return clamp(vec3(0.5) + vec3(0.5)*cos( 2.*PI*(vec3(1.0)*t+vec3(0.00,0.10,0.20)) ),0.,1.);
return clamp(vec3(0.5) + vec3(0.5)*cos( 2.*PI*(vec3(1.0)*t+vec3(0.30,0.20,0.20)) ),0.,1.);
// return clamp(vec3(0.5) + vec3(0.5)*cos( 2.*PI*(vec3(1.0,1.0,0.5)*t+vec3(0.80,0.90,0.30)) ),0.,1.);
// return clamp(vec3(0.5) + vec3(0.5)*cos( 2.*PI*(vec3(1.0,0.7,0.4)*t+vec3(0.00,0.15,0.20)) ),0.,1.);
// return clamp(vec3(0.5) + vec3(0.5)*cos( 2.*PI*(vec3(2.,1.,1.)*t+vec3(0.50,0.20,0.25)) ),0.,1.);
}
void calcPattern(out float value, out vec3 color, vec2 p, float t) {
value = 0.0;
color = vec3(0.0);
// repeat for each octave
for (float o = 1.0; o <= 8.0; o += 1.) {
float r = hash11(1.234 * o);
float expo = pow(2.5,o);
float phaseOffset = r * PI;
float phaseSpeed = 0.5 + (o * 0.25) * (0.5 + r);
float amplitude = 1.5 / expo; // sum[1,8] of 1/2.5^x ~= .66, so mult by 1.5
float contribution = sin( phaseOffset + 0.5 * expo * ( phaseSpeed * (t + 0.15*o*sin(t+2.*PI*r)) + (p.x + p.y) ) );
value += amplitude * (contribution);
}
value = 0.5 + 0.5 * value; // normalize sine range
color = cosPal(value);
}
void main( void ) {
float value;
vec3 gradColor;
calcPattern(value, gradColor, vec2(-10.*vUv.x, 4.*vUv.y), T);
float circFade = length(vUv - vec2(0.5, 0.5)) * 1.75;
circFade = max(0.0, 1.0 - (circFade * circFade));
gl_FragColor = vec4((1.0 + 0.15 * value) * gradColor * circFade, 1.0);
}
</script>
<div id="container"></div>
<div id="info">Pastel Rays - GLSL shader - with <a href="https://threejs.org" target="_blank">three.js</a>
</div>
<div id="controls">
<label for="resolution">resolution: </label>
<select id="resolution" value="2">
<option value="0.5">0.5x</option>
<option value="1">1x</option>
<option value="2" selected>2x</option>
<option value="4">4x</option>
<option value="8">8x</option>
</select>
</div>
var lastUpdate;
var container;
var camera, scene, renderer;
var uniforms;
function init(showStats) {
// stats
if (showStats) {
var stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0';
stats.domElement.style.top = '0';
document.body.appendChild(stats.domElement);
requestAnimationFrame(function updateStats(){
stats.update();
requestAnimationFrame(updateStats);
});
}
// basic setup
container = document.getElementById( 'container' );
camera = new THREE.Camera();
camera.position.z = 1;
scene = new THREE.Scene();
var geometry = new THREE.PlaneBufferGeometry( 2, 2 );
// shader stuff
uniforms = {
time: { type: "f", value: 1.0 },
resolution: { type: "v2", value: new THREE.Vector2() }
};
var material = new THREE.ShaderMaterial( {
uniforms: uniforms,
vertexShader: document.getElementById( 'vertexShader' ).textContent,
fragmentShader: document.getElementById( 'fragmentShader' ).textContent
} );
lastUpdate = new Date().getTime();
// put it together for rendering
var mesh = new THREE.Mesh( geometry, material );
scene.add( mesh );
renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( window.devicePixelRatio / 2 );
container.appendChild( renderer.domElement );
// event listeners
onWindowResize();
window.addEventListener( 'resize', onWindowResize, false);
document.getElementById('resolution').addEventListener('change', onResolutionChange, false);
}
// events
function onWindowResize(evt) {
renderer.setSize( window.innerWidth, window.innerHeight );
uniforms.resolution.value.x = renderer.domElement.width;
uniforms.resolution.value.y = renderer.domElement.height;
}
function onResolutionChange(evt) {
var newResolutionScale = parseFloat(evt.target.value);
renderer.setPixelRatio( window.devicePixelRatio / newResolutionScale );
uniforms.resolution.value.x = renderer.domElement.width;
uniforms.resolution.value.y = renderer.domElement.height;
}
function animate() {
var currentTime = new Date().getTime()
var timeSinceLastUpdate = currentTime - lastUpdate;
lastUpdate = currentTime;
requestAnimationFrame( animate );
render(timeSinceLastUpdate);
}
function render(timeDelta) {
uniforms.time.value += (timeDelta ? timeDelta / 1000 : 0.05);
renderer.render( scene, camera );
}
// boot
init(false);
animate();
body {
color: #ffffff;
font-family: Monospace;
font-size: 13px;
text-align: center;
font-weight: bold;
background-color: #000;
margin: 0px;
overflow: hidden;
}
#info, #controls {
position: absolute;
width: 100%;
padding: 5px;
background: rgba(#000,0.4);
}
#info { top: 0; }
#controls { bottom: 0; }
a {
color: #ffffff;
transition: 150ms all;
&:hover, &:focus {
color: #ffc107;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment