首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC++

從火焰算法到光牆特效:調色盤索引動畫的實現詳解

     編輯:VC++

效果預覽

光牆效果演示圖

核心原理:火焰算法的本質

經典的實時火焰效果基於「調色盤索引遞減」與「鄰域平均模糊」兩大支柱:

  1. 調色盤構建:建立一個 256 色的漸變調色盤,從黑(索引 0)到亮白(索引 255),中間經過深紅、亮紅、橙、黃等過渡色。
  2. 燃料注入:在緩衝區底部隨機寫入高索引值(亮色),模擬火焰根部最亮。
  3. 向上傳播與衰減:每幀從下往上掃描,當前像素索引 = 下方像素索引 - 1(衰減),索引不小於 0。
  4. 模糊平滑:取周圍 3x3 或 5x5 鄰域平均值,消除條狀感,產生自然擾動。
  5. 映射顯示:將索引緩衝區通過調色盤映射為真彩色輸出到屏幕。

調色盤生成代碼(16-bit 555 模式)

WORD palette[256];
ZeroMemory(palette, sizeof(palette));

for (int i = 0; i < 64; ++i) {
    // 0-63: 黑 -> 深紅 (僅紅分量漸增)
    palette[i] = (i/2) << 10;                     // R 分量在 bit 10-14
    // 64-127: 深紅 -> 亮黃 (紅滿,綠漸增)
    palette[i+64]  = 0x7C00 | ((i/2) << 5 & 0x3E0); // G 分量在 bit 5-9
    // 128-191: 亮黃 -> 亮白 (紅綠滿,藍漸增)
    palette[i+128] = 0x7C00 | 0x3E0 | (i/2 & 0x1F); // B 分量在 bit 0-4
    // 192-255: 全白
    palette[i+191] = 0xFFFF;
}

註:0x7C00 = 紅滿 (31<<10),0x3E0 = 綠滿 (31<<5)。此調色盤可直接用於 16-bit 顯示模式;若為 24/32-bit 則需擴展為 RGBQUAD 陣列。

火焰緩衝區與渲染循環

// 緩衝區:索引值,char 足夠 (0-255)
char fireBuf[320][220]; // 假設 320x200 可見區,底部留 2 行作燃料區

// 每幀:注入燃料 (底部第 2 行)
for (int x = 0; x < 320; ++x) {
    int j = rand() * 320 / RAND_MAX;
    fireBuf[218][j] = (rand() / (float)RAND_MAX > 0.5f) ? 255 : 0; // 隨機亮/暗顆粒
}

// 從上往下渲染 (y=0 為頂部)
for (int y = 0; y < 218; ++y) {
    for (int x = 0; x < 320; ++x) {
        // 簡單衰減:取正下方像素索引 -1
        fireBuf[y][x] = (fireBuf[y+1][x] > 0) ? fireBuf[y+1][x] - 1 : 0;
    }
}

// 可選:3x3 平均模糊
// for (y=1; y<217; ++y) for (x=1; x<319; ++x)
//     fireBuf[y][x] = (fireBuf[y-1][x-1]+fireBuf[y-1][x]+fireBuf[y-1][x+1]
//                    +fireBuf[y][x-1]+fireBuf[y][x]+fireBuf[y][x+1]
//                    +fireBuf[y+1][x-1]+fireBuf[y+1][x]+fireBuf[y+1][x+1]) / 9;

// 映射到顯存 (伪代碼)
for (y=0; y<200; ++y) for (x=0; x<320; ++x)
    screen[y][x] = palette[fireBuf[y][x]];

從火焰到光牆:只需改變傳播方向

火焰是「從下往上」渲染(y 遞增),光牆則是「從左往右」或「從右往左」水平傳播。只需將雙重循環的遍歷順序改為水平方向:

// 光牆:從左往右 (x 遞增)
for (int x = 1; x < 319; ++x) {
    for (int y = 0; y < 200; ++y) {
        fireBuf[y][x] = (fireBuf[y][x-1] > 0) ? fireBuf[y][x-1] - 1 : 0;
    }
}
// 燃料注入在最左列 (x=0)
for (int y = 0; y < 200; ++y) {
    if (rand()/(float)RAND_MAX > 0.5f) fireBuf[y][0] = 255;
}

同理,垂直光牆(從上往下)只需將火焰循環的 y 方向反轉:for (int y = height-2; y > 0; --y)。

調色盤技術的現代價值

  • 極低運算量:只需整數加減、查表,無浮點、無像素級色彩運算,適合嵌入式、舊硬體、WebAssembly 等受限環境。
  • 藝術可控性強:調色盤即藝術資源,設計師可直接繪製 1x256 漸變圖,程序只負責索引運算。
  • 易於擴展:同一索引緩衝區可同時映射多套調色盤(如白天/夜晚、冰/火),實現場景瞬間切換。

完整 Demo 專案建議結構

LightWall/
├── Palette.cpp/h      // 調色盤生成、載入、保存
├── Buffer.cpp/h       // 索引緩衝區分配、燃料注入、傳播、模糊
├── Renderer.cpp/h     // 將索引緩衝區 Blit 到屏幕 (GDI/DirectDraw/OpenGL 紋理)
├── Main.cpp           // 消息循環、定時器驅動幀更新
└── Resource/          // 預設調色盤圖片、圖示

本文旨在傳遞「索引動畫」的核心思想:將色彩運算與幾何演化分離。掌握此法,可輕鬆實作火焰、光牆、水波、電弧、魔法光環等諸多經典特效,並在現代引擎中作為 Shader 的靈感原型。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved