Webgl:在 GPGPU 中使用鼠标偏移维护粒子位置

问题描述 投票:0回答:1

我有一个简单的粒子方块,我想随着鼠标的移动而移动,映射到-1到1,这样它的左下角就会粘在光标上。

这在顶点着色中相当容易,您只需将 mouse.xy 添加到 pos.xy 即可。但我想使用 GPGPU 方法来保存粒子状态并用它做一些事情。

我无法通过鼠标移动使整个方块移动并停止。如何修改我的着色器代码,以便使整个方块移动与鼠标移动同步,如下面的视频所示?

仅在顶点着色器中实现预期行为无需 gpgpuenter image description here



但是使用gpgpu,这就是我管理的: My gpgpu

这是我的着色器代码:

    void main() {
        vec2 uv = vUv;
        vec4 pos = texture2D( tMap, vUv );
        
        vec2 mouse = uMouse;
        vec2 targetPos = mouse + pos.xy;
        float targetLen = length( mouse );
        
       float len = distance( mouse.xy, pos.xy ); // this needs to shrink for every particle together
    
        pos.xy += ( targetPos - pos.xy ) * .01 * len;
        
        gl_FragColor = pos;
    }

我知道我的方法是错误的,因为每一帧,

pos.xy
都会在纹理中被重写,并且我们不断向其中添加 mouse.xy。但我可以通过什么方式真正修复偏移量,以便
distance
函数不断缩小每个粒子的速度呢?

小提琴

vector game-physics gpgpu particles compute-shader
1个回答
0
投票

我修改了你的fiddle代码(https://jsfiddle.net/zn8sm5gx/),你现在可以看看它是否符合你的期望。


您真正想要做的是计算第

n-1
帧和第
n
帧处鼠标位置之间的增量,然后将此增量添加到着色器中的
pos
,例如:

precision highp float;
uniform float uTime;

uniform sampler2D tMap;
uniform vec2 uMouse;
uniform vec2 uLastMouse;

varying vec2 vUv;


void main() {
    vec4 pos = texture2D( tMap, vUv );
    
    vec2 moveDelta = uMouse - uLastMouse;
    pos.xy += moveDelta;
    
    gl_FragColor = pos;
}

只需将最后一帧的鼠标位置记录在一个统一变量中,并在前帧的基础上更新它。您可以通过解耦

mousemove
事件的处理并设置渲染状态来实现此目的:

  // EVENTS
  #events(){
  
    this.currentMouse = new Vec2();
    this.lastMouse = new Vec2();
    this.mouseMoved = false;
    
    document.addEventListener('mousemove', ( e ) => {
  
      this.progress = 0;
      this.mouseMoved = true;
      
      this.lastMouse = this.currentMouse.clone();
  
      this.currentMouse.x = ( e.pageX / this.gl.renderer.width ) * 2 - 1;
      this.currentMouse.y = ( e.pageY / this.gl.renderer.height ) * 2 - 1;
    });
  
    }
  
  // ANIMATE
  #animate(){
    
    // UPDATING VALUES
    // this.speed = (t * 0.000007) % 1;
    this.speed += .007;

    if (this.mouseMoved) {
      this.positionBuffer.passes[0].uniforms.uMouse.value = new Vec2( this.currentMouse.x, -this.currentMouse.y );
      this.positionBuffer.passes[0].uniforms.uLastMouse.value = new Vec2( this.lastMouse.x, -this.lastMouse.y );
      this.mouseMoved = false;
    } else {
      this.positionBuffer.passes[0].uniforms.uLastMouse.value = new Vec2( this.currentMouse.x, -this.currentMouse.y );
    }

    this.sourceMesh.program.uniforms.uTime.value = this.speed;
    this.positionBuffer.passes[0].uniforms.uTime.value = this.speed;
    this.positionBuffer.render();

    this.renderer.render({ scene: this.sourceMesh.scene, camera: this.camera });

    requestAnimationFrame( this.#animate.bind(this) );

  }

这里

#events
重点关注更新“最后更改的鼠标位置”,并使用布尔值通知渲染例程此更改是否发生在最后一帧。

© www.soinside.com 2019 - 2024. All rights reserved.