のぐそんブログ

暗いおじさんがシコシコ書くブログです。

THREE.jsでフラグメントシェーダを使ってみるの基礎基礎メモ1

フラグメントシェーダを使って色を変更してみたいと思います。

基礎の復習

ベースとなるコードです。

js
window.onload = () => {
  let windowWidth = window.innerWidth;
  let windowHeight = window.innerHeight;

  // rendererの作成
  let renderer = new THREE.WebGLRenderer();
  
  // canvasをbodyに追加
  document.body.appendChild(renderer.domElement);

  // canvasをリサイズ
  renderer.setSize(windowWidth, windowHeight);

  // scene作成
  let scene = new THREE.Scene();
  
  // camera作成
  let camera = new THREE.PerspectiveCamera(75, windowWidth / windowHeight, 0.1, 1000);
  camera.position.z = 100;

  // Geometry作成
  let geometry = new THREE.PlaneBufferGeometry(100, 100);
  
  // Material作成
  let material = new THREE.ShaderMaterial({
    vertexShader: myVert,
    fragmentShader: myFrag,
    uniforms:{
      uColor: {type: "c", value: new THREE.Color(0xFF0000)}
    }
  });
  
  // Mesh作成
  let mesh = new THREE.Mesh(geometry,material);

  // Meshをシーンに追加
  scene.add(mesh);

  // draw
  renderer.render(scene, camera);
};
vert(頂点シェーダー)
void main() {
  gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}
frag(フラグメントシェーダー)
precision mediump float;

 uniform vec3 uColor;

void main(){    
  gl_FragColor =vec4(uColor, 1.0);
}
結果

Kobito.yP7wXn.png

マウス座標で色を変えてみる

マウス座標を取得して色を変更してみたいと思います。 requestAnimationFrameでuniformsを更新していきます。

js
window.onload = () => {
  let windowWidth = window.innerWidth;
  let windowHeight = window.innerHeight;
  let mouse = new THREE.Vector2(0.0, 0.0);

  // rendererの作成
  let renderer = new THREE.WebGLRenderer();
  
  // canvasをbodyに追加
  document.body.appendChild(renderer.domElement);

  // canvasをリサイズ
  renderer.setSize(windowWidth, windowHeight);

  // scene作成
  let scene = new THREE.Scene();
  // camera作成
  let camera = new THREE.PerspectiveCamera(75, windowWidth / windowHeight, 0.1, 1000);
  camera.position.z = 100;

  // Geometry作成
  let geometry = new THREE.PlaneBufferGeometry(100, 100);
  
  // Material作成
  let material = new THREE.ShaderMaterial({
    vertexShader: myVert,
    fragmentShader: myFrag,
    uniforms: {
        uMouse: {
        type: "v2",
        value: mouse
      },
    }
  });
  
  // Mesh作成
  let mesh = new THREE.Mesh(geometry, material);

  // Meshをシーンに追加
  scene.add(mesh);

  //マウス座標を取得
  renderer.domElement.addEventListener('mousemove', function (e) {
    mouse = new THREE.Vector2(
      e.clientX / windowWidth,
      e.clientY / windowHeight);
  }, false);

  // draw
  render();

  //描画
  function render() {
    renderer.render(scene, camera);
    
    material.uniforms.uMouse.value = mouse;

    // animation
    requestAnimationFrame(render);
  }

};
frag(フラグメントシェーダー)
precision mediump float;

 uniform vec2 uMouse;

void main(){
  // テクスチャ座標をカラーに出力
  gl_FragColor =vec4(uMouse.x,uMouse.y,0.0, 1.0);
}
結果

マウスを動かすと色が変わります。

See the Pen vJqRqb by nogson (@satofaction) on CodePen.

経過時間で色を変えてみる

window.onload = () => {
  let windowWidth = window.innerWidth;
  let windowHeight = window.innerHeight;
  let clock = new THREE.Clock();
  let time = 0.0;

  // rendererの作成
  let renderer = new THREE.WebGLRenderer();
  
  // canvasをbodyに追加
  document.body.appendChild(renderer.domElement);

  // canvasをリサイズ
  renderer.setSize(windowWidth, windowHeight);

  // scene作成
  let scene = new THREE.Scene();
  // camera作成
  let camera = new THREE.PerspectiveCamera(75, windowWidth / windowHeight, 0.1, 1000);
  camera.position.z = 100;

  // Geometry作成
  let geometry = new THREE.PlaneBufferGeometry(100, 100);
  
  // Material作成
  let material = new THREE.ShaderMaterial({
    vertexShader: myVert,
    fragmentShader: myFrag,
    uniforms: {
        uTime: {
        type: "f",
        value: time
      },
    }
  });
  
  // Mesh作成
  let mesh = new THREE.Mesh(geometry, material);

  // Meshをシーンに追加
  scene.add(mesh);

  //マウス座標を取得
  renderer.domElement.addEventListener('mousemove', function (e) {
    mouse = new THREE.Vector2(
      e.clientX / windowWidth,
      e.clientY / windowHeight);
  }, false);

  // draw
  render();

  //描画
  function render() {
    renderer.render(scene, camera);
    
    //経過時間を取得
    time  = clock.getElapsedTime();
    material.uniforms.uTime.value = time;

    // animation
    requestAnimationFrame(render);
  }

};
frag(フラグメントシェーダー)
precision mediump float;
 uniform float uTime;

void main(){
  float t = abs(cos(uTime));
  gl_FragColor =vec4(t,t,t, 1.0);
}
結果

See the Pen YxovGW by nogson (@satofaction) on CodePen.

まとめ

すごい基礎的な部分なのですが、なかなか上手くいきません。 とにかく色々やってみるしかありません。