You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GLSL着色器为何将深色及亮色转换为绿色?

问题分析与修复方案

问题根源

你的代码里有三个关键问题导致了颜色异常:

  • 错误的亮度计算:dot(Color, vec3(1))只是把RGB三个通道的值加起来,这不是符合人眼感知的亮度(Luma)。正确的亮度需要根据RGB通道的视觉权重计算,比如BT.709标准的权重是红0.2126、绿0.7152、蓝0.0722。错误的亮度计算会让高/低亮度场景下的mix逻辑完全偏离预期。
  • 除以0的精度风险:当颜色接近黑色时,dot(Color, vec3(1.0))会趋近于0,直接做除法会引发数值溢出或精度崩溃,最终导致颜色偏绿(绿色通道数值相对突出时就会出现这种情况)。
  • 极端参数的指数计算:如果LumaMask过小或者Luma过高,-Luma * 2 * PI / LumaMask的绝对值会变得极大,exp的结果要么趋近于0要么趋近于1,mix操作会直接偏向某一端,放大计算误差。

修复后的代码

vec3 ExtractColor(vec3 Color, float LumaMask)
{
    // 使用BT.709标准的亮度权重计算真实Luma
    const vec3 lumaWeights = vec3(0.2126, 0.7152, 0.0722);
    float Luma = dot(Color, lumaWeights);
    
    // 钳制LumaMask避免极端值,防止指数计算溢出
    LumaMask = max(LumaMask, 0.001);
    float ColorMask = exp(-Luma * 2.0 * PI / LumaMask);
    
    Color = mix(Color, vec3(Luma), ColorMask);
    
    // 加入极小epsilon避免除以0,同时完成归一化
    float sum = dot(Color, vec3(1.0));
    return Color / max(sum, 0.0001);
}

关键修改说明

  1. 替换亮度计算权重:用标准的视觉权重计算Luma,确保亮度值符合人眼感知,让mix逻辑的色彩过渡更自然。
  2. 钳制LumaMask:给LumaMask设置最小阈值,避免指数函数的参数出现极端值,稳定ColorMask的输出范围。
  3. 安全归一化:给归一化的分母加一个极小的epsilon(0.0001),彻底避免除以0的情况,防止数值异常。

内容的提问来源于stack exchange,提问作者Summit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 17:22:08