Shader 是 GPU 端的渲染程序,XGE 支持自定义顶点/片元着色器,通过 Uniform 传递参数。
Shader 由顶点着色器(Vertex)和片元着色器(Fragment)组成。 XGE 使用 GLSL ES 语法。创建后可通过 Uniform 函数传递标量、向量参数。 Shader 使用引用计数管理,可被多个 Material 共享。
| 函数 | 说明 |
|---|---|
int xgeShaderCreate(xge_shader pShader, const char* sVertexSource, const char* sFragmentSource) | 编译着色器 |
int xgeShaderAddRef(xge_shader pShader) | 增加引用 |
void xgeShaderFree(xge_shader pShader) | 释放 |
int xgeShaderUniform1i(xge_shader pShader, const char* sName, int iX) | 设置 int uniform |
int xgeShaderUniform1f(xge_shader pShader, const char* sName, float fX) | 设置 float uniform |
int xgeShaderUniform2f(xge_shader pShader, const char* sName, float fX, float fY) | 设置 vec2 uniform |
int xgeShaderUniform3f(xge_shader pShader, const char* sName, float fX, float fY, float fZ) | 设置 vec3 uniform |
int xgeShaderUniform4f(xge_shader pShader, const char* sName, float fX, float fY, float fZ, float fW) | 设置 vec4 uniform |
gcc -O2 -I. -o ch102.exe ch102_main.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch102.exe
const char* 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";
const char* fsSrc =
"precision mediump float;\n"
"varying vec2 vUV;\n"
"uniform sampler2D uTex;\n"
"uniform float uGray;\n"
"void main() {\n"
" vec4 c = texture2D(uTex, vUV);\n"
" float g = dot(c.rgb, vec3(0.299,0.587,0.114));\n"
" gl_FragColor = mix(c, vec4(g,g,g,c.a), uGray);\n"
"}\n";
xge_shader_t shader;
xgeShaderCreate(&shader, vsSrc, fsSrc);
// 设置灰度强度
xgeShaderUniform1f(&shader, "uGray", 0.8f);将以下代码保存为 ch102_main.c,编译后运行即可看到灰度 Shader 动画效果:
#include "xge.h"
#include <math.h>
static xge_shader_t g_shader;
static xge_font g_font = NULL;
static float g_time = 0.0f;
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"
"uniform float uGray;\n"
"void main() {\n"
" vec4 c = texture2D(uTex, vUV);\n"
" float g = dot(c.rgb, vec3(0.299,0.587,0.114));\n"
" gl_FragColor = mix(c, vec4(g,g,g,c.a), uGray);\n"
"}\n";
static int onFrame(void* pUser) {
(void)pUser;
xgeClear(0x081114FF);
g_time += 0.016f;
// 动态灰度强度(0~1 循环)
float gray = 0.5f + 0.5f * sinf(g_time * 2.0f);
xgeShaderUniform1f(&g_shader, "uGray", gray);
xgeTextDraw(g_font, "Grayscale Shader (animated)",
50.0f, 50.0f, 0xFFFFFFFF)
return XGE_OK;
}
int main(void) {
xge_desc_t d = {0};
d.iWidth = 800;
d.iHeight = 600;
d.sTitle = "ch102 - Grayscale Shader";
d.iFlags = XGE_INIT_VSYNC;
xgeInit(&d);
xgeFontLoad(&g_font, "Roboto.ttf", 18.0f);
// 创建 Shader
xgeShaderCreate(&g_shader, g_vsSrc, g_fsSrc);
xgeRun(onFrame, NULL);
xgeShaderFree(&g_shader);
xgeFontFree(g_font);
xgeUnit();
return 0;
}