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

DelphiX 圖片混合模式實戰:DrawAdd 與 DrawSub 加減色效果對比

     編輯:Delphi

核心概念:加色與減色混合模式

DelphiX 提供 DrawAdd(加色/正片疊底)與 DrawSub(減色/減去)兩種進階混合模式,廣泛應用於遊戲特效、UI 高亮、陰影投射等場景。本文通過雙圖層疊加範例,直觀展示兩種模式的視覺差異與數學原理。

完整範例:背景圖 + 前景圖的混合模式對比

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DXDraws, StdCtrls, DXClass;

type
  TForm1 = class(TForm)
    DXDraw1: TDXDraw;
    DXImageList1: TDXImageList;
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  pic1, pic2: TPictureCollectionItem;  // pic1=背景, pic2=前景

procedure TForm1.FormCreate(Sender: TObject);
const
  ImgPath1 = 'C:\Temp\Back.jpg';      // 背景圖 (大尺寸)
  ImgPath2 = 'C:\Temp\DelphiX.bmp';   // 前景圖 (含透明區域)
begin
  DXImageList1.DXDraw := DXDraw1;
  
  // 載入背景圖
  pic1 := TPictureCollectionItem(DXImageList1.Items.Add);
  pic1.Picture.LoadFromFile(ImgPath1);
  
  // 載入前景圖
  pic2 := TPictureCollectionItem(DXImageList1.Items.Add);
  pic2.Picture.LoadFromFile(ImgPath2);
  
  Button1.Caption := 'DrawAdd (加色/發光)';
  Button2.Caption := 'DrawSub (減色/陰影)';
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  r: TRect;
begin
  // 計算前景圖居中底部位置
  r := Bounds(
    (DXDraw1.Width - pic2.Width) div 2,
    (DXDraw1.Height - pic2.Height),  // 底部對齊
    pic2.Width,
    pic2.Height
  );
  
  DXDraw1.Surface.Fill(0);  // 清空背景
  
  // 1. 先繪製背景圖 (拉伸填滿)
  pic1.StretchDraw(DXDraw1.Surface, DXDraw1.ClientRect, 0);
  
  // 2. 再用 DrawAdd 繪製前景圖 (加色混合)
  pic2.DrawAdd(DXDraw1.Surface, r, 0);
  
  DXDraw1.Flip;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  r: TRect;
begin
  r := Bounds(
    (DXDraw1.Width - pic2.Width) div 2,
    (DXDraw1.Height - pic2.Height),
    pic2.Width,
    pic2.Height
  );
  
  DXDraw1.Surface.Fill(0);
  
  // 1. 繪製背景
  pic1.StretchDraw(DXDraw1.Surface, DXDraw1.ClientRect, 0);
  
  // 2. 用 DrawSub 繪製前景 (減色混合)
  pic2.DrawSub(DXDraw1.Surface, r, 0);
  
  DXDraw1.Flip;
end;

end.

混合模式數學原理深度解析

DrawAdd (加色混合 / Linear Dodge / Additive)

// 每個顏色通道獨立計算
Result.R = Min(Src.R + Dest.R, 255);
Result.G = Min(Src.G + Dest.G, 255);
Result.B = Min(Src.B + Dest.B, 255);

// 等價公式:Result = Src + Dest (飽和算術)

視覺特徵:

  • 亮部疊加變更亮,純白 (255,255,255) 保持純白
  • 黑色 (0,0,0) 完全透明,不影響背景
  • 中間色調亮度提升,產生「發光」、「能量疊加」感

典型應用:

  • 火焰、爆炸、魔法光效、雷電、光劍
  • 粒子系統的加色粒子 (火花、星塵、法力特效)
  • UI 高亮選中狀態、技能冷卻完成閃爍
  • HDR 曝光模擬、Bloom 光暈後處理基礎層

DrawSub (減色混合 / Subtractive)

// 每個顏色通道獨立計算
Result.R = Max(Dest.R - Src.R, 0);
Result.G = Max(Dest.G - Src.G, 0);
Result.B = Max(Dest.B - Src.B, 0);

// 等價公式:Result = Dest - Src (飽和算術)

視覺特徵:

  • 暗部疊加變更暗,純黑 (0,0,0) 保持純黑
  • 白色 (255,255,255) 將背景完全變黑
  • 中間色調亮度降低,產生「陰影」、「遮蔽」、「能量吸收」感

典型應用:

  • 陰影投射、陰暗氣氛、地下城霧效
  • 負面狀態視覺化 (中毒、詛咒、虛弱)
  • 遮罩/蒙版效果、UI 禁用狀態置灰
  • 倒扣卡牌、記憶體洩漏視覺化 (開玩笑)

對比示意圖 (文字版)

背景像素:     R=100  G=150  B=200  (淡藍色)
前景像素:     R=200  G=100  B=50   (橙紅色)
────────────────────────────────────────────
DrawAdd 結果: R=255  G=250  B=250  (近白色,高亮)
DrawSub 結果: R=0    G=50   B=150  (深藍綠,變暗)
普通覆蓋:     R=200  G=100  B=50   (前景色完全遮蓋)
Alpha 50%:    R=150  G=125  B=125  (中間色)

進階技巧:結合透明色與混合模式

前景圖的透明區域 (由 TransparentColor + Transparent := True 定義) 在混合時會被跳過,不參與運算:

// 確保前景圖透明色正確設定
pic2.Transparent := True;
pic2.TransparentColor := clFuchsia;  // 或 clWhite, 視圖片而定

// DrawAdd/DrawSub 會自動跳過透明像素
// 只有非透明像素參與加減色運算

動畫應用:脈動發光與陰影呼吸

var
  PulsePhase: Integer = 0;
  UseAddMode: Boolean = True;

procedure TForm1.DXTimer1Timer(Sender: TObject; LagCount: Integer);
var
  r: TRect;
  Intensity: Byte;
begin
  DXDraw1.Surface.Fill(0);
  pic1.StretchDraw(DXDraw1.Surface, DXDraw1.ClientRect, 0);
  
  r := Bounds((DXDraw1.Width - pic2.Width) div 2,
              (DXDraw1.Height - pic2.Height) div 2,
              pic2.Width, pic2.Height);
  
  // 產生 0-255 正弦波脈動
  Intensity := 128 + Round(127 * Sin(PulsePhase * Pi / 128));
  Inc(PulsePhase, 4);  // 速度控制
  
  // 動態調整前景圖亮度 (通過著色實現)
  // 注意:DrawAdd/DrawSub 不直接支援強度參數
  // 需配合 DrawAddCol/DrawSubCol 或預處理圖片
  
  if UseAddMode then
    pic2.DrawAdd(DXDraw1.Surface, r, 0)
  else
    pic2.DrawSub(DXDraw1.Surface, r, 0);
  
  DXDraw1.Flip;
end;

DrawAddCol / DrawSubCol:帶顏色著色的加減色

若需「綠色發光」或「紅色陰影」,使用帶顏色版本:

// 加色 + 著色 (發光顏色可控)
pic2.DrawAddCol(DXDraw1.Surface, r, 0, clLime);    // 綠色發光
pic2.DrawAddCol(DXDraw1.Surface, r, 0, clRed);     // 紅色發光

// 減色 + 著色 (陰影顏色可控)
pic2.DrawSubCol(DXDraw1.Surface, r, 0, clBlue);    // 藍色陰影
pic2.DrawSubCol(DXDraw1.Surface, r, 0, clMaroon);  // 暗紅陰影

原理:先將前景圖非透明像素著色為指定顏色,再進行加/減色混合。

效能與最佳實踐

場景建議模式優化提示
大量粒子發光DrawAdd批次繪製相同模式粒子;使用點精靈
全屏陰影/霧效DrawSub使用單張半透明黑色矩形而非逐像素
UI 按鈕懸停高亮DrawAdd預先準備高亮版圖片,避免即時混合
技能範圍指示器DrawAddCol綠色=可施放,紅色=不可施放
負面狀態圖示DrawSubCol紫色=中毒,藍色=冰凍,黑色=沉默

常見問題與解決

問題原因解決
DrawAdd 後圖片變全白前景圖亮度過高或背景過亮降低前景圖亮度;確保背景有暗部
DrawSub 後圖片變全黑前景圖包含大量白色/高亮像素調整前景圖色調;避免純白像素
透明區域也參與混合Transparent 屬性未設定或顏色不匹配檢查 TransparentColor 與圖片實際透明色
混合效果與預期不符顏色空間差異 (sRGB vs Linear)DelphiX 在 sRGB 空間混合,注意圖片色彩配置

總結

DrawAdd 與 DrawSub 是 DelphiX 實現專業級視覺特效的核心混合模式。加色 = 發光/能量疊加,減色 = 陰影/能量吸收。結合透明色遮罩、著色變體、動態強度控制,可構建豐富的遊戲特效體系。理解其數學本質(飽和加減法)有助於預測視覺結果並設計更精確的美術資源。

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