如何使单位选择圈合并?


16

我想知道如何使合并圆选择产生这种效果。以下是说明图片:

在此处输入图片说明 在此处输入图片说明

基本上我正在寻找这种效果:

在此处输入图片说明

如何实现圆的合并效果?我没有发现有关此效果的任何解释。我知道投射这些纹理可以开发贴花系统,但是我不知道如何创建合并效果。

如果可能的话,我正在寻找纯粹的着色器解决方案。


您能解释一下“合并效应”是什么意思吗?
温德拉2014年

当然,如果您查看屏幕快照的右上角字符,则贴花不会相互交叉,但是左侧的两个交叉会越过其蓝色圆圈并合并。我添加了新的屏幕截图以显示效果。
2014年

您是否坚持着色器解决方案?如果没有,那么您只需在上一张图中解决即可。
温德拉2014年

上一张屏幕截图仅显示了我定位的效果。最终结果应类似于先前的屏幕截图。
2014年

1
是的,我同意,我认为它们会动态地使用纹理构建一个网格圆,然后将其切割以合并它们。这也是一个很好的解决方案,但我认为您可以做到的效果有限。
2014年

Answers:


8

您可以采取一些技巧:

Z缓冲区

渲染所有其他对象后,为每个单元渲染一个较小的透明圆,最大Z值。然后在地面上渲染选择圆贴花。由于它们以Z顺序排列在下方,因此当它们以单位为单位时将被丢弃。

完全透明意味着圆写入Z缓冲区(最大Z值)。现在,当您渲染贴花时,它们将针对Z缓冲区值进行测试,并且如果它们通过测试,则它们将被渲染(这仅在圆之外发生)

模版

与以前的方法相同,但是这次使用模板缓冲区。为具有某些模板值的单位渲染较小的圆,然后渲染选择贴花。设置模具以丢弃带有模具值的所有元素。


Z缓冲区技术很有趣,但我不知道第一个透明圆圈如何修剪地面贴花。
2014年

0

例如,您可以在贴图渲染像素着色器中检查是否与任何其他贴图有交集,并在这种情况下杀死像素。进行此类圆形贴花非常有效。


1
我假设您已从答案中删除了该部分-将所有圆的位置和半径传递给着色器。
Kromster说支持Monica 2014年

@Krom如果OP对解决方案表示有兴趣,我很乐意提供更多详细信息。
JarkkoL 2014年

0

您是说地面上的那些蓝色圆圈吗?

可能有一种更聪明的方法来执行此操作,但请以我的解决方案为例说明如何执行此操作。将圈子渲染为屏幕大小的单独的空纹理。此时,您可以根据需要将它们混合在一起。根据您的需要,您可以编写全色或仅写给定像素处存在圆圈的信息。但是,如果您要进行Z测试效果,则将明确需要每个写入像素的深度信息。

在上一步之后渲染地形时,可以使用像素着色器中的屏幕坐标作为UV对以前创建的纹理进行采样。现在您知道,该圆应该或不应该投影到给定的地形像素上。但是,这样可以像禁用Z测试一样工作,因此地形无法隐藏任何圆。如果希望地形隐藏其后面的圆,请在将圆与地形纹理混合之前执行深度测试。您可以使用较小的偏差来启用仅在地形下方一点的圆的渲染,但是您仍然希望它们渲染。


编辑:现在,为了获得合并圆的效果,您需要做的是:当渲染到单独的纹理时,您需要检查是否已经有一个要渲染新圆的圆。(检查那里的纹理是否有值),如果有,请擦除此像素。当两个或多个圆圈重叠时,这应具有“轮廓”效果。为了使它正常工作,但是您只需要对圆的内部而不是边界进行此测试。因此,在渲染圆时,请在输出纹理中写入一些特定的值,这表明它是一个圆。然后,您只需要在圆上不进行任何渲染就可以了。

Edit2:对于简单的红色/绿色示例:在渲染任何像素之前,请检查该像素是否尚未绿色。如果是,请不要渲染。这将达到目的。实际上,在写入纹理时,您甚至可以在圆的外部/内部使用红色/绿色,然后在渲染地形时读取这些值并将其转换为所需的颜色。

如果我的答案很抽象,请告诉我。


我有大致的想法,但是正如您所说,这对我来说是关于合并圆的抽象:)
2014年

0

有一些选择。作为一种通用方法,模板缓冲区通常在需要屏蔽某些图形的地方非常方便,例如示例中圆圈重叠的轮廓。

在这种情况下,我认为无需模板缓冲区就可以轻松完成此操作。您可以使用深度缓冲区消除圆重叠的轮廓。这个想法是您将圆的内部仅绘制到深度缓冲区中(因为我们不想看到内部),然后绘制轮廓。这样,轮廓的与另一个圆重叠的部分将通过深度测试消除。

唯一的警告是您必须对深度战斗保持谨慎。您可以使用较小的偏移量来确保轮廓线实际上位于内部后面,并通过深度测试将其消除。另一种方法是使用glPolygonOffset()

假设您有两个平行于xy平面的圆,其圆心分别位于(x1,y1,z)和(x2,y2,z)。您具有以下绘制功能:

// Draw interior part of circle, shown in green in the schematic in the question.
drawInterior(x, y, z);

// Draw outline of circle, shown in red in the schematic in the question.
drawOutline(x, y, z);

然后,绘图顺序如下所示,delta只是一个小的偏移量:

glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
drawInterior(x1, y1, z + delta);
drawInterior(x2, y2, z + delta);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
drawOutline(x1, y1, z);
drawOutline(x2, y2, z);

0

在我的头顶上,如果将这些贴花绘制为圆盘,我将测试每个圆与另一个圆的相交点,并将相交点放入数组中。然后绘制不在交点内的弧。但是,这不是着色器解决方案。


是的,我也考虑过这个问题:),但是正如您所说的,它不是着色器解决方案,也不是非常通用的解决方案。但是谢谢!
2014年

那是非常模糊的描述
Kromster说支持Monica

0

你想在这里嘲笑。您的第一遍将圆渲染到模板缓冲区。第二遍渲染可视轮廓,在模板缓冲区未更改的任何地方 第二遍必须使用比第一遍更大的几何形状,在这种情况下,简单的线性标量就足够了。

尽管我在此处绘制轮廓的解决方案超出了您的需要(因为该着色器将每个网格边缘变成一个完整的四边形),但它的确遵循这种方法:将原始模型绘制到模具缓冲区中,然后在其中绘制更大的版本模具缓冲区仍为0。


谢谢!因此,与其先绘制可见部分,不如先将透明圆渲染到模具中。但是如何渲染圆形透明圆呢?我不能限制要渲染到模具中的图像的一部分。当我渲染到模具时,一切都在那儿,对吗?
Doodlemeat

是的,这就是为什么第二遍(可见部分)缩放较大的原因:因此其范围大于模板缓冲区。您只需要在第二遍中应用顶点标量(环顾四周轮廓着色器,它们中的大多数使用我指的是更简单的标量)。如果颜色是透明的,您也不能更改模板缓冲区。在这种情况下,您可能需要第二个纹理蒙版,或者可以做一些距离数学来确定圆。我需要几个小时才能访问Unity来提供任何代码。
Draco18s不再信任2016年

嗯,只需要在第一遍中将黑白图像写入模板缓冲区,以使黑色在模板中变为0,白色就变为1,该怎么办。那有可能吗?
Doodlemeat

这就是第二个纹理蒙版的意思。我很确定它会起作用,如果没有Unity,我就无法真正进行验证,而我将在24个小时内没有得到Unity。
Draco18s不再信任SE 2016年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.