Jason Thompson
Jason Thompson

Reputation: 41

Shadertoy in THREE.js

I'm currently trying to use translate this shader onto a canvas using THREE.js : https://www.shadertoy.com/view/4sjXRG. This is the function I'm using, it works for more simple Shaders. I assume I need to maybe save the floats as uniforms but I'm kind of lost on this one. Has anyone done something along these lines and knows what the problem could be? I've been using this guide: https://threejsfundamentals.org/threejs/lessons/threejs-shadertoy.html

  const canvas = document.querySelector('#background');
  const renderer = new THREE.WebGLRenderer({canvas});
  renderer.autoClearColor = false;

  const camera = new THREE.OrthographicCamera(
    -1, // left
     1, // right
     1, // top
    -1, // bottom
    -1, // near,
     1, // far
  );
  const scene = new THREE.Scene();
  const plane = new THREE.PlaneBufferGeometry(2, 2);

  const fragmentShader = `
    #include <common>

    uniform vec3 iResolution;
    uniform float iTime;


float ltime;

float noise(vec2 p)
{
  return sin(p.x*10.) * sin(p.y*(3. + sin(ltime/11.))) + .2; 
}

mat2 rotate(float angle)
{
  return mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
}


float fbm(vec2 p)
{
  p *= 1.1;
  float f = 0.;
  float amp = .5;
  for( int i = 0; i < 3; i++) {
    mat2 modify = rotate(ltime/50. * float(i*i));
    f += amp*noise(p);
    p = modify * p;
    p *= 2.;
    amp /= 2.2;
  }
  return f;
}

float pattern(vec2 p, out vec2 q, out vec2 r) {
  q = vec2( fbm(p + vec2(1.)),
        fbm(rotate(.1*ltime)*p + vec2(3.)));
  r = vec2( fbm(rotate(.2)*q + vec2(0.)),
        fbm(q + vec2(0.)));
  return fbm(p + 1.*r);

}

vec3 hsv2rgb(vec3 c)
{
    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
  vec2 p = fragCoord.xy / iResolution.xy;
  ltime = iTime;
  float ctime = iTime + fbm(p/8.)*40.;
  float ftime = fract(ctime/6.);
  ltime = floor(ctime/6.) + (1.-cos(ftime*3.1415)/2.);
  ltime = ltime*6.;
  vec2 q;
  vec2 r;
  float f = pattern(p, q, r);
  vec3 col = hsv2rgb(vec3(q.x/10. + ltime/100. + .4, abs(r.y)*3. + .1, r.x + f));
  float vig = 1. - pow(4.*(p.x - .5)*(p.x - .5), 10.);
  vig *= 1. - pow(4.*(p.y - .5)*(p.y - .5), 10.);
  fragColor = vec4(col*vig,1.);
}


    void main() {
      mainImage(gl_FragColor, gl_FragCoord.xy);
      }
    `;

    const uniforms = {
      iTime: { value: 0 },
      iResolution:  { value: new THREE.Vector3() },
    };

  const material = new THREE.ShaderMaterial({
      fragmentShader,
      uniforms,
  });
  scene.add(new THREE.Mesh(plane, material));

  function resizeRendererToDisplaySize(renderer) {
    const canvas = renderer.domElement;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    const needResize = canvas.width !== width || canvas.height !== height;
    if (needResize) {
      renderer.setSize(width, height, false);
    }
    return needResize;
  }

  function render(time) {

    time *= 0.001; //convert to seconds

    resizeRendererToDisplaySize(renderer);

    const canvas = renderer.domElement;
    uniforms.iResolution.value.set(canvas.width, canvas.heigth, 1);
    uniforms.iTime.value = time;

    renderer.render(scene, camera);

    requestAnimationFrame(render);
  }

  requestAnimationFrame(render);
}

main();```


Upvotes: 4

Views: 1056

Answers (1)

Rabbid76
Rabbid76

Reputation: 211277

The uniform iResolution is not proper set. It's a simple typo. canvas.height rather than canvas.heigth:

uniforms.iResolution.value.set(canvas.width, canvas.heigth, 1);

uniforms.iResolution.value.set(canvas.width, canvas.height, 1);

const fragmentShader = `
#include <common>

uniform vec3 iResolution;
uniform float iTime;

float ltime;

float noise(vec2 p)
{
  return sin(p.x*10.) * sin(p.y*(3. + sin(ltime/11.))) + .2; 
}

mat2 rotate(float angle)
{
  return mat2(cos(angle), -sin(angle), sin(angle), cos(angle));
}


float fbm(vec2 p)
{
  p *= 1.1;
  float f = 0.;
  float amp = .5;
  for( int i = 0; i < 3; i++) {
    mat2 modify = rotate(iTime/50. * float(i*i));
    f += amp*noise(p);
    p = modify * p;
    p *= 2.;
    amp /= 2.2;
  }
  return f;
}

float pattern(vec2 p, out vec2 q, out vec2 r) {
  q = vec2( fbm(p + vec2(1.)),
	    fbm(rotate(.1*iTime)*p + vec2(3.)));
  r = vec2( fbm(rotate(.2)*q + vec2(0.)),
	    fbm(q + vec2(0.)));
  return fbm(p + 1.*r);

}

vec3 hsv2rgb(vec3 c)
{
    vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
    vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
    return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}

void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
  vec2 p = fragCoord.xy / iResolution.xy;
  ltime = iTime;
  float ctime = iTime + fbm(p/8.)*40.;
  float ftime = fract(ctime/6.);
  ltime = floor(ctime/6.) + (1.-cos(ftime*3.1415)/2.);
  ltime = ltime*6.;
  vec2 q;
  vec2 r;
  float f = pattern(p, q, r);
  vec3 col = hsv2rgb(vec3(q.x/10. + ltime/100. + .4, abs(r.y)*3. + .1, r.x + f));
  float vig = 1. - pow(4.*(p.x - .5)*(p.x - .5), 10.);
  vig *= 1. - pow(4.*(p.y - .5)*(p.y - .5), 10.);
  fragColor = vec4(col*vig,1.);
}

void main() {
    mainImage(gl_FragColor, gl_FragCoord.xy);
}
`;

function main() {
    const canvas = document.querySelector('#background');
    const renderer = new THREE.WebGLRenderer({canvas});
    renderer.autoClearColor = false;

    let camera = new THREE.OrthographicCamera(
       -1, // left
        1, // right
        1, // top
       -1, // bottom
       -1, // near,
        1, // far
    );
    camera.position.z = 1;

    const scene = new THREE.Scene();
    const plane = new THREE.PlaneBufferGeometry(2, 2);

    const uniforms = {
        iTime: { value: 0 },
        iResolution:  { value: new THREE.Vector3() },
    };

    const material = new THREE.ShaderMaterial({
        fragmentShader,
        uniforms,
    });
     scene.add(new THREE.Mesh(plane, material));

    function resizeRendererToDisplaySize(renderer) {
        const canvas = renderer.domElement;
        const width = canvas.clientWidth;
        const height = canvas.clientHeight;
        const needResize = canvas.width !== width || canvas.height !== height;
        if (needResize) {
        renderer.setSize(width, height, false);
        }
        return needResize;
    }

    function render(time) {

        time *= 0.001; //convert to seconds

        resizeRendererToDisplaySize(renderer);

        const canvas = renderer.domElement;
        uniforms.iResolution.value.set(canvas.width, canvas.height, 1);
        uniforms.iTime.value = time;

        renderer.render(scene, camera);

        requestAnimationFrame(render);
    }

    requestAnimationFrame(render);
}

main();
#background{
	background : black;
	color : white;
  	margin: auto;
	width : 500px;
	height : 500px;
}
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/three.js"></script>
<div><canvas id="background"></canvas></div>

Upvotes: 2

Related Questions