opengl - 在 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 内核扩展到更大的内核会改善这种情况吗?
解决方案
(移自评论)
这很可能是一个精度问题——您是否将其渲染为 8 位目标?您可能至少需要一个 32 位浮点数。
由于您使用现代 OpenGL,因此最好glTextureStorage2D
使用GL_RGBA32F
. internalformat
没有“我的 GL 纹理的默认格式是 8 位 RGBA”之类的东西,除非您使用旧版 API、非标准扩展或直接在屏幕上渲染。
推荐阅读
- elasticsearch - 除了直方图和 date_histogram 之外,是否可以在聚合的子聚合中进行管道聚合?
- flutter - 发生 Flutter 运行时异常。_TypeError(类型'列表
' 不是类型 'String' 的子类型) - wifi - 无法在同一个 5Ghz wi-fi 网络中从手机连接到 PC,而 2.4 工作正常
- mysql - where('videos.created_at', '>', '2020.07.26 14:16:29') 不适用于左连接表 - Eloquent,Laravel
- python - 根据 pandas 中另一列中存在的条件对列执行 True/False 操作
- html - 如果 'cc-sub-header-title' 是一个 Angular 组件,那么验证它是这个模块的一部分
- php - 如何将相同的页面连接到后端的不同数据并使它们适用于各自的数据?
- reactjs - 使用 React 通过该数组中的组件事件从数组中删除一行
- javascript - 从 QWebEngineView 自动登录到网站
- driver - 从 ESP32 驱动 TMC5160