creator3d 用shader实现色相,饱和度及色调的调整

论坛里挺多调整色相,饱和度及色调,稍微拿过来改了一下,放个creator3d版本的。



上代码

Unlit-HSV.zip (1.5 KB)
编辑完发现代码块的换行有点问题,所以传多个文件上来。


CCEffect %{
  techniques:
  - name: opaque
    passes:
    - vert: unlit-vs:vert
      frag: unlit-fs:frag
      properties: &props
        color:        { value: [1, 1, 1, 1], inspector: { type: color } }
        tilingOffset: { value: [1, 1, 0, 0] }
        mainTexture:  { value: grey         }
        alphaTexture:  { value: grey         }
        Hue : { value: 0, inspector : { displayName : "色相[0-359]" } }
        Saturation : { value : 1.0, inspector : { displayName : "饱和度[0-3.0]" } }
        Value : { value : 1.0, inspector : { displayName : "色调[0-3.0]" } }
  - name: transparent
    passes:
    - vert: unlit-vs:vert
      frag: unlit-fs:frag
      blendState:
        targets:
        - blend: true
          blendSrc: src_alpha
          blendDst: one_minus_src_alpha
          blendSrcAlpha: src_alpha
          blendDstAlpha: one_minus_src_alpha
      properties: *props
}%

CCProgram unlit-vs %{
  precision mediump float;
  #include <cc-global>
  #include <cc-local-batch>
  #include <input>

  #if USE_VERTEX_COLOR
    in vec4 a_color;
    out vec4 v_color;
  #endif

  in vec2 a_texCoord;
  out vec2 v_uv;
  uniform TexCoords {
    vec4 tilingOffset;
  };

  highp vec4 vert () {
    vec4 position;
    CCVertInput(position);

    highp mat4 matWorld;
    CCGetWorldMatrix(matWorld);

    highp vec4 pos = cc_matProj * (cc_matView * matWorld) * position;

    v_uv = a_texCoord;
    #if FLIP_UV
      v_uv.y = 1.0 - v_uv.y;
    #endif
    v_uv = v_uv * tilingOffset.xy + tilingOffset.zw;

    #if USE_VERTEX_COLOR
      v_color = a_color;
    #endif

    return pos;
  }
}%

CCProgram unlit-fs %{
  precision mediump float;
  #include <output>

  in vec2 v_uv;
  uniform sampler2D mainTexture;
  uniform Values {
    float Hue;
    float Saturation;
    float Value;
  };

  #if USE_COLOR
    uniform Constant {
      vec4 color;
    };
  #endif
  #
  #if USE_ALPHAIMAGE
    uniform sampler2D alphaTexture;
  #endif


  #if USE_VERTEX_COLOR
    in vec4 v_color;
  #endif
  
  vec3 RGBConvertToHSV(vec3 rgb) {
    float R = rgb.x, G = rgb.y, B = rgb.z;
    vec3 hsv;
    float max1 = max(R,max(G,B));
    float min1 = min(R,min(G,B));
    if (R == max1) {
      hsv.x = (G-B)/(max1-min1);
    }
    if (G == max1) {
      hsv.x = 2.0 + (B-R)/(max1-min1);
    }
    if (B == max1) {
      hsv.x = 4.0 + (R-G)/(max1-min1);
    }
    hsv.x = hsv.x * 60.0;   
    if (hsv.x < 0.0) hsv.x = hsv.x + 360.0;
    hsv.z = max1;
    hsv.y = (max1 - min1) / max1;
    return hsv;
  }

  vec3 HSVConvertToRGB(vec3 hsv) {
    float R,G,B;
    if( hsv.y == 0.0 ) {
      R=G=B=hsv.z;
    }
    else {
      hsv.x = hsv.x/60.0; 
      int i = int(hsv.x);
      float f = hsv.x - float(i);
      float a = hsv.z * ( 1.0 - hsv.y );
      float b = hsv.z * ( 1.0 - hsv.y * f );
      float c = hsv.z * ( 1.0 - hsv.y * (1.0 - f ) );
      if(i == 0) {
        R = hsv.z; G = c; B = a;
      }
      else if(i == 1) {
        R = b; G = hsv.z; B = a; 
      }
      else if(i == 2) {
        R = a; G = hsv.z; B = c; 
      }
      else if(i == 3) {
        R = a; G = b; B = hsv.z;
      }
      else if(i == 4) {
        R = c; G = a; B = hsv.z;
      }
      else {
        R = hsv.z; G = a; B = b; 
      }
    }
    return vec3(R,G,B);
  }

  vec4 frag () {
    vec4 o = texture(mainTexture, v_uv);
    vec3 colorHSV = RGBConvertToHSV(o.xyz); //转换为HSV
    colorHSV.x += Hue; //调整偏移Hue值
    colorHSV.x = mod(colorHSV.x, 360.0); //超过360的值从0开始

    colorHSV.y *= Saturation; //调整饱和度
    colorHSV.z *= Value;
    o.xyz = HSVConvertToRGB(colorHSV.xyz); //将调整后的HSV,转换为RGB颜色

    #if USE_COLOR
      o *= color;
    #endif

    #if USE_VERTEX_COLOR
      o *= v_color;
    #endif
    
    #if USE_ALPHAIMAGE
      o.a = texture(alphaTexture, v_uv).r;
    #endif

    return CCFragOutput(o);
  }
}%


使用办法:

  1. 在项目资源里创建一个Effect文件,然后把上面的的shader代码全放进去
  2. 再创建一个Material文件,然后选中Material文件,在右边属性栏处,Effect选择第1步创建的Effect
  3. 再把贴图拉进MainTexture里面。其它参数可以自行修改试试,会出现不同的效果。
  4. 最后再把这个材质拉到你的对象材质上。

ps:代码块USE_ALPHAIMAGE可支持使用通道图片

5赞

谢谢分享,已置顶