VariantSet 管理同一 Shader 的多个编译变体(通过宏定义区分),按需编译并缓存。
同一渲染效果可能需要多个 Shader 变体(如:有/无法线贴图、有/无雾效)。 VariantSet 以源码模板 + 宏定义组合为 Key,按需编译并缓存变体, 避免手动管理大量 Shader 对象。
| 函数 | 说明 |
|---|---|
int xgeShaderVariantSetInit(xge_shader_variant_set pSet, const char* sVertexSource, const char* sFragmentSource) | 初始化变体集 |
void xgeShaderVariantSetFree(xge_shader_variant_set pSet) | 释放变体集 |
int xgeShaderVariantGet(xge_shader_variant_set pSet, uint32_t iKey, const xge_shader_define_t* pDefines, int iDefineCount, xge_shader* ppShader) | 获取/编译变体 |
gcc -O2 -I. -o ch103.exe ch103_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch103.exe
// 片元着色器模板(含条件编译)
const char* fsSrc =
"precision mediump float;\n"
"varying vec2 vUV;\n"
"uniform sampler2D uTex;\n"
"#ifdef ENABLE_FOG\n"
"uniform float uFogDensity;\n"
"#endif\n"
"void main() {\n"
" vec4 c = texture2D(uTex, vUV);\n"
"#ifdef ENABLE_FOG\n"
" c.rgb = mix(c.rgb, vec3(0.8), uFogDensity);\n"
"#endif\n"
" gl_FragColor = c;\n"
"}\n";
xge_shader_variant_set_t vs;
xgeShaderVariantSetInit(&vs, vsSrc, fsSrc);
// 获取无雾变体
xge_shader shaderPlain;
xgeShaderVariantGet(&vs, 0, NULL, 0, &shaderPlain);
// 获取有雾变体
xge_shader_define_t defs[1] = {
{ "ENABLE_FOG", "1" }
};
xge_shader shaderFog;
xgeShaderVariantGet(&vs, 1, defs, 1, &shaderFog);将以下代码保存为 ch103_main.c,编译后运行即可看到 Shader 变体集与条件编译效果:
#include "xge.h"
static xge_shader_variant_set_t g_vs;
static xge_shader g_shaderPlain;
static xge_shader g_shaderFog;
static xge_font g_font = NULL;
static const char* g_vsSrc =
"attribute vec2 aPos;\n"
"attribute vec2 aUV;\n"
"varying vec2 vUV;\n"
"void main() {\n"
" vUV = aUV;\n"
" gl_Position = vec4(aPos, 0.0, 1.0);\n"
"}\n";
static const char* g_fsSrc =
"precision mediump float;\n"
"varying vec2 vUV;\n"
"uniform sampler2D uTex;\n"
"#ifdef ENABLE_FOG\n"
"uniform float uFogDensity;\n"
"#endif\n"
"void main() {\n"
" vec4 c = texture2D(uTex, vUV);\n"
"#ifdef ENABLE_FOG\n"
" c.rgb = mix(c.rgb, vec3(0.8), uFogDensity);\n"
"#endif\n"
" gl_FragColor = c;\n"
"}\n";
static int onFrame(void* pUser) {
(void)pUser;
xgeClear(0x081114FF);
xgeTextDraw(g_font, "Variant 0: Plain (no fog)",
50.0f, 50.0f, 0xFFFFFFFF)
xgeTextDraw(g_font, "Variant 1: ENABLE_FOG",
50.0f, 100.0f, 0x88CCFFFF)
xgeTextDraw(g_font,
"Same source, different #define combinations",
50.0f, 150.0f, 0xAAAAAAFF)
return XGE_OK;
}
int main(void) {
xge_desc_t d = {0};
d.iWidth = 800;
d.iHeight = 600;
d.sTitle = "ch103 - Shader Variants";
d.iFlags = XGE_INIT_VSYNC;
xgeInit(&d);
xgeFontLoad(&g_font, "Roboto.ttf", 18.0f);
// 初始化变体集
xgeShaderVariantSetInit(&g_vs, g_vsSrc, g_fsSrc);
// 获取无雾变体
xgeShaderVariantGet(&g_vs, 0, NULL, 0,
&g_shaderPlain);
// 获取有雾变体
xge_shader_define_t defs[1] = {
{ "ENABLE_FOG", "1" }
};
xgeShaderVariantGet(&g_vs, 1, defs, 1,
&g_shaderFog);
xgeRun(onFrame, NULL);
xgeShaderVariantSetFree(&g_vs);
xgeFontFree(g_font);
xgeUnit();
return 0;
}