Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to achieve this motion blur shader effect?

I tried to create the snow effect like the one on the bottom page of this link http://blog.edankwan.com/post/my-first-christmas-experiment. Everything else works fine But just can't make the motion blur effect work. Any ideas?

the texture sprite used to achieve the motion blur effect

enter image description here

here is the code:

(function(global) {

  var img = 'https://i.imgur.com/hlmsgWA.png'

  var renderer, scene, camera
  var w = 800, h = 320
  var uniforms
  
  var geometry
  var texture, material
  var gui
  var conf = {
    amount: 200,
    speed: 0.5,
    time: 0
  }

  var obj = {
    init: function() {
      renderer = new THREE.WebGLRenderer({
        antialias: true
      })
      renderer.setPixelRatio(window.devicePixelRatio)
      renderer.setSize(w, h)
      camera = new THREE.Camera
      scene = new THREE.Scene()

      geometry = new THREE.BufferGeometry()

      var positions = []
      
      for(var i = 0, l = conf.amount; i < l; i++) {
        positions[i * 3] = Math.random() * 800 - 400
        positions[i * 3 + 1] = i
        positions[i * 3 + 2] = Math.random() * 800
      }
      geometry.addAttribute('position', new THREE.Float32BufferAttribute(positions, 3))

      var vs = document.getElementById('vertexShader').textContent
      var fs = document.getElementById('fragmentShader').textContent

      uniforms = {
        u_amount: {
          type: 'f',
          value: conf.amount
        },
        u_speed: {
          type: 'f',
          value: conf.speed
        },
        u_time: {
          type: 'f',
          value: conf.time
        },
        u_resolution: {
          type: 'vec2',
          value: new THREE.Vector2(w, h)
        },
        u_texture : {
          value: new THREE.TextureLoader().load(img)
        }
      }
      material = new THREE.ShaderMaterial({
        uniforms: uniforms,
        vertexShader: vs,
        fragmentShader: fs,
        transparent: true
      })

      var points = new THREE.Points(geometry, material)
      scene.add(points)

      document.body.appendChild(renderer.domElement)
      this.render()
      this.createGui()
  
    },

    createGui: function() {
      gui = new dat.GUI()
      gui.add(conf, 'speed', -1, 1)
    },

    render: function() {
      requestAnimationFrame(this.render.bind(this))
      uniforms.u_time.value += conf.speed * 0.003
      renderer.render(scene, camera)
    }

  }

  obj.init()

})(window)
<script id="vertexShader" type="x-shader/x-vertex">
    precision highp float;
    vec3 getPosOffset(float ratio, float thershold) {
      return vec3(
        cos((ratio * 80.0 + 10.0) * thershold) * 20.0 * thershold,
        (sin((ratio * 90.0 + 30.0) * thershold) + 1.0) * 5.0 * thershold + mix(500.0, -500.0, ratio / thershold),
        sin((ratio * 70.0 + 20.0) * thershold) * 20.0 * thershold
      );
    }

    uniform vec2 u_resolution;
    uniform float u_amount;
    uniform float u_speed;
    uniform float u_time;
    varying float v_alpha;
    varying float v_rotation;
    varying float v_index;
    void main() {
      float indexRatio = position.y / u_amount;
      float thershold = 0.7 + indexRatio * 0.3;
      float ratio = mod(u_time - indexRatio * 3.0, thershold);
      float prevRatio = mod(u_time - u_speed - indexRatio * 3.0, thershold);
      vec3 offsetPos = getPosOffset(ratio, thershold);
      vec3 prevOffsetPos = getPosOffset(prevRatio, thershold);
      vec3 pos = position;
      pos += offsetPos;

      float perspective = (2000.0 - pos.z) / 2000.0;
      pos.x *= perspective;
      pos.y *= perspective;

      float delta = length(offsetPos.xy - prevOffsetPos.xy);
      float maxDelta = 2.7;
      v_index = floor(pow(clamp(delta, 0.0, maxDelta) / maxDelta, 5.0) * 15.99);  
      v_rotation = atan((offsetPos.x - prevOffsetPos.x) / (offsetPos.y - prevOffsetPos.y));

      pos.x *= 2.0 / u_resolution.x;
      pos.y *= 2.0 / u_resolution.y;
      pos.z = 0.0;
      gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
      gl_PointSize = 24.0 * perspective;
      v_alpha = perspective;
    }
  </script>
  <script id="fragmentShader" type="x-shader/x-fragment">
  
    uniform sampler2D u_texture;
    varying float v_rotation;
    varying float v_index;
    varying float v_alpha;
    void main() {
      vec2 coord =  gl_PointCoord.xy;
      coord = vec2(
        clamp(cos(v_rotation) * (coord.x - 0.5) + sin(v_rotation) * (coord.y - 0.5) + 0.5, 0.0, 1.0),
        clamp(cos(v_rotation) * (coord.y - 0.5) - sin(v_rotation) * (coord.x - 0.5) + 0.5, 0.0, 1.0)
      );
      float index = floor(v_index + 0.5);
      coord.y = - coord.y + 4.0;
      coord.x += (index - floor(index / 4.0) * 4.0);
      coord.y -= floor(index / 4.0);
      coord *= 0.25;
      vec4 color = texture2D(u_texture, coord);
      color.a *= v_alpha;
      gl_FragColor = color;
    }
  </script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/99/three.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.7.3/dat.gui.js"></script>

http://blog.edankwan.com/post/my-first-christmas-experiment.

like image 642
david.x Avatar asked Dec 04 '18 09:12

david.x


People also ask

Can ReShade add motion blur?

er/Shaders/Trails. fx . Object motion blur is not possible with ReShade though, because there is no velocity information, so these are all screenspace.

How do you install a motion blur filter?

Add a motion blurChoose Filter > Blur > Motion Blur and adjust the Angle to match the direction of your subject's motion. Use the Distance setting to control the amount of blur.


1 Answers

In snippet code you treat variable speed differently in your update loop and in vertex shader.

  1. Update: uniforms.u_time.value += conf.speed * 0.003
  2. Shader usage: float prevRatio = mod(u_time - u_speed - indexRatio * 3.0, thershold);

You'll get desired result if you change u_speed to u_speed * 0.003 in shader code (or better move that multiplication to definition in javascript).

Fast way to debug such things - pass your values to output color and check if it is what you expect.

==================

If someone wants to make tails with non-flat curvature - you can store last N points of each particle path. Then you can fully compute trail mesh geometry on CPU and stream it to GPU.

Or another way: you can upload all paths to single Uniform Buffer Object and find right point to fetch with pointId and uv of tail mesh vertex.

like image 62
Ramil Kudashev Avatar answered Oct 26 '22 15:10

Ramil Kudashev