Chapter 11 · 渲染管线

清屏与颜色模型

理解 XGE 的 RGBA8 打包颜色格式、清屏操作,以及颜色宏与工具函数的使用。

11

概念:RGBA8 打包颜色

XGE 中所有颜色都以 uint32_t 表示,按 RGBA 顺序打包在 32 位中。每个通道占 8 位(0–255)。这与常见的 HTML/CSS 的 #RRGGBBAA 格式一致。

// 内存布局(高位 → 低位):
// [31..24] R  [23..16] G  [15..8] B  [7..0] A
//
// 示例:琥珀色不透明
// R=0xFF G=0xB4 B=0x54 A=0xFF → 0xFFB454FF

API 速查

函数 / 宏说明
void xgeClear(uint32_t iColor)以指定颜色清除整个帧缓冲
XGE_COLOR_RGBA(r, g, b, a)宏:从 4 个 0–255 分量打包为 uint32_t
XGE_COLOR_GET_R(c)宏:提取红色分量
XGE_COLOR_GET_G(c)宏:提取绿色通道
XGE_COLOR_GET_B(c)宏:提取蓝色通道
XGE_COLOR_GET_A(c)宏:提取 Alpha 通道
uint32_t xgeColorRGBA(int r, int g, int b, int a)函数版打包(运行时值)
xge_color_t xgeColorUnpack(uint32_t c)解包为浮点 RGBA(0.0–1.0)

示例 1:基本清屏

编译本章示例

gcc -O2 -I. -o ch11.exe ch11_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch11.exe
static int onFrame(void* pUser) {
    // 方式 1:直接写十六进制字面量
    xgeClear(0x081114FF);  // 深石油蓝

    // 方式 2:用宏从分量构建(编译期常量)
    // xgeClear(XGE_COLOR_RGBA(8, 17, 20, 255));

    return XGE_OK;
}

示例 2:动态颜色(渐变背景)

static int onFrame(void* pUser) {
    double t = xgeTimer();

    // R 通道随时间正弦变化
    int r = (int)(128 + 127 * sin(t * 0.5));
    int g = 17;
    int b = 20;

    // 运行时打包(不能用宏,因为值不是常量)
    uint32_t color = xgeColorRGBA(r, g, b, 255);
    xgeClear(color);

    return XGE_OK;
}

示例 3:颜色解包与分量操作

uint32_t amber = 0xFFB454FF;

// 用宏提取分量
int r = XGE_COLOR_GET_R(amber);  // 255
int g = XGE_COLOR_GET_G(amber);  // 180
int b = XGE_COLOR_GET_B(amber);  // 84
int a = XGE_COLOR_GET_A(amber);  // 255

// 解包为浮点(用于 shader 或混合计算)
xge_color_t c = xgeColorUnpack(amber);
// c.fR=1.0, c.fG=0.706, c.fB=0.329, c.fA=1.0

// 修改 Alpha 后重新打包
uint32_t semi = XGE_COLOR_RGBA(r, g, b, 128);  // 50% 透明

常用颜色速查

颜色十六进制RGBA 分量
深石油蓝(背景)0x081114FF8, 17, 20, 255
琥珀色0xFFB454FF255, 180, 84, 255
青绿色0x4FD8C2FF79, 216, 194, 255
珊瑚红0xFF6B5EFF255, 107, 94, 255
天蓝色0x6DB3F2FF109, 179, 242, 255
纯白0xFFFFFFFF255, 255, 255, 255
纯黑0x000000FF0, 0, 0, 255
全透明0x000000000, 0, 0, 0

完整代码

将以下代码保存为 ch11_main.c,编译后运行即可看到动态渐变背景:

#include "xge.h"
#include <math.h>

static int onFrame(void* pUser) {
    (void)pUser;
    double t = xgeTimer();

    // R 通道随时间正弦变化
    int r = (int)(128 + 127 * sin(t * 0.5));
    uint32_t color = xgeColorRGBA(r, 17, 20, 255);
    xgeClear(color);

    return XGE_OK;
}

int main(void) {
    xge_desc_t d = {0};
    d.iWidth  = 800;
    d.iHeight = 600;
    d.sTitle  = "ch11 - Color Model";
    d.iFlags  = XGE_INIT_VSYNC;
    xgeInit(&d);
    xgeRun(onFrame, NULL);
    xgeUnit();
    return 0;
}

代码讲解

  • xgeTimer() 返回引擎启动以来的秒数,用于驱动动画。
  • xgeColorRGBA(r,g,b,a) 是函数版颜色打包,接受运行时变量(宏版 XGE_COLOR_RGBA 要求编译期常量)。
  • 帧回调返回 XGE_OK 保持循环;关闭窗口或按 Alt+F4 退出。

要点与陷阱

  • Alpha = 0 不等于黑色——Alpha 0 表示完全透明。清屏时 Alpha 通常设为 255。
  • 宏 vs 函数:XGE_COLOR_RGBA 是宏,参数必须是编译期可求值的表达式;xgeColorRGBA 是函数,接受运行时变量。
  • 字节序无关:XGE 的颜色打包是逻辑定义(R 在最高位),不受 CPU 大小端影响。
  • xgeClear 必须在 Begin/End 之间——在帧外调用无效。
  • 预乘 Alpha:XGE 内部使用预乘 Alpha 混合。如果你手动计算颜色,需要 R' = R × A / 255。

进阶练习

  1. 实现一个 HSL → RGBA 转换函数,用 xgeColorRGBA 输出,让背景色相每帧旋转 1°。
  2. 用 xgeColorUnpack 获取浮点分量,实现两个颜色的线性插值(lerp)。
  3. 编写一个颜色选择器:用键盘 R/G/B/A 键增减各分量,实时清屏显示结果。
清屏与颜色模型效果
图:清屏与颜色模型渲染效果