线性插值返回重复的块状图像

时间:2016-01-23 20:40:18

标签: c# interpolation unity5

所以,我试图想出我自己的Perlin / Fractal噪声的简单实现(我只是将噪声添加到自身重新采样多次)。

当涉及到算法的重采样部分时,为了在阵列的较小部分上使用双线性插值来实现较低频率的噪声,以有效地"拉伸"较小的部分(即:查看256x256噪声片的16x16部分,但将其视为256x256像素阵列)

我使用的网站(嗯,其中一个)供参考,http://lodev.org/cgtutor/randomnoise.html

从网站上看,前两张图片是我正在寻找的结果,但我得到的是这样的(我使用的是64x64阵列):

Original

Resampled using x8 Zoom

我使用的所有代码都在Unity中(我知道它有一个内置的Perlin生成器,但我想要自己的代码):

using UnityEngine;

使用System.Collections;

公共类NoiseGenerator:MonoBehaviour {

//Dimensions of the array
public int width;
public int height;

//RNG Stuff for reproducability
public bool useTimeAsSeed;
public string seed;

//The array the nopise gets stored in
int[,] noise;

//These are used in the editor to control if we zoon in or not, original image gets resized to 1/ratio
public bool zoom;
public int ratio=1;


//Function used to fill up the array with white noise (random numbers with a uniform distribution between 0-255)
void InitNoise() {
    noise = new int[width, height];
    if (useTimeAsSeed) {
        seed = Time.time.ToString();
    }
    System.Random r = new System.Random(seed.GetHashCode());
    for (int x = 0; x < width; x++) {
        for (int y = 0; y < height; y++) {
            noise[x, y] = r.Next(0,256);                
        }
    }       
}


//Function to smooth the noise when it's being resampled
/*
    AB
    CD
    |when resampled
    v
    A--R---B
    |  X   | 
    |      |
    |      |
    C--J---D

    Uses bilinear Interpolation to get the wighted average of A B C and D, which are all neighbouring pixels in the original picture
    Returns an int value between 0-255
*/
int SmoothNoise(float x, float y) {
    float fractX = x - (int)x; //Fractional part of the X-coord, used as the weight for Lerping in the x-direction
    float fractY = y - (int)y; //Fractional part of the Y-coord, used as the weight for Lerping in the y-direction
    //Calculating the neigbouring pixels
    //For edge values the respective "missing pixel" is filled in by the other end of the noise sheet
    int x1 = ((int)x + width) % width;
    int x2 = (x1 + width - 1) % width;
    int y1 = ((int)y + height) % height;
    int y2 = (y1 + height - 1) % height;
    //Calculating R and J by Lerping the respective pixels
    float R = Mathf.Lerp(noise[x1, y1], noise[x2, y1], fractX);
    float J = Mathf.Lerp(noise[x2, y1], noise[x2, y2], fractX);
    //Finally Lerp R and J to get the value for X
    return (int)(Mathf.Lerp(R,J,fractY));
}

void Start() {
    InitNoise();        
}
//Easy way to display the array as a temporary solution until actual terrain display is implemented
void OnDrawGizmos() {
    if (noise != null) {
        for (int x = 0; x < width; x++){
            for (int y = 0; y < height; y++){
                float component = (float)noise[x, y] / 255;
                if (zoom) {
                    //Using the result of SmoothNoise normalised to be between 0-1 we construct a color component to be used when displaying
                    component = (float)SmoothNoise((float)x/ratio, (float)y/ratio) / 255;
                }                    
                Gizmos.color = new Color(component,component,component);
                Vector3 pos = new Vector3(-width/2 + x + .5f, 0, -height/2 + y + .5f);
                Gizmos.DrawCube(pos, Vector3.one);
            }
        }
    }
}

}

0 个答案:

没有答案