有谁有ps里面的 颜色模式的shader吗

在网上找到的一个

#ifdef GL_ES 
precision mediump float; 
#endif 
varying vec2 v_texCoord;
varying vec4 v_fragmentColor;
uniform vec3 b_color;

vec3 HSLToRGB(vec3 hsl);
float HueToRGB(float f1, float f2, float hue);
vec3 RGBToHSL(vec3 color);
vec3 BlendColor(vec3 base, vec3 blend);

void main(void)
{
    vec4 col = v_fragmentColor * texture2D(CC_Texture0, v_texCoord);//v_fragmentColor is sprite setColor
    gl_FragColor.rgb = BlendColor(col.rgb,b_color);
    gl_FragColor.a = col.a;
};

vec3 RGBToHSL(vec3 color)
{
    vec3 hsl; // init to 0 to avoid warnings ? (and reverse if + remove first part)
    
    float fmin = min(min(color.r, color.g), color.b);    //Min. value of RGB
    float fmax = max(max(color.r, color.g), color.b);    //Max. value of RGB
    float delta = fmax - fmin;             //Delta RGB value

    hsl.z = (fmax + fmin) / 2.0; // Luminance

    if (delta == 0.0)        //This is a gray, no chroma...
    {
        hsl.x = 0.0;    // Hue
        hsl.y = 0.0;    // Saturation
    }
    else                                    //Chromatic data...
    {
        if (hsl.z < 0.5)
            hsl.y = delta / (fmax + fmin); // Saturation
        else
            hsl.y = delta / (2.0 - fmax - fmin); // Saturation
        
        float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta;
        float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta;
        float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta;

        if (color.r == fmax )
            hsl.x = deltaB - deltaG; // Hue
        else if (color.g == fmax)
            hsl.x = (1.0 / 3.0) + deltaR - deltaB; // Hue
        else if (color.b == fmax)
            hsl.x = (2.0 / 3.0) + deltaG - deltaR; // Hue

        if (hsl.x < 0.0)
            hsl.x += 1.0; // Hue
        else if (hsl.x > 1.0)
            hsl.x -= 1.0; // Hue
    }

    return hsl;
}

float HueToRGB(float f1, float f2, float hue)
{
    if (hue < 0.0)
        hue += 1.0;
    else if (hue > 1.0)
        hue -= 1.0;
    float res;
    if ((6.0 * hue) < 1.0)
        res = f1 + (f2 - f1) * 6.0 * hue;
    else if ((2.0 * hue) < 1.0)
        res = f2;
    else if ((3.0 * hue) < 2.0)
        res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0;
    else
        res = f1;
    return res;
}

vec3 HSLToRGB(vec3 hsl)
{
    vec3 rgb;
    
    if (hsl.y == 0.0)
        rgb = vec3(hsl.z); // Luminance
    else
    {
        float f2;
        
        if (hsl.z < 0.5)
            f2 = hsl.z * (1.0 + hsl.y);
        else
            f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z);
            
        float f1 = 2.0 * hsl.z - f2;
        
        rgb.r = HueToRGB(f1, f2, hsl.x + (1.0/3.0));
        rgb.g = HueToRGB(f1, f2, hsl.x);
        rgb.b= HueToRGB(f1, f2, hsl.x - (1.0/3.0));
    }
    
    return rgb;
}

vec3 BlendColor(vec3 base, vec3 blend)
{
    vec3 blendHSL = RGBToHSL(blend);
    return HSLToRGB(vec3(blendHSL.r, blendHSL.g, RGBToHSL(base).b));
}

但是颜色偏深啊

做过的帮忙看下。

对比

裙子

这个是叫饱和度高了还是亮度低了啊

用这种shader的时候,先确认下你纹理的blendfunc,png图加载的时候2dx会做alpha预乘的,如果你这纹理是预乘过的,你这shader用的时候得先把纹理的rgb还原,再做剩下的运算,最后再把alpha乘上。

1赞

Hi,非常感谢回复。我看到sprite初始化的时候

ALPHA_PREMULTIPLIED定义:

const BlendFunc BlendFunc::ALPHA_PREMULTIPLIED = {GL_ONE, GL_ONE_MINUS_SRC_ALPHA};
GL_ONE_MINUS_SRC_ALPHA:表示用1.0减去源颜色的alpha值来作为因子。

不知道2dx在哪里预乘,我应该怎么还原纹理的rgb呢。

CCImage.cpp里面有这样一段代码是处理预乘的:

void Image::premultipliedAlpha()
{
#if CC_ENABLE_PREMULTIPLIED_ALPHA == 0
        _hasPremultipliedAlpha = false;
        return;
#else
    CCASSERT(_renderFormat == Texture2D::PixelFormat::RGBA8888, "The pixel format should be RGBA8888!");
    
    unsigned int* fourBytes = (unsigned int*)_data;
    for(int i = 0; i < _width * _height; i++)
    {
        unsigned char* p = _data + i * 4;
        fourBytes[i] = CC_RGB_PREMULTIPLY_ALPHA(p[0], p[1], p[2], p[3]);
    }
    
    _hasPremultipliedAlpha = true;
#endif
}

如果你不希望 png 图片做 alpha 预乘,可以把这里面的预乘代码注释掉。不过注释掉预乘的代码后,你 sprite 渲染的 blend function 也需要做相应的修改。

谢谢回复啊。

// premultiply alpha, or the effect will wrong when want to use other pixel format in Texture2D,
// such as RGB888, RGB5A1
#define CC_RGB_PREMULTIPLY_ALPHA(vr, vg, vb, va) \
    (unsigned)(((unsigned)((unsigned char)(vr) * ((unsigned char)(va) + 1)) >> 8) | \
    ((unsigned)((unsigned char)(vg) * ((unsigned char)(va) + 1) >> 8) << 8) | \
    ((unsigned)((unsigned char)(vb) * ((unsigned char)(va) + 1) >> 8) << 16) | \
    ((unsigned)(unsigned char)(va) << 24))

NS_CC_BEGIN

这段代码是什么意思啊。我注释掉,计算之后再再shader里面预乘,但是那段代码不知道怎么转换的

我现在是在shader里面alpha为0还能渲染出来图像

子龙大大你qq多少啊 我这个很捉急 需要你帮忙啊

vec4 col = v_fragmentColor * texture2D(CC_Texture0, v_texCoord);//v_fragmentColor is sprite setColor
col.rgb = col.rgb / col.a;
gl_FragColor.rgb = BlendColor(col.rgb,b_color);
gl_FragColor.rgb = gl_FragColor.rgb * col.a;
gl_FragColor.a = col.a;

你先试试这样,如果这样对了,那就是预乘的问题

很感谢啊。
我使用openGL做了同样的操作,效果比cocos渲染的淡一些,但是还是相对ps的较深。我又调整一下,整体差不多了。
col.rgb = col.rgb / col.a;
为什么当clo.a是0分母为0的时候shader也可以正常运行啊

我弄得效果差不多了。但是还是有一些疑问。
我在sprite里面设置
setBlendFunc(BlendFunc::ALPHA_NON_PREMULTIPLIED);
取消了预乘。
但是在shader渲染的时候

    //runseColor.rgb /= runseColor.a;
    gl_FragColor = runseColor;```
如果我不除以alpha导致渲染的纹理很暗不正确,取消注释则正常。

但是这样会出现一个问题,除以alpha之后会导致rgb的通道每个都大于1,
再通过alpha混合的时候就达不到预期的效果了。(该透明的地方变成不透明)

我目前所有传进来的每个纹理,都没有除以alpha通道,当一切都计算之后再除以alpha。
但是为什么要除以alpha通道才正常呢?


@zilong 
@liuxiaoyi135
vec3 BlendColorAlpha(vec4 base , vec4 blend)
{    
    if(blend.a == 0) return base.rgb;
    return base.rgb*(1-blend.a) + blend.rgb*blend.a;
}

最后在混合alpha里面加了一个判断,虽然看似没有用。但是问题解决了。

没加之前

加过之后

混合需要的图片:

希望有人遇到这个问题的时候也能找到问题所在。也帮我解释一下这是为什么。

你虽然blendfunc取消了预乘,但是cocos加载png的时候会对纹理做预乘操作,这样纹理和你设置的blendfunc不是对应的,渲染就不对了,你要是blendfunc取消预乘就要在CCImage.cpp里改源码,不对纹理做预乘