glsl生成设计之网格噪声

网格噪声

  网格噪声基于距离场,这里的距离是指到一个特征点集最近的点的距离。比如说我们要写一个 4 个特征点的距离场,我们应该做什么呢?对每一个像素,计算它到最近的特征点的距离。也就是说,我们需要遍历所有 4 个特征点,计算他们到当前像素点的距离,并把最近的那个距离存下来。

float min_dist = 100.; // A variable to store the closest distance to a point  
    min_dist = min(min_dist, distance(st, point_a));  
    min_dist = min(min_dist, distance(st, point_b));  
    min_dist = min(min_dist, distance(st, point_c));  
    min_dist = min(min_dist, distance(st, point_d));

![在这里插入图片描述](https://img-blog.csdnimg.cn/03d1292ae212434d8226ddf2f04fb05f.png#pic_center)
#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

void main() {
    vec2 st = gl_FragCoord.xy/u_resolution.xy;
    st.x *= u_resolution.x/u_resolution.y;

    vec3 color = vec3(.0);

    // Cell positions
    vec2 point[5];
    point[0] = vec2(0.83,0.75);
    point[1] = vec2(0.60,0.07);
    point[2] = vec2(0.28,0.64);
    point[3] =  vec2(0.31,0.26);
    point[4] = u_mouse/u_resolution;

    float m_dist = 1.;  // minimum distance

    // Iterate through the points positions
    for (int i = 0; i < 5; i++) {
        float dist = distance(st, point[i]);

        // Keep the closer distance
        m_dist = min(m_dist, dist);
    }

    // Draw the min distance (distance field)
    color += m_dist;

    // Show isolines
    // color -= step(.7,abs(sin(50.0*m_dist)))*.3;

    gl_FragColor = vec4(color,1.0);
}

在这里插入图片描述

平铺和迭代

  把空间分割成网格。并不需要计算每一个像素点到每一个特征点的距离。每个像素点是在自己的线程中运行,我们可以把空间分割成网格(cells),每个网格对应一个特征点。另外,为避免网格交界区域的偏差,我们需要计算像素点到相邻网格中的特征点的距离。每个像素点只需要计算到九个特征点的距离:他所在的网格的特征点和相邻的八个网格的特征点。

// Scale
st *= 3.;
// Tile the space
vec2 i_st = floor(st);
vec2 f_st = fract(st);


![在这里插入图片描述](https://img-blog.csdnimg.cn/3adc5f25f8994defa72d9f45963eba90.png#pic_center)   我们将使用网格坐标(存储在整数坐标 i_st 中)来构造特征点的随机位置。random2f 函数接受一个 vec2 类型参数,返回给我们一个 vec2 类型的随机位置。所以,在每个网格内,我们有一个特征点在随机位置上。

vec2 point = random2(i_st);

网格内的每个像素点(存储在浮点坐标 f_st 中)都会计算它到那个随机点的距离。

vec2 diff = point - f_st;
float dist = length(diff);


我们还需要计算像素点到相邻网格中随机点的距离,而不只是当前的网格。我们需要 遍历 所有相邻网格。不是所有网格,仅仅是那些和当前网格相邻的网格。从网格坐标来说,就是 x 坐标从 -1 (左)到 1 (右), y 坐标从 -1 (下)到 1 (上)。一个 9 个网格的 3x3 区域可以用两个 for 循环遍历:

for (int y= -1; y <= 1; y++) {
    for (int x= -1; x <= 1; x++) {
        // Neighbor place in the grid
        vec2 neighbor = vec2(float(x),float(y));
        ...
    }
}

在这里插入图片描述

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;

vec2 random2( vec2 p ) {
    return fract(sin(vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3))))*43758.5453);
}

void main() {
    vec2 st = gl_FragCoord.xy/u_resolution.xy;
    st.x *= u_resolution.x/u_resolution.y;
    vec3 color = vec3(.0);

    // Scale
    st *= 3.;

    // Tile the space
    vec2 i_st = floor(st);
    vec2 f_st = fract(st);

    float m_dist = 1.;  // minimum distance

    for (int y= -1; y <= 1; y++) {
        for (int x= -1; x <= 1; x++) {
            // Neighbor place in the grid
            vec2 neighbor = vec2(float(x),float(y));

            // Random position from current + neighbor place in the grid
            vec2 point = random2(i_st + neighbor);

			// Animate the point
            point = 0.5 + 0.5*sin(u_time + 6.2831*point);

			// Vector between the pixel and the point
            vec2 diff = neighbor + point - f_st;

            // Distance to the point
            float dist = length(diff);

            // Keep the closer distance
            m_dist = min(m_dist, dist);
        }
    }

    // Draw the min distance (distance field)
    color += m_dist;

    // Draw cell center
    color += 1.-step(.02, m_dist);

    // Draw grid
    color.r += step(.98, f_st.x) + step(.98, f_st.y);

    // Show isolines
    // color -= step(.7,abs(sin(27.0*m_dist)))*.5;

    gl_FragColor = vec4(color,1.0);
}

在这里插入图片描述

这个算法也可以从特征点而非像素点的角度理解。在那种情况下,算法可以表述为:每个特征点向外扩张生长,直到它碰到其它扩张的区域。这反映了自然界的生长规则。生命的形态是由内部扩张、生长的力量和限制性的外部力量共同决定的。模拟这种行为的算法以 Georgy Voronoi 命名。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值