Gabriel Nazoa Gabriel Nazoa - 5 months ago 143x
Javascript Question

Export from Shadertoy to Three.js

I am making my first steps coding. I made some courses on internet, then I played with some three.js experiments, and now I would like to continue learning experimenting with Shaders.

I found and it's really amazing! There are a lot of difference experiments with incredible effects. I am trying to use one of these shaders in Three.js but is not so easy.

The Shaders are already written, it's true. But I don't know what to do with that, I don't know how I can use it.

Because it's not only copy and paste the code. There is a relation that I have to write to can apply some of these amazing effects to a Three.js geometry. I have to use uniforms, and I don't know how I can make to know which uniforms I can use, and how can I use them.

I started see the tutorials in Shadertoy and some articles on Internet and it looks like something really abstract. I think that I should study a lot of maths before start understanding that language.

Do you have some recommendation to start?

Maybe is something simpler than I think and I can just copy, paste, and experiment with the code on my HTML document?


Shadertoy is a relatively complex program. It's got audio input into shaders, video input into shaders, audio data generation from shaders, various kinds of textures including both 2d and cubemaps. Supporting all those features is not a small amount of work.

That said a basic shader can be used pretty easily, see example below. But shadertoy shaders are not really designed to be used as materials on meshes in three.js.

If you want to understand why and how WebGL works see

var $ = document.querySelector.bind(document);

var camera = new THREE.Camera();
camera.position.z = 1;

var scene = new THREE.Scene();

var geometry = new THREE.BufferGeometry();
var vertices = new Float32Array([
  -1, -1, 
   1, -1, 
  -1,  1, 
  -1,  1, 
   1, -1, 
   1,  1, 
geometry.addAttribute( 'position', new THREE.BufferAttribute( vertices, 2 ) );

var uniforms = {
  iGlobalTime: { type: "f", value: 1.0 },
  iResolution: { type: "v3", value: new THREE.Vector3() },

var material = new THREE.RawShaderMaterial({
  uniforms: uniforms,
  vertexShader: $('#vs').text,
  fragmentShader: $('#shadertoy-boilerplate').text.replace('${usershader}', $('#fs').text),

var mesh = new THREE.Mesh(geometry, material);

var renderer = new THREE.WebGLRenderer();


function resize(force) {
  var canvas = renderer.domElement;
  var dpr    = 1; //window.devicePixelRatio;  // make 1 or less if too slow
  var width  = canvas.clientWidth  * dpr;
  var height = canvas.clientHeight * dpr;
  if (force || width != canvas.width || height != canvas.height) {
    renderer.setSize( width, height, false );
    uniforms.iResolution.value.x = renderer.domElement.width;
    uniforms.iResolution.value.y = renderer.domElement.height;

function render(time) {
  uniforms.iGlobalTime.value = time * 0.001;
  renderer.render(scene, camera);
canvas {
  border: 1px solid black;
<script id="vs" type="not-js">
attribute vec4 position;
void main()	{
  gl_Position = position;
<script id="fs" type="not-js">
// FROM:
#define SHAPE length(z.yz)
//#define SHAPE length(
//#define SHAPE length(z.yz-z.xx)
#define HIGH_QUAL
#ifdef HIGH_QUAL
#define MARCH_STEPS 199
#define MARCH_STEPS 99
float k=7.0+3.0*sin(iGlobalTime*0.15);
vec3 mcol=vec3(0.0);
void AbsBox(inout vec4 z){//abs box by kali; 
void Bulb(inout vec4 z, in vec4 c){//mandelBulb by twinbee
 float r = length(;
 float zo = asin(z.z / r) * k + iGlobalTime*0.15;
 float zi = atan(z.y, z.x) * 7.0;
 z=pow(r, k-1.0)*vec4(r*vec3(cos(zo)*vec2(cos(zi),sin(zi)),sin(zo)),z.w*k)+c; 
float DE(vec3 p){
  vec4 c = vec4(p,1.0),z = c;
  float r0=(length(;;
  for(int i=0;i<7;i++)AbsBox(z);
  float r=SHAPE;
  return 0.5 * max((r-1.0) / z.w,-r0);

vec3 sky(vec3 rd, vec3 L){//modified bananaft's & public_int_i's code
  float d=0.4*dot(rd,L)+0.6;
  //return vec3(d);
  float y=max(0.,L.y),sun=max(1.-(1.+10.*y+rd.y)*length(rd-L),0.)
  return d*mix(vec3(0.3984,0.5117,0.7305),vec3(0.7031,0.4687,0.1055),sun)
float rnd;
void randomize(in vec2 p){rnd=fract(float(iFrame)+sin(dot(p,vec2(13.3145,117.7391)))*42317.7654321);}

float ShadAO(in vec3 ro, in vec3 rd){
 float t=0.0,s=1.0,d,mn=0.01;
 for(int i=0;i<12;i++){
 return s;
vec3 scene(vec3 ro, vec3 rd){
  vec3 L=normalize(vec3(0.4,0.025,0.5));
  vec3 bcol=sky(rd,L);
  vec4 col=vec4(0.0);//color accumulator
  float t=DE(ro)*rnd,d,od=1.0,px=1.0/iResolution.x;
  for(int i=0;i<MARCH_STEPS;i++){
      float dif=clamp(1.0-d/od,0.2,1.0);
      vec3 scol=mcol*dif*(1.3-0.3*t);
#ifdef HIGH_QUAL
      	vec2 s=vec2(DE(ro+d*4.0*L),DE(ro+d*16.0*L));
      float alpha=(1.0-col.w)*clamp(1.0-d/(px*t),0.0,1.0);
  return col.rgb;
mat3 lookat(vec3 fw){
 fw=normalize(fw);vec3 rt=normalize(cross(fw,vec3(0.0,1.0,0.0)));return mat3(rt,cross(rt,fw),fw);
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
   float tim=iGlobalTime*0.3,r=2.0+cos(tim*0.7);
   vec2 uv=(fragCoord-0.5*iResolution.xy)/iResolution.x;
   vec3 ro=vec3(sin(tim)*r,sin(tim*0.4),cos(tim)*r);
   vec3 rd=lookat(-ro)*normalize(vec3(uv,1.0));
<!-- // FROM -->
<script id="shadertoy-boilerplate" type="not-js">#extension GL_OES_standard_derivatives : enable
//#extension GL_EXT_shader_texture_lod : enable
#ifdef GL_ES
precision highp float;
uniform vec3      iResolution;
uniform float     iGlobalTime;
uniform float     iChannelTime[4];
uniform vec4      iMouse;
uniform vec4      iDate;
uniform float     iSampleRate;
uniform vec3      iChannelResolution[4];
uniform int       iFrame;
uniform float     iTimeDelta;
uniform float     iFrameRate;
struct Channel
    vec3  resolution;
    float time;
uniform Channel iChannel[4];
uniform sampler2D iChannel0;
uniform sampler2D iChannel1;
uniform sampler2D iChannel2;
uniform sampler2D iChannel3;
void mainImage( out vec4 c,  in vec2 f );


void main( void ){
  vec4 color = vec4(0.0,0.0,0.0,1.0);
  mainImage( color, gl_FragCoord.xy );
  color.w = 1.0;
  gl_FragColor = color;
<script src=""></script>