HLSL实现PS混合模式

base = 基色

blend = 混合色

alpha = 不透明度

基础型

// 正常
float3 normal(float3 base, float3 blend, float alpha) {
    return lerp(base, blend, alpha);
}

变暗型(去亮型)

// 变暗
//    UE 中可用 Blend_Darken 代替
float3 darken(float3 base, float3 blend) {
	return min(base, blend);
}

// 正片叠底
float3 multiply(float3 base, float3 blend) {
	return base * blend;
}

// 颜色加深
//    UE 中可用 Blend_ColorBurn 代替
float3 color_burn(float3 base, float3 blend) {
	return base - ((1 - base) * (1 - blend)) / blend;
}

// 线性加深
//    UE 中可用 Blend_LinearBurn 代替
float3 linear_burn(float3 base, float3 blend) {
	return base + blend - 1;
}

// 深色
float3 darker_color(float3 base, float3 blend) {
	float base_value = base.x + base.y + base.z;
	float blend_value = blend.x + blend.y + blend.z;
	return base_value > blend_value ? blend : base;
}

变亮型(去暗型)

// 变亮
//    UE 中可用 Blend_Lighten 代替
float3 lighten(float3 base, float3 blend) {
	return max(base, blend);
}

// 滤色
//    UE 中可用 Blend_Screen 代替
float3 screen(float3 base, float3 blend) {
	return 1 - (1 - base) * (1 - blend);
}

// 颜色减淡
//    UE 中可用 Blend_ColorDodge 代替
float3 color_dodge(float3 base, float3 blend) {
	return base + (base * blend) / (1 - blend);
}

// 线性减淡
//    UE 中可用 Blend_LinearDodge 代替
float3 linear_dodge(float3 base, float3 blend) {
	return base + blend;
}

// 浅色
float3 lighter_color(float3 base, float3 blend) {
	float base_value = base.x + base.y + base.z;
	float blend_value = blend.x + blend.y + blend.z;
	return base_value <= blend_value ? blend : base;
}

溶合型

// 叠加
//    UE 中可用 Blend_Overlay 代替
float3 overlay(float3 base, float3 blend) {
	return base <= 0.5 ? (base * blend) / 0.5 : 1 - ((1 - base) * (1 - blend)) / 0.5;
}

// 柔光
//    UE 中可用 Blend_SoftLight 代替(效果与 PS 不一致)
float3 soft_light(float3 base, float3 blend) {
	return blend <= 0.5 ? (base * blend) / 0.5 + pow(base, 2) * (1 - 2 * blend) : base * (1 - blend) / 0.5 + sqrt(base) * (2 * blend - 1);
}

// 强光
//    UE 中可用 Blend_HardLight 代替
float3 hard_light(float3 base, float3 blend) {
	return blend <= 0.5 ? (base * blend) / 0.5 : 1 - ((1 - base) * (1 - blend)) / 0.5;
}

// 亮光
float3 vivid_light(float3 base, float3 blend) {
	return blend <= 0.5 ? base - ((1 - base) * (1 - 2 * blend)) / (2 * blend) : base + (base * (2 * blend - 1)) / (2 * (1 - blend));
}

// 线性光(效果与 PS 不一致)
//    UE 中可用 Blend_LinearLight 代替
float3 linear_light(float3 base, float3 blend) {
	return base + 2 * blend - 1;
}

// 点光(效果与 PS 不一致)
//    UE 中可用 Blend_PinLight 代替
float3 pin_light(float3 base, float3 blend) {
	return blend <= 0.5 ? min(base, 2 * blend) : min(base, 2 * blend - 1);
}

// 实色混合
float3 hard_mix(float3 base, float3 blend) {
	return base + blend >= 1;
}

色差型

// 差值
//    UE 中可用 Blend_Difference 代替
float3 difference(float3 base, float3 blend) {
	return abs(base - blend);
}

// 排除
//    UE 中可用 Blend_Exclusion 代替
float3 exclusion(float3 base, float3 blend) {
	return base + blend - (base * blend) / 0.5;
}

// 减去
//    contract: 缩放值
//    compensation: 补偿值
float3 subtract(float3 base, float3 blend, float contract = 1, float compensation = 0) {
	return (base - blend) / contract + compensation;
}

// 划分
float3 division(float3 base, float3 blend) {
	return base / blend;
}

调色型

// srgb 转 rgb
float3 gamma2linear(float3 gamma_color) {
	return pow(gamma_color, 2.2);
}

// rgb 转 srgb
float3 linear2gamma(float3 linear_color) {
	return pow(linear_color, 1.0 / 2.2);
}

// rgb 转 hsv(色相、饱和度、明度)
float3 rgb2hsv(float3 color) {
	float4 K = float4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
	float4 p = lerp(float4(color.zy, K.wz), float4(color.yz, K.xy), step(color.z, color.y));
	float4 q = lerp(float4(p.xyw, color.x), float4(color.x, p.yzx), step(p.x, color.x));
	float d = q.x - min(q.w, q.y);
	float e = 0.001;
	return float3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}

// hsv 转 rgb
float3 hsv2rgb(float3 color) {
	color = float3(color.x, saturate(color.yz));
	float4 K = float4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
	float3 p = abs(frac(color.xxx + K.xyz) * 6.0 - K.www);
	return color.z * lerp(K.xxx, saturate(p - K.xxx), color.y);
}


// 色相
//    用基色的明亮度和饱和度,加混合色的色相,生成结果色。
float3 hue(float3 base, float3 blend) {
	float3 base_hsv = rgb2hsv(gamma2linear(base));
	float3 blend_hsv = rgb2hsv(gamma2linear(blend));
	float3 hue_hsv = float3(blend_hsv.x, base_hsv.y, base_hsv.z);
	return linear2gamma(hsv2rgb(hue_hsv));
}

// 饱和度
//    用基色的明亮度和色相,加混合色的饱和度,生成结果色。
float3 saturation(float3 base, float3 blend) {
	float3 base_hsv = rgb2hsv(gamma2linear(base));
	float3 blend_hsv = rgb2hsv(gamma2linear(blend));
	float3 saturation_hsv = float3(base_hsv.x, blend_hsv.y, base_hsv.z);
	return linear2gamma(hsv2rgb(saturation_hsv));
}

// 颜色
//    用基色的明亮度,加混合色的色相和饱和度,生成结果色。
float3 color(float3 base, float3 blend) {
	float3 base_hsv = rgb2hsv(gamma2linear(base));
	float3 blend_hsv = rgb2hsv(gamma2linear(blend));
	float3 color_hsv = float3(blend_hsv.x, blend_hsv.y, base_hsv.z);
	return linear2gamma(hsv2rgb(color_hsv));
}

// 明度
//    用基色的色相和饱和度,加混合色的明亮度,创建结果色。
float3 luminosity(float3 base, float3 blend) {
	float3 base_hsv = rgb2hsv(gamma2linear(base));
	float3 blend_hsv = rgb2hsv(gamma2linear(blend));
	float3 luminosity_hsv = float3(base_hsv.x, base_hsv.y, blend_hsv.z);
	return linear2gamma(hsv2rgb(luminosity_hsv));
}

混合模式中 alpha 计算

        先以基色混合色通过混合模式的公式算出结果色,再以混合模式算出的结果色作为正常模式的混合色加上alpha(不透明度)得出最终的结果色

混合模式填充度计算

        先以混合色、混合模式对应的中性色(不同混合模式对应的中性色不一样),将中性色代入正常模式的alpha值得出结果色,再用得出的结果色作为混合色,与基色通过混合模式的公式得出最终的结果色

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值