【问题标题】:Retrieve Vertices Data in THREE.js在 THREE.js 中检索顶点数据
【发布时间】:2015-05-17 05:05:45
【问题描述】:

我正在使用自定义着色器创建网格。在顶点着色器中,我正在修改几何顶点的原始位置。那么我需要从着色器外部访问这个新的顶点位置,我该如何完成呢?

【问题讨论】:

    标签: three.js textures webgl shader vertex-shader


    【解决方案1】:

    代替变换反馈(WebGL 1.0 不支持),您必须使用直通片段着色器和浮点纹理(这需要加载扩展程序 OES_texture_float)。这是在 WebGL 中的 GPU 上生成顶点缓冲区的唯一方法。 WebGL 也不支持像素缓冲区对象,因此读取输出数据的效率会非常低。

    不过,您可以通过以下方式完成此操作:

    这将是一个粗略的概述,侧重于 OpenGL,而不是特定于 Three.js 的任何内容。

    首先,以这种方式编码您的顶点数组(为索引添加第 4 个组件):

    Vec4 pos_idx  :  xyz = Vertex Position,  w = Vertex Index (0.0 through NumVerts-1.0)
    

    将顶点索引存储为w 组件是必要的,因为 OpenGL ES 2.0 (WebGL 1.0) 不支持 gl_VertexID

    接下来,您需要一个 2D 浮点纹理:

    MaxTexSize = Query GL_MAX_TEXTURE_SIZE
    
    Width  = MaxTexSize;
    Height = min (NumVerts / MaxTexSize, 1);
    

    使用这些尺寸创建一个 RGBA 浮点纹理并将其用作 FBO 颜色附件 0。

    顶点着色器:

    #version 100
    
    attribute vec4 pos_idx;
    
    uniform int width;  // Width of floating-point texture
    uniform int height; // Height of floating-point texture
    
    varying vec4 vtx_out;
    
    void main (void)
    {
      float idx = pos_idx.w;
    
      // Position this vertex so that it occupies a unique pixel
      vec2 xy_idx = vec2 (float ((int (idx) % width)) / float (width),
                          floor (idx / float (width)) / float (height)) * vec2 (2.0) - vec2 (1.0);
      gl_Position = vec4 (xy_idx, 0.0f, 1.0f);
    
    
      //
      // Do all of your per-vertex calculations here, and output to vtx_out.xyz
      //
    
    
      // Store the index in the W component
      vtx_out.w = idx;
    }
    

    直通片段着色器:

    #version 100
    
    varying vec4 vtx_out;
    
    void main (void)
    {
      gl_FragData [0] = vtx_out;
    }
    

    画图并回读:

    // Draw your entire vertex array for processing (as `GL_POINTS`)
    glDrawArrays (GL_POINTS, 0, NumVerts);
    
    // Bind the FBO's color attachment 0 to `GL_TEXTURE_2D`
    
    // Read the texture back and store its results in an array `verts`
    glGetTexImage (GL_TEXTURE_2D, 0, GL_RGBA, GL_FLOAT, verts);
    

    【讨论】:

    • Three.js 中的一些代码可以大致完成您想要的操作,可以在 here 找到。它略有不同之处在于它始终在 GPU 上保留顶点,但如果您检查这个答案并且作为一些示例代码,您应该能够将一些东西放在一起。
    • 非常感谢您提供如此详细的解释!所以我明白唯一的方法是使用片段着色器来检索纹理(基于顶点位置),然后再次将 RGBA 颜色从纹理转换到位置,对吧?
    • @MickeyMouse:是的,但是...如果您不需要 CPU 端的这些位置,您实际上可以在另一个渲染通道的顶点着色器中进行纹理查找。如果您检查我列出的示例的源代码,它会显示如何做到这一点。 我不确定您是否需要 GPU 上的顶点,我描述的答案是从 GPU 下载顶点数据。
    • 是的,我想我在 CPU 中需要它们。我正在尝试制作高斯模糊并将其应用于顶点位置(高度)值(不适用于颜色)。为了优化流程,我分两步执行任务,水平和垂直 (gamerendering.com/2008/10/11/gaussian-blur-filter-shader)。也许对于这两个步骤,我在 CPU 中不需要它们(?)。第三步是标准化值,这意味着我必须遍历所有顶点,所以我发现最后一步需要它们在 CPU 中。
    • @MickeyMouse:我真的不知道如何将模糊过滤器应用于顶点数据。你可能会得到一个点云,但是按照我在脑海中描绘的方式,当你插入额外的顶点模糊会创建时,你会失去像三角形这样的结构。在任何情况下,如果您将顶点位置存储在纹理中,则可以在片段着色器中进行多次提取(您必须使用我之前链接的 Three.js 示例中的纹理坐标索引逻辑来从正确的纹素)并可能在 GPU 上实现整个事情。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-30
    • 2013-11-03
    • 1970-01-01
    相关资源
    最近更新 更多