【问题标题】:Draw influence of dots in network绘制网络中点的影响
【发布时间】:2015-08-28 15:16:35
【问题描述】:

我遇到了一个有点烦人的问题,如果不知道正确的词汇就很难解释,但以下两张图片应该可以解释我在寻找什么。

我有一个连接点的网络。每个点都有一个颜色属性。

Dot Network

网络中的每个点都代表一个位置,由于缺乏更好的术语,该位置由相应的颜色“拥有”。我现在想通过生成类似的东西来正确展示每个拥有的点对其附近的影响,即颜色“领土”:

Colored Dot Network

我看不到一个简单的解决方案。我能看到的最可能的解决方案是生成一个平面,将有关每个点的信息传递给适当的着色器并使用它来计算平面的纹理。然而,与此示例不同的是,不仅有 10 个点,而且可能介于 1000-2000 之间。

提出一些更具体的问题:

1) 着色器能否处理点数(1000+)?

2) 我不确定着色器必须采用哪种算法才能获得正确的结果。遍历所有点并将它们与所有剩余的点进行比较并产生某种重量似乎.. 次优。我的背景是物理学,第一直觉是产生类似于 Wigner-seitz 细胞的东西。 (我会提供一个图片链接来解释我的意思,但似乎我只能使用新帐户发布 2 个链接。然而,快速的谷歌图片搜索应该有很多好的结果)

3) 最明显的一个:我缺少一个简单的解决方案吗?

【问题讨论】:

  • 这些点是否会移动或改变其影响半径?如果不是,则为每个点生成一个影响多边形(相对于其直接邻居)并根据需要更新每个多边形的颜色可能会更高效。
  • @rutter 它们不会相对于彼此移动,它们的连接也不会改变。我以前没有考虑过为每个点生成一个多边形。虽然回想起来,我对 Wigner-seitz 细胞的第一直觉就是这样,所以也许它确实有优点

标签: unity3d


【解决方案1】:

这就是我要做的,创建一个包含所有点及其位置的数组,让我们来讨论一下,就像你将在全屏中统一运行它一样,然后创建一个保存所有点位置的新数组,但不是世界位置我们想要以像素为单位的位置。现在这是代码中的那部分:

Transform[] dots;
Vector3[] position; //Vector2 is more appropriate because of 2D space but most of the Unity functions support only Vector3

void Awake(){
    for(int i =0; i < dots.Length; i++)
        position[i] = Camera.main.WorldToScreenPoint(dots[i].position);
}

现在我们有了屏幕上所有点的位置,接下来就是创建实际的纹理了。

Texture2D outTex = new Texture2D (Screen.height, Screen.width, TextureFormat.RGB24, false);

现在我们应该遍历这个纹理上的每个像素并创建特定的公式来确定该像素应该是什么颜色。

添加另一个 Color32 类型的数组变量,它将为每个点定义颜色(由谁“拥有”)。

int h = outTex.height;
int w = outTex.width;
for (int i = 0; i < h; i++)
    for (int j = 0; j < w; j++) {
        //Formula for determining color is right here, here is my suggestion 
        //(the most simplest one), check the color of each dot and based on the distance 
        //between this pixel and dot's position determine how much influence that dot
        //has on this pixel, here is how it goes
        float red = 0;
        float green = 0;
        float blue = 0;
        float divider = 0;
        for(int c = 0; c < dots.Length; c++){
            float curDist = Vector3.Distance(dots[c].position, new Vector3(j, i ,0);
            curDist = 1f/(curDist+1f);
            red += dotColors[c].r * curDist;
            green += dotColors[c].g * curDist;
            blue += dotColors[c].b * curDist;
            divider++;
        }
        outTex.SetPixel (j , i, new Color32(red/divider, green/divider, blue/divider, 255);    
    }
outTex.Apply();

最后一部分是添加一些具有整个屏幕大小的精灵并将此纹理应用于它。

所有这些只是为了让您了解如何解决它,所有这些代码都未经测试,因此您会在其中发现一些错误,但我将这项工作留给您。如果您发现任何问题,请在此处发表评论,我会回复,因为您提出了一个有趣的问题,我非常愿意帮助您。这一切都让我想起了用不同颜色的光源在它前面渲染白色 2D 纹理(这是你的点),所以尝试在网上查找人们如何编写 2D 光渲染脚本,你会发现一些有趣和有用的东西在那里。

【讨论】:

  • 我采用了您的方法并对其进行了一些更改,因此它没有将颜色混合在一起,而是使用最接近的 Dot 的颜色,实际上它确实产生了我正在寻找的确切结果,但是......在平均情况下有 2000 个点,纹理需要具有相当高的分辨率才能使结果看起来可以接受。即使是 3k * 3k 的纹理看起来也不是很好。有了这么多的数据,算法需要足够的时间让我同时做晚饭。我可以缓存结果,但它是保证随时间变化的少数事情之一
  • 你能把制作的图片或截图发给我吗?我真的很想看看它的外观,但我现在没有时间设置它 :) 需要这么长时间的问题是因为“SetPixel”非常缓慢且无效,因为每次调用它都需要一个一大堆内存,而不是为了设置一个像素的颜色而删除所有内存,尝试使用“SetPixels”docs.unity3d.com/ScriptReference/Texture2D.SetPixels.html
  • Here 是它目前的样子。我为每个点分配了一个随机颜色只是为了测试,但是一旦每个点都具有适当的颜色,它应该看起来完全符合我的需要。我现在试试 SetPixels 并比较它与 SetPixel 相比所花费的时间
  • 从 SetPixel 切换到 SetPixels 并没有加快速度。我怀疑瓶颈不是设置像素,而是遍历每个像素的所有点以及 Vector3.Distance 调用。我想不出任何方法来减少所需的检查次数
  • 请记住,您调用 Vector3.Distance 每个像素的数量取决于您拥有的点数,所以假设您以全高清分辨率运行,调用次数等于 1680* 1050*2000,也就是 350 亿次,距离是用 pythagorean 计算的,它需要平方根,而且非常昂贵,现在好在我们不需要平方根,因为我们只是在比较距离,如果一个距离的平方大于另一个距离的平方,那么第一个距离更大,没有必要计算根然后计算它们。
猜你喜欢
  • 2017-02-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-19
  • 1970-01-01
  • 2018-08-25
  • 2017-02-03
相关资源
最近更新 更多