首页 > 解决方案 > 在 GLSL 中模拟扩散方程

问题描述

我正在尝试模拟 glsl 中的扩散(而不是Gray Scott 反应扩散方程),但我似乎很难让它正常工作。到目前为止,在我所有的测试中,扩散都会在某个点停止,并在我预期之前很久就达到平衡。

我的 glsl 代码:

#version 460
#define KERNEL_SIZE 9

float kernel[KERNEL_SIZE];
vec2 offset[KERNEL_SIZE];

uniform float width;
uniform float height;
uniform sampler2D current_concentration_tex;
uniform float diffusion_constant; // rate of diffusion of U

in vec2 vTexCoord0;

out vec4 fragColor;

void main(void)
{
    float w         = 1.0/width;
    float h         = 1.0/height;

    kernel[0] = 0.707106781;
    kernel[1] = 1.0;
    kernel[2] = 0.707106781;
    kernel[3] = 1.0;
    kernel[4] = -6.82842712;
    kernel[5] = 1.0;
    kernel[6] = 0.707106781;
    kernel[7] = 1.0;
    kernel[8] = 0.707106781;

    offset[0] = vec2( -w, -h);
    offset[1] = vec2(0.0, -h);
    offset[2] = vec2(  w, -h);

    offset[3] = vec2( -w, 0.0);
    offset[4] = vec2(0.0, 0.0);
    offset[5] = vec2(  w, 0.0);

    offset[6] = vec2( -w, h);
    offset[7] = vec2(0.0, h);
    offset[8] = vec2(  w, h);

    float chemical_density = texture( current_concentration_tex, vTexCoord0 ).r; // reference texture from last frame

    float laplacian;

    for( int i=0; i<KERNEL_SIZE; i++ ){
        float tmp = texture( current_concentration_tex, vTexCoord0 + offset[i] ).r;
        laplacian += tmp * kernel[i];
    }

    float du = diffusion_constant * laplacian; // diffusion equation
    chemical_density += du; // diffuse; dt * du
    //chemical_density *= 0.9999; // decay

    fragColor = vec4( clamp(chemical_density, 0.0, 1.0 ), 0.0, 0.0, 1.0 );
}

如果扩散模拟工作正常,我希望每帧都绘制一个“源”,并让化学扩散远离源慢慢地进入帧的其余部分。然而,扩散似乎提前“停止”并且不会进一步消退。例如,当我在中心绘制一个恒定环作为源时:

来自扩散模拟的样本图像

我还尝试了在中心使用一次性化学物质的初始条件,没有添加额外的化学物质——同样,我希望它会褪色到零(均匀分布在整个框架上),但它停止的时间要早​​得多我希望:

在此处输入图像描述

我在 glsl 中的模拟代码有问题吗?或者这更像是一种数值方法的问题?从 3x3 内核扩展到更大的内核会改善这种情况吗?

标签: openglglslsimulationcinder

解决方案


(移自评论)

这很可能是一个精度问题——您是否将其渲染为 8 位目标?您可能至少需要一个 32 位浮点数。

由于您使用现代 OpenGL,因此最好glTextureStorage2D使用GL_RGBA32F. internalformat没有“我的 GL 纹理的默认格式是 8 位 RGBA”之类的东西,除非您使用旧版 API、非标准扩展或直接在屏幕上渲染。


推荐阅读