如何在三个js中将多个纹理裁剪为多边形

Posted

技术标签:

【中文标题】如何在三个js中将多个纹理裁剪为多边形【英文标题】:How to clip multiple textures to polygon in three js 【发布时间】:2017-02-13 02:44:21 【问题描述】:

我有一堆平面,每个平面在网格中都有自己的纹理。目前我将它们渲染为单独的平面,每个平面都有自己的纹理,尽管我可以使用具有多个面的单个平面。

每种颜色都是一种纹理。

我有一个与这些平面平行的任意形状的多边形网格:

这个形状可以完全包含在一个平面内,或者更大。

我想用平面的重叠纹理来纹理多边形:

如何在三个js中完成这种纹理的裁剪?

我也愿意接受任何其他 WebGL 解决方案。

我的一些想法:

    将多边形细分为与重叠平面相对应的面。然后使用 UV 坐标对这些面进行纹理处理。我知道我可以让它工作,但它似乎太复杂的解决方案。 对多边形应用多个纹理并使用 UV 坐标来分布它们。 -- 如果不细分,我不确定这是否可行?

还有其他想法吗?这可以通过混合模式来实现吗?

【问题讨论】:

只是一个想法,很可能效率不高。你不能按需要的顺序在 2d 画布上绘制所有纹理,然后在多边形上简单地映射一个纹理吗? 好主意。我想我会尝试渲染到纹理。对于我的基本用例来说,它应该足够有效。不过,它似乎仍然过于复杂。 【参考方案1】:

几个想法:


将小纹理烘焙到texture atlas 中,这样您就可以在具有一组 uv 的单个平面上拥有切片(如果需要多个图集,您可以在一个 WebGL 程序中使用多个纹理采样器)。

计算平面的 uv 对应于形状顶点的世界 pos 并使用这些 uv 采样纹理图集。 为此,您可能需要传递给形状材质平面的模型矩阵(或者如果您知道它,则只需缩放/偏移方向,如果平面是固定的,则什么都没有)。

请记住,您不需要在小图块上使用高分辨率纹理。此外,可以通过将图块渲染到纹理来替换图集(从顶部使用正交投影) 或通过在单独的采样器中传递纹理。关于最后一种情况:要确定要传递哪些纹理,您可以测试形状的边界框与地图图块。


使用简单材质将您的形状渲染为纹理,并将此纹理用作绘制平面的主要通道中的蒙版。

详细说明:

使用普通相机将您想要遮罩的形状放在单独的容器中,并使用非常简单的材料(到处写白色)render it to a fixed size texture。在该渲染通道之后,您应该有一个黑色和白色形状的纹理,就像您在屏幕上看到的一样(但缩放为方形纹理)。

之后渲染场景的其余部分,传递给瓷砖材质遮罩纹理。在片段着色器中使用 screenPos 作为 uv 的示例蒙版纹理,只有当你得到白色时才绘制片段(否则丢弃)。可能不是最好的主意(丢弃是昂贵的)。


深度遮罩方法的更好版本:在遮罩过程中禁用颜色写入 (renderer.context.colorMask(false, false, false, false);)。之后,您应该在深度缓冲区中拥有您的形状。然后将颜色掩码重置为所有true,设置renderer.autoClearDepth = false,设置tileMaterial.depthFunc = THREE.GreaterDepth(more about depthFunc)。然后渲染你的瓷砖。这应该可以完成工作。

也可以通过将遮罩深度写入depthTexture 并将其用作主通道中的纹理来完成。


使用模板缓冲区进行屏蔽:我还没有尝试过,但它应该适合您的情况。示例:1、2。想法类似于上面描述的遮罩。

【讨论】:

你能详细说明后两个吗?除非在运行时创建,否则我不能使用纹理图集,因为我在运行时从 google maps api 动态加载我的纹理图块。 @rawbeans 添加了详细信息。考虑在单独的采样器中传递纹理并使用世界空间坐标进行采样,我认为它应该工作得很好,因为没有额外的通道。但是,可用采样器的数量可能会干扰。 谢谢。我最终渲染到纹理,然后像您的第一个建议一样计算 UV。效果很好。 @rawbeans 很高兴听到这个消息!

以上是关于如何在三个js中将多个纹理裁剪为多边形的主要内容,如果未能解决你的问题,请参考以下文章

如何在OpenGL中将像素作为纹理绘制到多边形?

在 OpenGL 的全屏四边形中将 QGraphicsScene 显示为纹理

在现有的 texture_2D 中裁剪四边形

如何在 C++ 中将位图绘制为 OpenGL 纹理?

如何在opengl中平滑多个四边形的纹理

WebGIS裁剪算法-线裁剪多边形