Skip to content

Instantly share code, notes, and snippets.

@scummtomte
Last active February 10, 2021 12:48
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scummtomte/523f2e4c403c083d6983f8865ca24bc7 to your computer and use it in GitHub Desktop.
Save scummtomte/523f2e4c403c083d6983f8865ca24bc7 to your computer and use it in GitHub Desktop.
porting shadertoy to three.js
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/85/three.min.js"></script>
</head>
<body>
<img id="image" src="crib.jpg">
<script id="fragShader" type="shader-code">
uniform vec2 res;
uniform sampler2D bufferTexture;
uniform sampler2D imageTexture;
uniform float time;
void main() {
vec2 uv = gl_FragCoord.xy / res;
gl_FragColor = texture2D(imageTexture, uv);
if (gl_FragColor == texture2D(imageTexture, uv)) {
vec2 vUv = gl_FragCoord.xy / res;
vec2 texel = 6. / res;
vec3 uv = texture2D(bufferTexture, vUv).xyz;
float gt = mod(time*vUv.x*vUv.y, 1.0*6.1415)*4.0;
vec2 d1 = vec2(uv.x*vec2(texel.x*cos(gt*uv.z), texel.y*sin(gt*uv.y)));
vec2 d2 = vec2(uv.y*vec2(texel.x*cos(gt*uv.x), texel.y*sin(gt*uv.y)));
vec2 d3 = vec2(uv.z*vec2(texel.x*cos(gt*uv.y), texel.y*sin(gt*uv.y)));
float bright = (uv.x+uv.y+uv.z)/1.9+1.1;
float r = texture2D(bufferTexture, vUv+d1*bright).x;
float g = texture2D(bufferTexture, vUv+d2*bright).y;
float b = texture2D(bufferTexture, vUv+d3*bright).z;
vec3 uvMix = mix(uv, vec3(r,g,b), 1.29);
vec3 orig = texture2D(imageTexture, vUv).xyz;
gl_FragColor = vec4(mix(uvMix, orig, 0.017), 1.0);
}
}
</script>
<script>
var scene;
var camera;
var renderer;
var bufferScene;
var textureA;
var textureB;
var bufferMaterial;
var plane;
var bufferObject;
var finalMaterial;
var quad;
var image;
var imageTexture;
function sceneSetup(){
scene = new THREE.Scene();
var width = window.innerWidth;
var height = window.innerHeight;
camera = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2, 1, 1000 );
camera.position.z = 2;
renderer = new THREE.WebGLRenderer();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
}
function imageTextureSetup() {
image = document.getElementById( 'image' );
imageTexture = new THREE.Texture(image),
imageTexture.minFilter = THREE.LinearFilter;
imageTexture.magFilter = THREE.LinearFilter;
imageTexture.format = THREE.RGBFormat;
}
function bufferTextureSetup(){
//Create buffer scene
bufferScene = new THREE.Scene();
//Create 2 buffer textures
textureA = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter});
textureB = new THREE.WebGLRenderTarget( window.innerWidth, window.innerHeight, { minFilter: THREE.LinearFilter, magFilter: THREE.NearestFilter} );
//Pass textureA to shader
bufferMaterial = new THREE.ShaderMaterial( {
uniforms: {
bufferTexture: { type: "t", value: textureA.texture },
res : {type: 'v2',value:new THREE.Vector2(window.innerWidth,window.innerHeight)},
//Keeps the resolution
imageTexture: {type: "t", value: imageTexture },
time: {type:"f",value:Math.random()*Math.PI*2+Math.PI}
},
fragmentShader: document.getElementById( 'fragShader' ).innerHTML
} );
plane = new THREE.PlaneBufferGeometry( window.innerWidth, window.innerHeight );
bufferObject = new THREE.Mesh( plane, bufferMaterial );
bufferScene.add(bufferObject);
//Draw textureB to screen
finalMaterial = new THREE.MeshBasicMaterial({map: textureB});
quad = new THREE.Mesh( plane, finalMaterial );
scene.add(quad);
}
//Initialize the Threejs scene
sceneSetup();
//Setup the frame buffer/texture we're going to be rendering to instead of the screen
imageTextureSetup();
bufferTextureSetup();
function render() {
requestAnimationFrame( render );
//Draw to textureB
renderer.render(bufferScene,camera,textureB,true);
//Swap textureA and B
var t = textureA;
textureA = textureB;
textureB = t;
quad.material.map = textureB.texture;
bufferMaterial.uniforms.bufferTexture.value = textureA.texture;
//Update time
bufferMaterial.uniforms.time.value += 0.01;
//Finally, draw to the screen
renderer.render( scene, camera );
}
render();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment