【问题标题】:Get modified mesh displaced by displacementMap in three.js在 three.js 中通过置换贴图获取修改后的网格
【发布时间】:2017-10-11 20:00:51
【问题描述】:

我正在尝试返回并导出被置换贴图置换的网格。

着色器正在根据这条线转换顶点(来自 三.js/src/renderers/shaders/ShaderChunk/displacementmap_vertex.glsl):

transformed += normalize( objectNormal ) * ( texture2D( displacementMap, uv ).x * displacementScale + displacementBias );

这是根据displacementMap置换一个顶点,并与该顶点的uv坐标混合。

我正在尝试创建此网格/几何图形,以便以后可以将其导出。

我在这里创建了一个问题的“演示”: Github Page 我希望在按 exportSTL 时,在视口中看到的 置换网格。但是我只得到了未移位的飞机。

我明白为什么会发生这种情况,置换只发生在着色器中,并没有真正直接置换平面的几何形状。

我还没有找到three.js 提供的方法,也没有找到任何从着色器中获取更改的方法。 所以我试图用“demo.js”中的一个函数来做。 但是,我是一个 WebGL/three.js 新手,在重新创建着色器的功能时遇到了问题。

我找到了处理 morphTargets 的出口商,但这些都没有帮助。 阅读this question 后,我尝试了PlaneBufferGeometry,因为它更接近着色器——但这对我来说产生了相同的结果。 我认为this question 最初试图产生类似的东西,但接受了一个不相关的问题。

最后,我想在 HTML 画布上进行绘制,然后实时更新纹理(我有这部分工作)。然后,用户可以导出网格进行 3D 打印。

是否有一种方法可以让 three.js 给我修改后的着色器几何? 或者有人可以帮我将着色器线翻译成“传统”的 Three.js 函数吗? 也许这是获得位移网格的完全错误的方法?

更新 - 示例正在运行

感谢 DeeFisher 的示例,我现在可以计算 CPU 中的位移,正如 imerso 最初建议的那样。 如果您现在单击Github Page,您将获得一个工作示例。 目前我不完全理解为什么我必须镜像画布才能最终获得正确的位移,但这在最坏的情况下是一个小麻烦。

【问题讨论】:

    标签: javascript 3d three.js webgl


    【解决方案1】:

    要做到这一点,同时仍然使用着色器进行置换,您需要切换到 WebGL2 并使用 Transform-Feedback(Google 搜索:WebGL2 Transform-Feedback)。

    另一种方法是将纹理读回 CPU,并在仅使用 CPU 置换顶点的同时对其进行扫描(Google 搜索:WebGL readPixels)。

    这两种选择都需要一些努力,因此目前没有代码示例。 =)

    【讨论】:

    • 感谢您的指点。我已经开始研究它,到目前为止没有成功。我想在 three.js 中做这件事,而不是切换到底层的 WebGL2。但是,我正在尝试根据您的建议修改 three.js GLSL 代码。如果我真的做到了,我希望能在某一时刻把它合并回来。
    • 如果你想继续使用 WebGL1,没有办法恢复/保存 GPU 置换的顶点,所以你唯一的选择是在 CPU 中读回置换纹理和置换顶点——也就是说,您不会使用 GLSL 进行置换,但至少您可以将 CPU 中的置换顶点导出到磁盘。在 WebGL2 中,您有 transform-feedback,这是一种读回移位顶点的方法,因此您仍然可以使用 GLSL,然后使用 transform-feedback 获取结果,最后导出到磁盘。
    • 接受了,因为除了您的建议之外似乎别无他法。 Three.js 开发分支正在开发 WebGL2 渲染器,但它似乎还没有准备好迎接黄金时间。查看ibiblio.org/e-notes/webgl/gpu/bounce.htm 似乎暗示来自WebGl2 的TransformFeedbacks 将是解决问题的好方法。无论如何感谢您的帮助。
    【解决方案2】:

    BABYLON.js 可以与 THREE.js 结合使用,它允许您在应用置换贴图时置换实际的网格顶点:

    var sphere = BABYLON.Mesh.CreateSphere("Sphere", 64, 10, scene, true);
    sphere.applyDisplacementMap(url, minHeight, maxHeight, onSuccess, uvOffset, uvScale)
    

    查看正在使用的函数示例here

    然后您可以使用 for 循环将 BABYLON 网格数据传输到三个网格对象中。

    【讨论】:

    • 我终于有时间测试这个了。正如 imerso 所建议的,Babylon.js(或至少您的示例)似乎正在 CPU 中执行此操作。但是:示例代码帮助我为 THREE.js 实现了相同的功能!我更新了 github 代码,它现在可以工作了,使用 STLBinaryExporter 我得到了正确置换的网格。 “正常” STLExporter 无法正确导出网格。所以我要感谢你为我指出了一个很好的例子,如何计算 CPU 中的位移。我真的很感激!非常感谢您!
    • 真棒@Deadolus !非常感谢。
    猜你喜欢
    • 2013-12-16
    • 1970-01-01
    • 2019-05-18
    • 1970-01-01
    • 2021-05-10
    • 1970-01-01
    • 2023-03-26
    • 1970-01-01
    • 2016-04-07
    相关资源
    最近更新 更多