javascript - Three.js GPU 上的 Verlet 布料模拟 : Can't follow my logic for finding bug

标签 javascript three.js webgl shader gpgpu

我在理解我尝试使用 Three.js 和 yomboprime 的 GPUComputationRenderer 实现的逻辑时遇到问题。

( https://github.com/yomboprime/GPGPU-threejs-demos/blob/gh-pages/js/GPUComputationRenderer.js )

我想做一个简单的 Verlet 布料模拟。这是我已经能够实现的逻辑(简短版本):

1) Position-Fragment-Shader:该着色器采用旧的和当前的位置纹理并计算新的位置,如下所示:

vec3 position = texture2D( texturePosition, uv ).xyz;
vec3 oldPosition = texture2D( textureOldPosition, uv ).xyz;
position =  (position * 2.0 - oldPosition + acceleration * delta *delta )

t = checkConstraints(position);
position += t;
gl_FragColor = vec4(position,1);

2) Old-Position-Shader 该着色器仅保存当前位置并为下一步保存。

vec3 position = texture2D( texturePosition, uv ).xyz;
gl_FragColor = vec4(position,1);

这工作正常,但使用该模式,不可能在一个步骤中多次计算约束,因为每个顶点都是单独观察的,并且无法看到其他像素在第一次迭代中所做的位置变化。

我想做的是将约束与 verlet 分开。目前它看起来像这样:

1) 位置着色器(texturePosition)

vec3 position = texture2D( textureConstraints, uv ).xyz;
vec3 oldPosition = texture2D( textureOldPosition, uv ).xyz;

position =  (position * 2.0 - oldPosition + acceleration * delta *delta );
gl_FragColor = vec4(position, 1 );

2)约束着色器(textureConstraints)

vec3 position = texture2D( texturePosition, uv ).xyz;

t = checkConstraints(position);
    position += t;
gl_FragColor = vec4(position,1);

3)旧位置着色器(textureOldPosition)

vec3 position = texture2D( textureConstraints, uv ).xyz;

gl_FragColor = vec4(position,1);

这个逻辑不起作用,即使我根本不计算约束并且只是像以前一样传递值。一旦在位置着色器中添加一些加速度,位置值就会爆炸到无处可去。

我做错了什么?

最佳答案

这个例子不是verlet布料,但我认为基本前提可能对你有帮助。我有一个fiddle它使用 GPUComputationRender 在点云上完成一些 Spring 物理。我认为您可以根据您的需要进行调整。

您需要的是更多信息。您需要对布料的原始形状(就好像它是一 block 平板)以及当前施加在任何这些点上的力(通过重力+风+结构完整性或其他)的固定引用,然后为您提供该点的当前位置。这些对其原始形状的引用点与力的结合将为您的布料带来内存,而不是像以前那样被甩开。

例如,这是我的 Spring 物理着色器,GPUComputationRenderer 使用它来计算可视化中的点位置。在这种情况下,tOffsets 是使云永久内存其原始形状的坐标 - 它们永远不会改变。这是我在程序开始时添加到制服中的 DataTexture。质量、 Spring 常数、重力和阻尼等各种力也保持一致并存在于着色器中。 tPositions 是变化的 vec4 坐标(其中两个坐标记录当前位置,另外两个记录当前速度):

<script id="position_fragment_shader" type="x-shader/x-fragment">   
  // This shader handles only the math to move the various points. Adding the sprites and point opacity comes in the following shader.      
  uniform sampler2D tOffsets; 
  uniform float uTime;

  varying vec2 vUv;

  float hash(float n) { return fract(sin(n) * 1e4); }

  float noise(float x) {
      float i = floor(x);
      float f = fract(x);
      float u = f * f * (3.0 - 2.0 * f);
      return mix(hash(i), hash(i + 1.0), u);
  }

  void main() {
      vec2 uv = gl_FragCoord.xy / resolution.xy;

       float damping = 0.98;

       vec4 nowPos = texture2D( tPositions, uv ).xyzw;
       vec4 offsets = texture2D( tOffsets, uv ).xyzw;
       vec2 velocity = vec2(nowPos.z, nowPos.w);

       float anchorHeight = 100.0;
       float yAnchor = anchorHeight;
       vec2 anchor = vec2( -(uTime * 50.0) + offsets.x, yAnchor + (noise(uTime) * 30.0) );

       // Newton's law: F = M * A
       float mass = 24.0;
       vec2 acceleration = vec2(0.0, 0.0);

       // 1. apply gravity's force:
       vec2 gravity = vec2(0.0, 2.0);
       gravity /= mass;
     acceleration += gravity;


       // 2. apply the spring force
       float restLength = yAnchor - offsets.y;
       float springConstant = 0.2;

       // Vector pointing from anchor to point position
       vec2 springForce = vec2(nowPos.x - anchor.x, nowPos.y - anchor.y);
       // length of the vector
       float distance = length( springForce );
       // stretch is the difference between the current distance and restLength
       float stretch =  distance - restLength;

       // Calculate springForce according to Hooke's Law
       springForce = normalize(springForce);
       springForce *= (springConstant * stretch);

       springForce /= mass;
       acceleration += springForce;

       velocity += acceleration;
       velocity *= damping;
       vec2 newPosition = vec2(nowPos.x - velocity.x, nowPos.y - velocity.y);
       // Write new position out
       gl_FragColor = vec4(newPosition.x, newPosition.y, velocity.x, velocity.y);
   }
</script>

关于javascript - Three.js GPU 上的 Verlet 布料模拟 : Can't follow my logic for finding bug,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48623830/

相关文章:

javascript - 旋转球体纹理 Three.js

javascript - Backbone & Slim PHP - Access-Control-Allow-Headers - 可以获取信息,不能发布信息?

javascript - Threejs相机旋转问题

javascript - 使用 Three.js 和 gsap 的 Mousemove 事件

glsl - 使用GLSL在平面上渲染平滑的引用网格

javascript - Canvas、WebGL 调试功能在 2019 浏览器中不存在?

javascript - 将存储 RGBA 的 Uint8Array 数组保存到 .png 文件

javascript - 如何让固定标题在滚动 html 表中工作(当标题有多行时)

javascript - 选择要序列化的属性

javascript - 具有类似行为的第二个元素上的 JS 单击事件不会触发