Raylib Alpha混合异常求助:按钮高亮效果不符合预期
Raylib 2D按钮高亮:白色遮罩变暗问题的无Shader解决方案
问题根源
你遇到的是Raylib默认BLEND_ALPHA混合模式的颜色叠加逻辑问题:
默认混合公式为:最终色 = 源色 * 源透明度 + 目标色 * (1 - 源透明度)
当白色遮罩的透明度较低(如0.33),且按钮原图颜色偏暗时,目标色的占比(1-0.33=0.67)远高于白色的占比,导致混合后颜色比原按钮更暗。如果遮罩精灵本身还带有alpha通道,实际透明度会进一步降低,变暗效果更明显。
无自定义Shader解决方案
以下三种方法均基于Raylib内置功能,无需编写Shader:
方案1:使用BLEND_ADDITIVE混合模式(推荐)
ADDITIVE模式的混合逻辑是最终色 = 目标色 + 源色 * 源透明度,白色遮罩的增量会直接加到按钮颜色上,从根源避免变暗问题,过渡更自然。
修改后的绘制代码:
// 绘制基础按钮 DrawTexturePro(GCN::TG->tex_grid_menubuts, (Rectangle){0, 32.0f*t, 320, 32}, (Rectangle){(float)x, (float)y, (float)320, (float)32}, (Vector2){0, 0}, 0.0f, (Color){255, 255, 255, 255}); if (hi > 0) { float alpha = hi_alph * hi / hi_max; BeginBlendMode(BLEND_ADDITIVE); // 绘制白色高亮遮罩 DrawTexturePro(GCN::TG->tex_grid_menubuts, (Rectangle){320, 32.0f*t, 320, 32}, (Rectangle){(float)x, (float)y, (float)320, (float)32}, (Vector2){0, 0}, 0.0f, (Color){255, 255, 255, (unsigned char)round(alpha * 255)}); EndBlendMode(); } // 绘制按钮文本 DrawTextEx(GCN::TG->fnt_AL, disp_text.c_str(), (Vector2){(float)(x + w/2 - MeasureTextEx(GCN::TG->fnt_AL, disp_text.c_str(), 24.0f, 1.0f).x/2), (float)(y+6)}, 24.0f, 1.0f, (Color){0, 0, 0, 255});
- 建议将
hi_alph调整至0.2~0.4区间,避免高亮过度刺眼。
方案2:预乘Alpha配合BLEND_ALPHA_PREMULTIPLY模式
预乘Alpha是将RGB值先与透明度相乘,再使用预乘混合模式,公式为最终色 = 源色 + 目标色 * (1 - 源透明度),确保白色的权重足够,不会被目标色压制。
修改后的绘制代码:
// 绘制基础按钮 DrawTexturePro(GCN::TG->tex_grid_menubuts, (Rectangle){0, 32.0f*t, 320, 32}, (Rectangle){(float)x, (float)y, (float)320, (float)32}, (Vector2){0, 0}, 0.0f, (Color){255, 255, 255, 255}); if (hi > 0) { float alpha = hi_alph * hi / hi_max; unsigned char alphaByte = (unsigned char)round(alpha * 255); // 生成预乘Alpha的白色 Color premultipliedWhite = {(unsigned char)(255 * alpha), (unsigned char)(255 * alpha), (unsigned char)(255 * alpha), alphaByte}; BeginBlendMode(BLEND_ALPHA_PREMULTIPLY); DrawTexturePro(GCN::TG->tex_grid_menubuts, (Rectangle){320, 32.0f*t, 320, 32}, (Rectangle){(float)x, (float)y, (float)320, (float)32}, (Vector2){0, 0}, 0.0f, premultipliedWhite); EndBlendMode(); } // 绘制按钮文本 DrawTextEx(GCN::TG->fnt_AL, disp_text.c_str(), (Vector2){(float)(x + w/2 - MeasureTextEx(GCN::TG->fnt_AL, disp_text.c_str(), 24.0f, 1.0f).x/2), (float)(y+6)}, 24.0f, 1.0f, (Color){0, 0, 0, 255});
方案3:直接绘制纯色高亮矩形(无需遮罩精灵)
如果遮罩仅为纯色按钮形状,可直接用DrawRectanglePro替代遮罩精灵,减少资源依赖,效果更可控:
// 绘制基础按钮 DrawTexturePro(GCN::TG->tex_grid_menubuts, (Rectangle){0, 32.0f*t, 320, 32}, (Rectangle){(float)x, (float)y, (float)320, (float)32}, (Vector2){0, 0}, 0.0f, (Color){255, 255, 255, 255}); if (hi > 0) { float alpha = hi_alph * hi / hi_max; BeginBlendMode(BLEND_ADDITIVE); // 直接绘制带透明度的白色矩形覆盖按钮 DrawRectanglePro((Rectangle){(float)x, (float)y, 320, 32}, (Vector2){0,0}, 0.0f, (Color){255,255,255, (unsigned char)round(alpha*255)}); EndBlendMode(); } // 绘制按钮文本 DrawTextEx(GCN::TG->fnt_AL, disp_text.c_str(), (Vector2){(float)(x + w/2 - MeasureTextEx(GCN::TG->fnt_AL, disp_text.c_str(), 24.0f, 1.0f).x/2), (float)(y+6)}, 24.0f, 1.0f, (Color){0, 0, 0, 255});
内容的提问来源于stack exchange,提问作者DrZ214
相关产品推荐
相关产品推荐

