【问题标题】:Read vertex positions as pixels in Three.js在 Three.js 中将顶点位置读取为像素
【发布时间】:2018-08-07 09:18:06
【问题描述】:

在顶点着色器中顶点发生位移的情况下,如何在 WebGL / Three.js 中检索它们的变换位置?

Otherquestions这里建议将位置写入纹理然后读取像素,但结果值似乎不正确。

在下面的示例中,位置被传递给片段着色器而不进行任何转换:

// vertex shader
varying vec4 vOut;

void main() {
    gl_Position = vec4(position, 1.0);
    vOut = vec4(position, 1.0);
}

// fragment shader
varying vec4 vOut;

void main() {
    gl_FragColor = vOut;
}

然后读取输出纹理,我希望pixel[0].rpositions[0].x 相同,但事实并非如此。

这是一个显示问题的 jsfiddle: https://jsfiddle.net/brunoimbrizi/m0z8v25d/2/

我错过了什么?

【问题讨论】:

  • 你的期望是错误的。当您对gl_Position 结果进行栅格化时,您会剪切您的网格。缓冲区中的 Pixel[0] 代表其他东西,与您的实际坐标相去甚远。顶点总是在某个 X,Y (width==4 / x == -2)。在屏幕上,您会看到 -1,-1 处的网格被插值,因此您的 -2,-2 不在屏幕上。如果您的宽度和高度大于 2,则数组中的最后一个像素应始终为 1,1。
  • 我有点困惑,为什么左下角的数字不同,但我认为这取决于您的分辨率以及您如何设置该视图
  • @pailhead 确定网格被剪裁了吗?我还尝试将位置乘以模型视图和投影矩阵(第 32 行 gl_Position = modelViewMatrix * projectionMatrix * vec4(position, 1.0);),结果在 -2 和 2 之间,但仍然关闭。
  • 好吧,这样想吧。制作尺寸为 1,1 的飞机。 gl_Position 然后将获得 -0.5,0.5 范围,您应该会看到一个仅填充屏幕中心的平面。如果您将其设置为大于 2,2,您将获得剪辑空间之外的顶点。我认为奇怪的数字来自第一个像素处发生的插值,但我对小提琴有点困惑。

标签: three.js glsl fragment-shader vertex-shader


【解决方案1】:

解决了。问题中提到的 jsfiddle 有很多问题。

  • width * height 应该等于顶点数。具有 4 x 4 段的 PlaneBufferGeometry 产生 25 个顶点。 3 x 3 得到 16。总是 (w + 1) * (h + 1)。
  • 顶点着色器中的位置需要轻推1.0 / width
  • 顶点着色器需要知道widthheight,它们可以作为uniform传入。
  • 每个顶点都需要一个属性及其索引,以便正确映射。
  • 每个位置都应该是生成纹理中的一个像素。
  • 生成的纹理应绘制为gl.POINTSgl_PointSize = 1.0

工作 jsfiddle:https://jsfiddle.net/brunoimbrizi/m0z8v25d/13/

【讨论】:

  • 嗯嗯,我不认为这实际上是最好的答案。
  • 对不起,我本来想现在有一个小提琴。您可以在没有积分的情况下执行此操作,但可能会涉及更多。
  • 如果你像这样隔开你的点,你将需要一个非常大的纹理,如果你开始对它们进行分组,你将不得不编写更多的逻辑。
  • 我添加了另一个答案来澄清我对 cme​​ts 的意思。
  • 为什么在你的屏幕截图中它是 0.75 而不是 1 是因为插值(我没有在小提琴中解决这个问题),但为什么它是 1 而不是 2 是因为剪辑,(解决在小提琴/答案)
【解决方案2】:

您没有正确写出顶点。

https://jsfiddle.net/ogawzpxL/

首先,您正在剪裁几何图形,因此您的顶点实际上在视图之外结束,您会看到四边形的中间没有任何顶点。

您可以使用uv 属性在视图中渲染整个四边形。

gl_Position = vec4( uv * 2. - 1. , 0. ,1.);

缓冲区中的所有内容都代表四边形上的某个点。看起来棘手的是,当您渲染时,像素将在您的顶点旁边采样。在小提琴中,我对世界空间事物应用了像素空间中的偏移量,但它并没有真正起作用。

它似乎与点一起工作的原因是这可能都是错误的:) 如果您只想转换顶点,那么您需要将它们正确存储在纹理中。您可以为此使用积分,但理想情况下它们不会间隔太多。在您的场景中,它们将填充纹理的前几行(因为它比它可能的大得多)。

当您尝试将此应用于PlaneGeometry 以外的其他内容时,您可能会开始遇到问题。在这种情况下,这个问题必须被打破。

【讨论】:

猜你喜欢
  • 2015-12-02
  • 1970-01-01
  • 1970-01-01
  • 2013-07-13
  • 1970-01-01
  • 2016-04-15
  • 2016-01-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多