【问题标题】:Smoothing noises with different amplitudes (Part 2)平滑不同幅度的噪声(第 2 部分)
【发布时间】:2019-04-29 13:34:30
【问题描述】:

好吧,我继续这个问题没有答案 (Smoothing random noises with different amplitudes),我还有另一个问题。

我已选择使用形状的轮廓/阴影 (Translating/transforming? list of points from its center with an offset/distance)。

这个轮廓/阴影比当前路径大。我使用这个存储库 (https://github.com/n-yoda/unity-vertex-effects) 来重新创建阴影。这很有效,除了一个事实。

要知道所有点的高度(通过这个阴影算法获得(Line 13 of ModifiedShadow.cs & Line 69 of CircleOutline.cs))我得到当前点到中心的距离,然后除以到中心的最大距离:

float dist = orig.Max(v => (v - Center).magnitude);
foreach Point in poly --> float d = 1f - (Center - p).magnitude / dist;

其中 orig 是阴影算法获得的整个点列表。 D 是阴影的高度。

但问题很明显我得到了一个完美的圆圈:

用红黑看对比:

这不是我想要的:

如您所见,这不是一个完美的渐变。让我们解释一下发生了什么。

我使用这个库来产生噪音:https://github.com/Auburns/FastNoise_CSharp

注意:如果你想知道我用什么来获得不同幅度的噪声:Smoothing random noises with different amplitudes(见第一个代码块),要查看实际情况,see this repo

  • 绿色背景颜色表示平均高度为 -0.25、幅度为 0.3 的噪声
  • 白色背景色表示平均高度为 0、幅度为 0.1 的噪声
  • 红色表示 1(对应于白色像素的噪声的总插值)
  • 黑色表示 0(对应于绿色像素的噪声的总插值)

这就是我们有这个输出的原因:

实际上,我已经尝试比较每个点到中心的距离,但这会输出一个奇怪且出乎意料的结果。

其实,我不知道该尝试什么...

【问题讨论】:

  • 另外,你能发布一个你需要的结果的模型吗?
  • 我有一个较早的评论,其中包含一些我在写答案时发现的问题。您的问题有点不清楚,如果在某个地方带有问号的问题会大大受益,因此可以具体回答这个问题的确切目的。我回答的问题是:为什么这个 lerp 不完全从/到内层和外层?

标签: c# unity3d interpolation noise amplitude


【解决方案1】:

问题在于 lerp 百分比(例如,在您的可视化中,从高/低或“红色”到“黑色”)只是点到中心距离的函数,除以一个常数(发生这种情况是任何点到中心的最大距离)。这就是为什么它看起来是圆形的。

例如,多边形左侧的最中心点可能距离中心 300 像素,而右侧的最中心点可能距离中心 5 像素。两者都需要是红色的,但是基于0 distance from center = red 不会是红色的,并且基于min distance from center = red 只会在右侧有红色。

相关的最小和最大距离会根据点的位置而变化

另一种方法是针对每个点:找到最近的白色像素,然后找到最近的绿色像素(或者,与绿色/白色相邻的最近的阴影像素,例如here)。然后,根据这两点与当前点之间的距离比较来选择您的红度。

因此,您可以这样做(伪 C#):

foreach pixel p in shadow_region {

    // technically, closest shadow pixel which is adjacent to x Pixel: 
    float closestGreen_distance = +inf;
    float closestWhite_distance = +inf;

    // Possibly: find all shadow-adjacent pixels prior to the outer loop 
    // and cache them. Then, you only have to loop through those pixels.
    foreach pixel p2 in shadow {
        float p2Dist = (p-p2).magnitude;

        if (p2 is adjacent to green) {
           if (p2Dist < closestGreen_distance) {
               closestGreen_distance = p2Dist;
           }
        }

        if (p2 is adjacent to white) {
           if (p2Dist < closestWhite_distance) {
               closestWhite_distance = p2Dist;
           }
        }
    }

    float d = 1f - closestWhite_distance / (closestWhite_distance + closestGreen_distance)
}

使用您在 cmets 中发布的代码,可能如下所示:

foreach (Point p in value)
{
    float minOuterDistance = outerPoints.Min(p2 => (p - p2).magnitude);
    float minInnerDistance = innerPoints.Min(p2 => (p - p2).magnitude);

    float d = 1f - minInnerDistance / (minInnerDistance + minOuterDistance);

    Color32? colorValue = func?.Invoke(p.x, p.y, d);

    if (colorValue.HasValue)
        target[F.P(p.x, p.y, width, height)] = colorValue.Value;
}

选择上述部分作为解决方案。以下部分,作为另一种选择提到,结果证明是不必要的。


如果您无法确定阴影像素是否与白色/绿色相邻,这里有一个替代方法,只需要计算粉红色(原始)轮廓中每个顶点的法线。

通过转到每个粉红色顶点并按照其法线向外创建外部“黄色”顶点。通过转到每个粉红色顶点并按照其法线向内创建内部“蓝色”顶点。

然后,当循环遍历阴影中的每个像素时,循环遍历黄色顶点以获得“最接近绿色”并通过蓝色获得“最接近白色”。

问题在于,由于您的形状不是完全凸出的,因此这些投影的蓝色和黄色轮廓在某些地方可能是由内向外的,因此您需要以某种方式处理它。我无法确定处理该问题的确切方法,但这是我目前所拥有的:

一个步骤是忽略任何具有指向当前阴影像素的外部法线的蓝色/黄色。

但是,如果当前像素位于黄色/蓝色形状由内向外的点内,我不确定如何继续。可能会忽略比应有的距离最近的粉红色顶点更近的蓝色/黄色顶点。

非常粗略的伪代码:

list yellow_vertex_list = new list 
list blue_vertex_list = new list 
foreach pink vertex p:
    given float dist;
    vertex yellowvertex = new vertex(p+normal*dist)
    vertex bluevertex = new vertex(p-normal*dist)

    yellow_vertex_list.add(yellowvertex)
    blue_vertex_list.add(bluevertex)

create shadow

for each pixel p in shadow:
    foreach vertex v in blue_vertex_list
        if v.normal points towards v: break;
        if v is the wrong side of inside-out region: break;
        if v is closest so far:
            closest_blue = v
            closest_blue_dist = (v-p).magnitude

    foreach vertex v in yellow_vertex_list
        if v.normal points towards v break;
        if v is the wrong side of inside-out region: break;
        if v is closest so far:
            closest_yellow = v
            closest_yellow_dist = (v-p).magnitude


    float d = 1f - closest_blue_dist / (closest_blue_dist + closest_yellow_dist)

【讨论】:

  • 好的,我正在尝试使用我在另一个问题(您已回答)中提出的缩放方法来获取内部和外部相邻像素,但结果如下:i.imgur.com/UdFR0t1.png...但是告诉我一件事,当您说像素与白色或绿色像素相邻时,就相当于我发布的纹理中表示的蓝色和黄色像素?
  • 你能完成第一个块的伪代码(多一点)吗?这是我所拥有的:pastebin.com/f1zBHAkq,这是它的输出:i.imgur.com/xdtvarI.png,问题这是它导致 NaN 值作为输出。我不完全明白我必须在这里分配什么closestWhite_distance;。另外,我认为相邻的意思是包含在内/外点列表中,但我认为我错了。
  • 另外,我试过这个:float minOuterDistance = outerPoints.Min(p =&gt; (Center - p).magnitude), minInnerDistance = innerPoints.Min(p =&gt; (Center - p).magnitude);,没有运气......
  • 谢谢!!!!!!那是我的错误,因为我是在比较中心而不是 p2。现在这就是它返回的内容:i.imgur.com/9NJ2QiE.png。我会给你一杯啤酒,但我认为这有点不可能哈哈哈(我想和你保持联系,这是我的 Discord:@z3nth10n#0775)
  • 我无法编辑自己的帖子,这是噪声的结果:i.imgur.com/AAKFncB.png(我认为这很好)。我很高兴:P 现在是优化时间:P
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-17
  • 1970-01-01
  • 2019-01-01
  • 2014-03-22
  • 2016-12-20
  • 2021-02-05
相关资源
最近更新 更多