【问题标题】:Hue shift shader breaks alpha色相移位着色器破坏了 alpha
【发布时间】:2015-12-31 04:52:36
【问题描述】:

我正在使用 cocos2dx。我有一个 Sprite,它使用这样的自定义着色器设置:

boss_1 = Sprite::createWithSpriteFrameName("Zombies/normal/0_0_0.png");
boss_1->setPosition(boss_1->getContentSize()/2.0f);
boss_1->setBlendFunc(cocos2d::BlendFunc::ALPHA_NON_PREMULTIPLIED);
boss_1->setGLProgramState(boss_1_state);

我有以下着色器:

vec3 hueAdjust(vec3 color, float hueAdjust)
{
    const vec3  kRGBToYPrime = vec3 (0.299, 0.587, 0.114);
    const vec3  kRGBToI     = vec3 (0.596, -0.275, -0.321);
    const vec3  kRGBToQ     = vec3 (0.212, -0.523, 0.311);

    const vec3  kYIQToR   = vec3 (1.0, 0.956, 0.621);
    const vec3  kYIQToG   = vec3 (1.0, -0.272, -0.647);
    const vec3  kYIQToB   = vec3 (1.0, -1.107, 1.704);

    // Convert to YIQ
    float   YPrime  = dot (color, kRGBToYPrime);
    float   I      = dot (color, kRGBToI);
    float   Q      = dot (color, kRGBToQ);

    // Calculate the hue and chroma
    float   hue     = atan (Q, I);
    float   chroma  = sqrt (I * I + Q * Q);

    // Make the user's adjustments
    hue += hueAdjust;

    // Convert back to YIQ
    Q = chroma * sin (hue);
    I = chroma * cos (hue);

    // Convert back to RGB
    vec3    yIQ   = vec3 (YPrime, I, Q);
    color.r = dot (yIQ, kYIQToR);
    color.g = dot (yIQ, kYIQToG);
    color.b = dot (yIQ, kYIQToB);

    // Save the result
    return color;
}

void main()
{
    vec4 v_orColor = v_fragmentColor * texture2D(CC_Texture0, v_texCoord);

    // Hue

    vec3 hueAdjustedColor = hueAdjust(v_orColor.rgb, hue_value);

    gl_FragColor = vec4(hueAdjustedColor, v_orColor.a);
}

但是 alpha 似乎丢失了,并且精灵被渲染为黑色背景。 (虽然色相转换效果很好,因为我可以用滑块测试它)

这只发生在 hueAdjust 函数中。如果我使用这个其他功能来改变对比度/饱和度/亮度,alpha 会完美保留:

vec3 ContrastSaturationBrightness(vec3 color, float brt, float sat, float con)
{
    // Increase or decrease these values to adjust r, g and b color channels seperately
    const float AvgLumR = 0.5;
    const float AvgLumG = 0.5;
    const float AvgLumB = 0.5;

    const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721);

    vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB);
    vec3 brtColor = color * brt;
    vec3 intensity = vec3(dot(brtColor, LumCoeff));
    vec3 satColor = mix(intensity, brtColor, sat);
    vec3 conColor = mix(AvgLumin, satColor, con);
    return conColor;
}

【问题讨论】:

  • 您使用什么 gfx 卡/驱动程序和操作系统版本? (可能是驱动错误)
  • 顺便说一句,您缺少:[Fragment] Compiler error 0(39) : error C1008: undefined variable "v_fragmentColor" 0(39) : error C1008: undefined variable "CC_Texture0" 0(39) : error C1008: undefined variable "v_texCoord" 0(43) : error C1008: undefined variable "hue_value" 可能是您使用的框架在内部添加的...我添加了uniform vec4 v_fragmentColor; uniform sampler2D CC_Texture0; uniform vec2 v_texCoord; uniform float hue_value; 然后编译就可以了。
  • 嘿,对不起,我直到现在才看到你的消息。我在 iPhone 6s plus 上使用 iOS 9.2 (13C75)。是的,cocos2dx 会自动添加您所说的我缺少的内容。
  • 听起来可能是抽签顺序问题。什么时候渲染?你能控制抽奖顺序吗?目测,应该没问题,我把它放到Unity里面渲染就好了。

标签: opengl opengl-es cocos2d-x shader


【解决方案1】:

看起来hueAdjust中的算法输出的是负色或NaNs...

我通过替换这一行让它工作了:

vec3 hueAdjustedColor = hueAdjust(v_orColor.rgb, hue_value);

用这个:

vec3 hueAdjustedColor = max(hueAdjust(v_orColor.rgb, hue_value), 0.0);

顺便说一句,算法似乎过于复杂。你为什么要转换这样的颜色 RGB -> YIQ -> HSV -> YIQ -> RGB?您可以将 RGB 直接转换为 HSV,反之亦然,无需中间 YIQ 阶段。这是用于此的快速无分支算法:http://lolengine.net/blog/2013/07/27/rgb-to-hsv-in-glsl

希望,它会有所帮助:)

【讨论】:

  • 就是这样!,它通过替换你刚才提到的行来工作,虽然我仍然不明白为什么 rgb 颜色为负数或 NaN 会影响 alpha 通道它确实解决了我的问题,做你碰巧知道为什么?哦,我改用 YIQ 的原因是在那个颜色空间中旋转色调。我最初从色调空间中提到的旋转色调中获取代码的地方有时会造成一些麻烦,所以建议这样做。非常感谢!
  • @Chiquis,我不知道为什么会发生这种情况。不久前我自己也遇到过类似的问题,当时谷歌搜索并没有给我任何有用的东西,所以我唯一确定的是,如果颜色分量超出 [0.0; 1.0] 范围 - 可能会发生奇怪的事情。但我不知道在每种特定情况下会发生什么以及为什么会发生:) 我认为这是因为 GPU 芯片中的一些低级优化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-30
  • 2017-06-30
  • 2012-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多