平滑不同幅度的噪声(第2部分) [英] Smoothing noises with different amplitudes (Part 2)

查看:142
本文介绍了平滑不同幅度的噪声(第2部分)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,我继续这个问题,没有回答(使具有不同幅度的随机噪声平滑),我还有另一个问题.

Well, I'm continuing this question without answer (Smoothing random noises with different amplitudes) and I have another question.

我选择使用形状的轮廓/阴影(

I have opted to use the contour/shadow of a shape (Translating/transforming? list of points from its center with an offset/distance).

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

This contour/shadow is bigger than the current path. I used this repository (https://github.com/n-yoda/unity-vertex-effects) to recreate the shadow. And this works pretty well, except for one fact.

了解所有点的高度(通过此阴影算法获得(

To know the height of all points (obtained by this shadow algorithm (Line 13 of ModifiedShadow.cs & Line 69 of CircleOutline.cs)) I get the distance of the current point to the center and I divide between the maximum distance to the center:

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

其中orig是通过阴影算法获得的点的完整列表. D是阴影的高度.

Where orig is the entire list of points obtained by the shadow algorithm. D is the height of the shadow.

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

But the problem is obvious I get a perfect circle:

用红色和黑色查看对比度:

In red and black to see the contrast:

这不是我想要的:

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

As you can see this not a perfect gradient. Let's explain what's happening.

我使用此库来生成噪音: https://github.com/Auburns/FastNoise_CSharp

I use this library to generate noises: https://github.com/Auburns/FastNoise_CSharp

注意::如果您想知道我用来获取不同幅度噪声的方法:参见此存储库

Note: If you want to know what I use to get noises with different amplitude: Smoothing random noises with different amplitudes (see first block of code), to see this in action, see this repo

  • 绿色背景代表噪声,平均高度为-0.25,幅度为0.3
  • 白色背景颜色表示平均高度为0且幅度为0.1的噪声
  • 红色表示1(对与白色像素相对应的噪声进行总插值)
  • 黑色表示0(对与绿色像素相对应的噪声进行总插值)

这就是为什么我们有以下输出:

That's why we have this output:

实际上,我尝试比较每个点到中心的距离,但这会产生奇怪且出乎意料的结果.

Actually, I have tried comparing distances of each individual point to the center, but this output a weird and unexpected result.

实际上,我不知道该怎么做...

Actually, I don't know what to try...

推荐答案

问题是lerp百分比(例如,可视化中从高/低或红色"到黑色")只是该点的函数到中心的距离,该距离除以一个常数(碰巧是任何一点到中心的最大距离).这就是为什么它看起来是圆形的.

The problem is that the lerp percentage (e.g., from high/low or "red" to "black" in your visualization) is only a function of the point's distance from the center, which is divided by a constant (which happens to be the maximum distance of any point from the center). That's why it appears circular.

例如,多边形左侧的最中心点可能离中心300像素,而右侧的最中心点可能是5像素.两者都必须为红色,但以0 distance from center = red为基础将不会是红色,而以min distance from center = red为基础将仅在右侧具有红色.

For instance, the centermost point on the left side of the polygon might be 300 pixels away from the center, while the centermost point on the right might be 5 pixels. Both need to be red, but basing it off of 0 distance from center = red won't have either be red, and basing it off the min distance from center = red will only have red on the right side.

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

针对每个点的一种替代方法是:找到最接近的白色像素,然后找到最接近的绿色像素(或与绿色/白色相邻的最接近的阴影像素,例如

One alternative method is for each point: find the closest white pixel, and find the closest green pixel, (or, the closest shadow pixel that is adjacent to green/white, such as here). Then, choose your redness depending on how the distances compare between those two points and the current point.

因此,您可以执行此操作(伪C#):

Therefore, you could do this (pseudo-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)
}

使用您在评论中发布的代码,看起来可能像这样:

Using the code you've posted in the comments, this might look like:

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;
}


选择上面的部分作为解决方案.下面的部分,作为另一个选项,被证明是不必要的.


如果您不能确定阴影像素是否与白色/绿色相邻,则这是一种替代方法,只需要计算粉色(原始)轮廓中每个顶点的法线即可.


The above part was chosen for the solution. The below part, mentioned as another option, turned out to be unnecessary.


If you can't determine if a shadow pixel is adjacent to white/green, here's an alternative that only requires the calculation of the normals of each vertex in your pink (original) outline.

通过转到每个粉红色顶点并遵循其法线向外来创建外部黄色"顶点.通过转到每个粉红色顶点并遵循其正常向内的方式来创建内部蓝色"顶点.

Create outer "yellow" vertices by going to each pink vertex and following its normal outward. Create inner "blue" vertices by going to each pink vertex and following its normal inward.

然后,当遍历阴影中的每个像素时,遍历黄色顶点以获得最接近绿色",并遍历蓝色以获得最接近白色".

Then, when looping through each pixel in the shadow, loop through the yellow vertices to get your "closest to green" and through the blue to get "closest to white".

问题在于,由于您的形状不是完全凸出的,因此这些投影的蓝色和黄色轮廓在某些地方可能会由内向外,因此您需要以某种方式进行处理.我在确定处理该问题的确切方法时遇到了麻烦,但这是我到目前为止所拥有的:

The problem is that since your shapes aren't fully convex, these projected blue and yellow outlines might be inside-out in some places, so you would need to deal with that somehow. I'm having trouble determining an exact method of dealing with that but here's what I have so far:

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

One step is to ignore any blues/yellows that have outward-normals that point towards the current shadow pixel.

但是,如果当前像素位于黄色/蓝色形状由内向外的点内,则我不确定如何继续.可能有一些事情可以忽略比最应该接近粉红色顶点的蓝色/黄色顶点.

However, if the current pixel is inside of a point where the yellow/blue shape is inside out, I'm not sure how to proceed. There might be something to ignoring blue/yellow vertexes that are closer to the closest pink vertex than they should be.

极其粗糙的伪代码:

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)

这篇关于平滑不同幅度的噪声(第2部分)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆