【问题标题】:WebGL / Three.js - Particles colored by texture flicker erratically while moving cameraWebGL / Three.js - 纹理着色的粒子在移动相机时不规则闪烁
【发布时间】:2015-02-09 10:56:23
【问题描述】:

这是一个jsfiddle 我放在一起显示粒子在使用纹理着色和相机移动时“闪烁”的问题。

更新:粒子上不应发生动画或运动。如果当您在视口上单击并拖动并且粒子闪烁或改变颜色时,您就会看到问题。这是我在使用 mac OS 10.9 和 windows 7 的 firefox 和 chrome 上测试并看到的问题。

粒子不会以任何方式重叠或剪裁。如果粒子使用常规着色器进行动画处理,则不会发生闪烁。只有当粒子使用纹理着色(在本例中使用 THREE.WebGLRenderTarget)时,闪烁才会明显。这样做是为了捕获以前的帧并将它们存储在缓冲区中(然后可以以 jsfiddle 示例中未显示的更高级方式使用)。

实际上似乎片段着色器可能错误地抓取了一个相邻像素,而不是它的目标,但我不确定 - 这没有多大意义,因为目标坐标仅在 init() 上生成,并且在那之后它们不会改变。

每个粒子的目标像素坐标作为顶点属性传递给片段着色器 1-1 不变(作为可变但没有可变值)。

uniform sampler2D colorMap; // The texture being used to color each particle
varying float v_geoX; // x,y coordinates passed as varyings
varying float v_geoY;

void main() {
    // Normally pulling the correct color, but this seems to get confused during camera movement.
    gl_FragColor = texture2D(colorMap, vec2(v_geoX, v_geoY));
}

有人对如何在不闪烁的情况下做到这一点有任何想法吗?当我将这种技术应用于更大更快的动画时,问题似乎只会变得更糟。到目前为止,我检查过的所有浏览器都发生了这种情况。

【问题讨论】:

  • 我没有看到任何闪烁。这个演示中是否需要彩色动画?演示问题是否需要渲染目标?
  • 这里也没有闪烁,Chrome 和 Firefox - Linux。您使用的是什么 GPU、浏览器和操作系统?应用了任何驱动程序解决方法(关于:gpu)?
  • @WestLangley 渲染目标是必要的,因为我需要捕获最后几帧以用于动画。我将 jsfiddle 简化为问题似乎发生时的基线示例。
  • 是的,我正在点击并拖动。没有闪烁。动画是否需要显示闪烁?如果没有,请将其关闭并简化演示。
  • 动画对我有帮助,但我已经对其进行了简化,因此动画不会更新并且应该是零运动。移动相机时您是否仍然看不到闪烁? jsfiddle.net/vko8hzzs/4

标签: javascript three.js webgl


【解决方案1】:

问题是你指向纹素之间的边缘。

这些行

   geoX.push(tx / imageSize);
   geoY.push(1.0 - ty / imageSize); // flip y

计算纹素之间的精确边缘。我的意思是让我们说imageSize 是4 texel,让我们说txty03

你的纹理坐标是这样的

   0    0.25  0.5   0.75       <- texture coords you're computing
   |     |     |     |     
   V     V     V     V     
   +-----+-----+-----+-----+
   |     |     |     |     |
   |     |     |     |     |   <- texels
   +-----+-----+-----+-----+

但是你想要的纹理坐标是这样的

     0.125 0.375 0.625 0.875   
      |     |     |     |   
      V     V     V     V  
   +-----+-----+-----+-----+
   |     |     |     |     |
   |     |     |     |     |   <- texels
   +-----+-----+-----+-----+

最简单的解决方法是添加 1/2 个纹素

   geoX.push(tx / imageSize       + 0.5 / imageSize);
   geoY.push(1.0 - ty / imageSize + 0.5 / imageSize); // flip y

问题在于您的数学直接指向纹素之间的舍入错误使其选择一个纹素或另一个。选择纹素的中心将解决这个问题。如果图像在相邻纹素之间没有那么大的对比度,您可能不会注意到。

【讨论】:

  • 修复它!谢谢@gman!我怀疑这与抓取错误的相邻像素(纹素)有关!我正在研究一个蛮力解决方案,通过将像素加倍以提供填充空间和错误空间,但是您所拥有的要好得多,并且可以直接解决问题。顺便说一句,对于任何看到闪烁并想要测试此解决方案 jsfiddle.net/vko8hzzs/5 的人来说,这是一个更新的小提琴。此外,我很确定闪烁只发生在配备 NVIDIA GeForce 显卡的机器上(与哪个浏览器无关)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-25
  • 2013-07-04
  • 2013-02-11
  • 1970-01-01
  • 1970-01-01
  • 2015-07-04
  • 1970-01-01
相关资源
最近更新 更多