在模拟数字篝火的项目中我们将火焰的形状、明度、色彩等特征进行了提取,试图通过程序的方式将火焰通过数字的形式复现出来,并在其中可以引入可供调整的变量,在此记录下整个程序的实现思路。
火焰的特征

火焰本质上是一种无序随机的等离子化学反应,但又有以下的一些特征:
(1)通常火焰底部为更为鲜艳和明亮,呈现出鲜艳的黄色色彩。
(2)从火焰底部自下而上亮度会逐步递减,且色彩会逐步变深向深红、褐红色靠近。
(3)每一支火焰的高度是随机跳跃的,整体成团状。

以上三种特征将会作为程序实现的思路。
程序的实现
在第一篇文章中提到,笔者使用了FastLED库对1024颗WS2812的LED阵列进行驱动,这个Arduino提供了一系列非常方便地函数对于LED阵列进行快速驱动,接下来的程序也将使用到这个库。
void Fire()
{
// 每颗LED的热量参数
static uint8_t heat[NUM_LEDS];
// Step 1. 冷却每个单元格,使火焰变冷
for( int i = 0; i < NUM_LEDS; i++) {
heat[i] = qsub8( heat[i], random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
}
// Step 2. 热量从每个单元格向上扩散
for( int k= NUM_LEDS - 1; k >= 2; k--) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 3] ) / 3;
}
// Step 3. 随机点燃底部的新火花
if( random8() < SPARKING ) {
int y = random8(7);
heat[y] = qadd8( heat[y], random8(160,255) );
}
// Step 4. 将热量值映射到颜色,通过调色板生成颜色
for( int j = 0; j < NUM_LEDS; j++) {
// Scale the heat value from 0-255 down to 0-240
// for best results with color palettes.
uint8_t colorindex = scale8( heat[j], 240);
CRGB color = ColorFromPalette( gPal, colorindex);
int pixelnumber;
if( gReverseDirection ) {
pixelnumber = (NUM_LEDS-1) - j;
} else {
pixelnumber = j;
}
leds[pixelnumber] = color;
}
这是一段基于fire2012进行修改的得到的实现火焰效果的核心程序:
1、热量参数数组
static uint8_t heat[NUM_LEDS];
这是一个静态数组,用于存储每个LED的热量值。由于使用static修饰符,这个数组在函数调用之间保留其值。
2、火焰的冷却
for (int i = 0; i < NUM_LEDS; i++) {
heat[i] = qsub8(heat[i], random8(0, ((COOLING * 10) / NUM_LEDS) + 2));
}
每个LED的热量会减少,qsub8函数确保热量不会低于0。减少的量是随机的,取决于COOLING参数,形成自然的冷却效果。
3、热量的扩散
for (int k = NUM_LEDS - 1; k >= 2; k--) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3;
}
这里的逻辑是将每个LED的热量更新为其下方LED的热量的平均值。这样,热量会逐渐向上扩散,模拟火焰向上的流动。
4、随机产生新的火花
if (random8() < SPARKING) {
int y = random8(7);
heat[y] = qadd8(heat[y], random8(160, 255));
}
5、将heat[]映射到LED真实的RGB色彩
for (int j = 0; j < NUM_LEDS; j++) {
uint8_t colorindex = scale8(heat[j], 240);
CRGB color = ColorFromPalette(gPal, colorindex);
int pixelnumber;
if (gReverseDirection) {
pixelnumber = (NUM_LEDS - 1) - j;
} else {
pixelnumber = j;
}
leds[pixelnumber] = color;
}
将热量值缩放到0-240范围内,以适应调色板的颜色索引。使用ColorFromPalette()函数从指定的调色板中获取相应的颜色。最后,根据是否反向显示,将颜色应用到相应的LED上。
其中可以调整的变量参数:
COOLING:控制火焰冷却的速度,较低值会使火焰变高,较高值则会使火焰较短。
SPARKING:控制新火花点燃的概率,较高值使火焰更旺盛,较低值则使火焰更闪烁。
通过这些参数可以对火焰的特征进行一定程度的调整,包括火焰大小幅度,且修改代码可调整色彩不局限于常规的火焰。
通过以上代码实现了火焰模拟的过程,且通过表面的磨砂亚克力板进一步对图像进行了模糊化处理进而呈现出更为比逼真的效果。
1 comment