- static const char *blend_add_frag =
- " result_color.rgb = dst_color.rgb + src_color.rgb;\n";
-
- static const char *blend_max_frag =
- " result_color.r = max(abs(dst_color.r, src_color.r);\n"
- " result_color.g = max(abs(dst_color.g, src_color.g);\n"
- " result_color.b = max(abs(dst_color.b, src_color.b);\n";
-
- static const char *blend_min_frag =
- " result_color.r = min(abs(dst_color.r, src_color.r);\n"
- " result_color.g = min(abs(dst_color.g, src_color.g);\n"
- " result_color.b = min(abs(dst_color.b, src_color.b);\n";
-
- static const char *blend_subtract_frag =
- " result_color.rgb = dst_color.rgb - src_color.rgb;\n";
-
-
- static const char *blend_multiply_frag =
- " result_color.rgb = dst_color.rgb * src_color.rgb;\n";
-
- static const char *blend_divide_frag =
- " result_color.rgb = dst_color.rgb / src_color.rgb;\n"
- " if(src_color.r == 0.0) result_color.r = 1.0;\n"
- " if(src_color.g == 0.0) result_color.g = 1.0;\n"
- " if(src_color.b == 0.0) result_color.b = 1.0;\n";
-
+#define QQ(q)#q
+#define SS(s)QQ(s)
+
+#define GL_STD_FRAG(FN) static const char *blend_##FN##_frag = \
+ " vec4 result;\n" \
+ " result.rgb = " SS(COLOR_##FN(1.0, src_color.rgb, src_color.a, dst_color.rgb, dst_color.a)) ";\n" \
+ " result.a = " SS(ALPHA_##FN(1.0, src_color.a, dst_color.a))";\n" \
+
+#define GL_VEC_FRAG(FN) static const char *blend_##FN##_frag = \
+ " vec4 result;\n" \
+ " result.r = " SS(COLOR_##FN(1.0, src_color.r, src_color.a, dst_color.r, dst_color.a)) ";\n" \
+ " result.g = " SS(COLOR_##FN(1.0, src_color.g, src_color.a, dst_color.g, dst_color.a)) ";\n" \
+ " result.b = " SS(COLOR_##FN(1.0, src_color.b, src_color.a, dst_color.b, dst_color.a)) ";\n" \
+ " result.a = " SS(ALPHA_##FN(1.0, src_color.a, dst_color.a)) ";\n" \
+ " result = clamp(result, 0.0, 1.0);\n" \
+
+#undef mabs
+#define mabs abs
+#undef mmin
+#define mmin min
+#undef mmax
+#define mmax max
+
+#undef ZERO
+#define ZERO 0.0
+#undef ONE
+#define ONE 1.0
+#undef TWO
+#define TWO 2.0
+
+static const char *blend_NORMAL_frag =
+ " vec4 result = mix(src_color, src_color, src_color.a);\n";
+
+static const char *blend_ADDITION_frag =
+ " vec4 result = dst_color + src_color;\n"
+ " result = clamp(result, 0.0, 1.0);\n";
+
+static const char *blend_SUBTRACT_frag =
+ " vec4 result = dst_color - src_color;\n"
+ " result = clamp(result, 0.0, 1.0);\n";
+
+static const char *blend_REPLACE_frag =
+ " vec4 result = src_color;\n";
+
+GL_STD_FRAG(MULTIPLY);
+GL_VEC_FRAG(DIVIDE);
+GL_VEC_FRAG(MAX);
+GL_VEC_FRAG(MIN);
+GL_VEC_FRAG(DARKEN);
+GL_VEC_FRAG(LIGHTEN);
+GL_STD_FRAG(DST);
+GL_STD_FRAG(DST_ATOP);
+GL_STD_FRAG(DST_IN);
+GL_STD_FRAG(DST_OUT);
+GL_STD_FRAG(DST_OVER);
+GL_STD_FRAG(SRC);
+GL_STD_FRAG(SRC_ATOP);
+GL_STD_FRAG(SRC_IN);
+GL_STD_FRAG(SRC_OUT);
+GL_STD_FRAG(SRC_OVER);
+GL_STD_FRAG(AND);
+GL_STD_FRAG(OR);
+GL_STD_FRAG(XOR);
+GL_VEC_FRAG(OVERLAY);
+GL_STD_FRAG(SCREEN);
+GL_VEC_FRAG(BURN);
+GL_VEC_FRAG(DODGE);
+GL_VEC_FRAG(HARDLIGHT);
+GL_VEC_FRAG(SOFTLIGHT);
+GL_VEC_FRAG(DIFFERENCE);
+
+static const char * const overlay_shaders[TRANSFER_TYPES] = {
+ blend_NORMAL_frag, // TRANSFER_NORMAL
+ blend_ADDITION_frag, // TRANSFER_ADDITION
+ blend_SUBTRACT_frag, // TRANSFER_SUBTRACT
+ blend_MULTIPLY_frag, // TRANSFER_MULTIPLY
+ blend_DIVIDE_frag, // TRANSFER_DIVIDE
+ blend_REPLACE_frag, // TRANSFER_REPLACE
+ blend_MAX_frag, // TRANSFER_MAX
+ blend_MIN_frag, // TRANSFER_MIN
+ blend_DARKEN_frag, // TRANSFER_DARKEN
+ blend_LIGHTEN_frag, // TRANSFER_LIGHTEN
+ blend_DST_frag, // TRANSFER_DST
+ blend_DST_ATOP_frag, // TRANSFER_DST_ATOP
+ blend_DST_IN_frag, // TRANSFER_DST_IN
+ blend_DST_OUT_frag, // TRANSFER_DST_OUT
+ blend_DST_OVER_frag, // TRANSFER_DST_OVER
+ blend_SRC_frag, // TRANSFER_SRC
+ blend_SRC_ATOP_frag, // TRANSFER_SRC_ATOP
+ blend_SRC_IN_frag, // TRANSFER_SRC_IN
+ blend_SRC_OUT_frag, // TRANSFER_SRC_OUT
+ blend_SRC_OVER_frag, // TRANSFER_SRC_OVER
+ blend_AND_frag, // TRANSFER_AND
+ blend_OR_frag, // TRANSFER_OR
+ blend_XOR_frag, // TRANSFER_XOR
+ blend_OVERLAY_frag, // TRANSFER_OVERLAY
+ blend_SCREEN_frag, // TRANSFER_SCREEN
+ blend_BURN_frag, // TRANSFER_BURN
+ blend_DODGE_frag, // TRANSFER_DODGE
+ blend_HARDLIGHT_frag, // TRANSFER_HARDLIGHT
+ blend_SOFTLIGHT_frag, // TRANSFER_SOFTLIGHT
+ blend_DIFFERENCE_frag, // TRANSFER_DIFFERENCE
+};