<Lib />\r
</ItemDefinitionGroup>\r
<ItemGroup>\r
- <ClInclude Include="mixer\image\photoshop_math.h" />\r
+ <ClInclude Include="mixer\image\blending_glsl.h" />\r
<ClInclude Include="video_channel.h" />\r
<ClInclude Include="video_channel_context.h" />\r
<ClInclude Include="consumer\output.h" />\r
<ClInclude Include="video_channel_context.h">\r
<Filter>source</Filter>\r
</ClInclude>\r
- <ClInclude Include="mixer\image\photoshop_math.h">\r
+ <ClInclude Include="mixer\image\blending_glsl.h">\r
<Filter>source\mixer\image</Filter>\r
</ClInclude>\r
</ItemGroup>\r
const size_t width_;\r
const size_t height_;\r
const size_t stride_;\r
- bool empty_;\r
\r
public:\r
implementation(size_t width, size_t height, size_t stride) \r
: width_(width)\r
, height_(height)\r
, stride_(stride)\r
- , empty_(true)\r
{ \r
GL(glGenTextures(1, &id_));\r
GL(glBindTexture(GL_TEXTURE_2D, id_));\r
GL(glTexImage2D(GL_TEXTURE_2D, 0, INTERNAL_FORMAT[stride_], width_, height_, 0, FORMAT[stride_], GL_UNSIGNED_BYTE, NULL));\r
GL(glBindTexture(GL_TEXTURE_2D, 0));\r
//CASPAR_LOG(trace) << "[device_buffer] allocated size:" << width*height*stride; \r
+ clear();\r
} \r
\r
~implementation()\r
void attach(int index)\r
{\r
GL(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + index, GL_TEXTURE_2D, id_, 0));\r
- empty_ = false;\r
}\r
\r
void clear()\r
{\r
attach(0);\r
GL(glClear(GL_COLOR_BUFFER_BIT));\r
- empty_ = true;\r
}\r
};\r
\r
void device_buffer::read(host_buffer& source){impl_->read(source);}\r
void device_buffer::write(host_buffer& target){impl_->write(target);}\r
void device_buffer::clear(){impl_->clear();}\r
-bool device_buffer::empty() const { return impl_->empty_; }\r
\r
}}
\ No newline at end of file
void unbind();\r
\r
void clear();\r
- bool empty() const;\r
\r
void attach(int index = 0);\r
void read(host_buffer& source);\r
--- /dev/null
+#pragma once\r
+\r
+static std::string get_blend_glsl()\r
+{\r
+ static std::string glsl = \r
+ "\n /* "\r
+ "\n ** Photoshop & misc math "\r
+ "\n ** Blending modes, RGB/HSL/Contrast/Desaturate, levels control "\r
+ "\n ** "\r
+ "\n ** Romain Dura | Romz "\r
+ "\n ** Blog: http://blog.mouaif.org "\r
+ "\n ** Post: http://blog.mouaif.org/?p=94 "\r
+ "\n */ "\r
+ "\n "\r
+ "\n "\r
+ "\n /* "\r
+ "\n ** Desaturation "\r
+ "\n */ "\r
+ "\n "\r
+ "\n vec4 Desaturate(vec3 color, float Desaturation) "\r
+ "\n { "\r
+ "\n vec3 grayXfer = vec3(0.3, 0.59, 0.11); "\r
+ "\n vec3 gray = vec3(dot(grayXfer, color)); "\r
+ "\n return vec4(mix(color, gray, Desaturation), 1.0); "\r
+ "\n } "\r
+ "\n "\r
+ "\n "\r
+ "\n /* "\r
+ "\n ** Hue, saturation, luminance "\r
+ "\n */ "\r
+ "\n "\r
+ "\n vec3 RGBToHSL(vec3 color) "\r
+ "\n { "\r
+ "\n vec3 hsl; "\r
+ "\n "\r
+ "\n float fmin = min(min(color.r, color.g), color.b); "\r
+ "\n float fmax = max(max(color.r, color.g), color.b); "\r
+ "\n float delta = fmax - fmin; "\r
+ "\n "\r
+ "\n hsl.z = (fmax + fmin) / 2.0; "\r
+ "\n "\r
+ "\n if (delta == 0.0) "\r
+ "\n { "\r
+ "\n hsl.x = 0.0; "\r
+ "\n hsl.y = 0.0; "\r
+ "\n } "\r
+ "\n else "\r
+ "\n { "\r
+ "\n if (hsl.z < 0.5) "\r
+ "\n hsl.y = delta / (fmax + fmin); "\r
+ "\n else "\r
+ "\n hsl.y = delta / (2.0 - fmax - fmin); "\r
+ "\n "\r
+ "\n float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta; "\r
+ "\n float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta; "\r
+ "\n float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta; "\r
+ "\n "\r
+ "\n if (color.r == fmax ) "\r
+ "\n hsl.x = deltaB - deltaG; "\r
+ "\n else if (color.g == fmax) "\r
+ "\n hsl.x = (1.0 / 3.0) + deltaR - deltaB; "\r
+ "\n else if (color.b == fmax) "\r
+ "\n hsl.x = (2.0 / 3.0) + deltaG - deltaR; "\r
+ "\n "\r
+ "\n if (hsl.x < 0.0) "\r
+ "\n hsl.x += 1.0; "\r
+ "\n else if (hsl.x > 1.0) "\r
+ "\n hsl.x -= 1.0; "\r
+ "\n } "\r
+ "\n "\r
+ "\n return hsl; "\r
+ "\n } "\r
+ "\n "\r
+ "\n float HueToRGB(float f1, float f2, float hue) "\r
+ "\n { "\r
+ "\n if (hue < 0.0) "\r
+ "\n hue += 1.0; "\r
+ "\n else if (hue > 1.0) "\r
+ "\n hue -= 1.0; "\r
+ "\n float res; "\r
+ "\n if ((6.0 * hue) < 1.0) "\r
+ "\n res = f1 + (f2 - f1) * 6.0 * hue; "\r
+ "\n else if ((2.0 * hue) < 1.0) "\r
+ "\n res = f2; "\r
+ "\n else if ((3.0 * hue) < 2.0) "\r
+ "\n res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0; "\r
+ "\n else "\r
+ "\n res = f1; "\r
+ "\n return res; "\r
+ "\n } "\r
+ "\n "\r
+ "\n vec3 HSLToRGB(vec3 hsl) "\r
+ "\n { "\r
+ "\n vec3 rgb; "\r
+ "\n "\r
+ "\n if (hsl.y == 0.0) "\r
+ "\n rgb = vec3(hsl.z); "\r
+ "\n else "\r
+ "\n { "\r
+ "\n float f2; "\r
+ "\n "\r
+ "\n if (hsl.z < 0.5) "\r
+ "\n f2 = hsl.z * (1.0 + hsl.y); "\r
+ "\n else "\r
+ "\n f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z); "\r
+ "\n "\r
+ "\n float f1 = 2.0 * hsl.z - f2; "\r
+ "\n "\r
+ "\n rgb.r = HueToRGB(f1, f2, hsl.x + (1.0/3.0)); "\r
+ "\n rgb.g = HueToRGB(f1, f2, hsl.x); "\r
+ "\n rgb.b= HueToRGB(f1, f2, hsl.x - (1.0/3.0)); "\r
+ "\n } "\r
+ "\n "\r
+ "\n return rgb; "\r
+ "\n } "\r
+ "\n "\r
+ "\n "\r
+ "\n /* "\r
+ "\n ** Contrast, saturation, brightness "\r
+ "\n ** Code of this function is from TGM's shader pack "\r
+ "\n ** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057 "\r
+ "\n */ "\r
+ "\n "\r
+ "\n vec3 ContrastSaturationBrightness(vec3 color, float brt, float sat, float con) "\r
+ "\n { "\r
+ "\n const float AvgLumR = 0.5; "\r
+ "\n const float AvgLumG = 0.5; "\r
+ "\n const float AvgLumB = 0.5; "\r
+ "\n "\r
+ "\n const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721); "\r
+ "\n "\r
+ "\n vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB); "\r
+ "\n vec3 brtColor = color * brt; "\r
+ "\n vec3 intensity = vec3(dot(brtColor, LumCoeff)); "\r
+ "\n vec3 satColor = mix(intensity, brtColor, sat); "\r
+ "\n vec3 conColor = mix(AvgLumin, satColor, con); "\r
+ "\n return conColor; "\r
+ "\n } "\r
+ "\n "\r
+ "\n "\r
+ "\n /* "\r
+ "\n ** Float blending modes "\r
+ "\n ** Adapted from here: http://www.nathanm.com/photoshop-blending-math/ "\r
+ "\n ** But I modified the HardMix (wrong condition), Overlay, SoftLight, ColorDodge, ColorBurn, VividLight, PinLight (inverted layers) ones to have correct results "\r
+ "\n */ "\r
+ "\n \n "\r
+ "\n#define BlendLinearDodgef BlendAddf \n "\r
+ "\n#define BlendLinearBurnf BlendSubstractf \n "\r
+ "\n#define BlendAddf(base, blend) min(base + blend, 1.0) \n "\r
+ "\n#define BlendSubstractf(base, blend) max(base + blend - 1.0, 0.0) \n "\r
+ "\n#define BlendLightenf(base, blend) max(blend, base) \n "\r
+ "\n#define BlendDarkenf(base, blend) min(blend, base) \n "\r
+ "\n#define BlendLinearLightf(base, blend) (blend < 0.5 ? BlendLinearBurnf(base, (2.0 * blend)) : BlendLinearDodgef(base, (2.0 * (blend - 0.5)))) \n "\r
+ "\n#define BlendScreenf(base, blend) (1.0 - ((1.0 - base) * (1.0 - blend))) \n "\r
+ "\n#define BlendOverlayf(base, blend) (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend))) \n "\r
+ "\n#define BlendSoftLightf(base, blend) ((blend < 0.5) ? (2.0 * base * blend + base * base * (1.0 - 2.0 * blend)) : (sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend))) \n "\r
+ "\n#define BlendColorDodgef(base, blend) ((blend == 1.0) ? blend : min(base / (1.0 - blend), 1.0)) \n "\r
+ "\n#define BlendColorBurnf(base, blend) ((blend == 0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0)) \n "\r
+ "\n#define BlendVividLightf(base, blend) ((blend < 0.5) ? BlendColorBurnf(base, (2.0 * blend)) : BlendColorDodgef(base, (2.0 * (blend - 0.5)))) \n "\r
+ "\n#define BlendPinLightf(base, blend) ((blend < 0.5) ? BlendDarkenf(base, (2.0 * blend)) : BlendLightenf(base, (2.0 *(blend - 0.5)))) \n "\r
+ "\n#define BlendHardMixf(base, blend) ((BlendVividLightf(base, blend) < 0.5) ? 0.0 : 1.0) \n "\r
+ "\n#define BlendReflectf(base, blend) ((blend == 1.0) ? blend : min(base * base / (1.0 - blend), 1.0)) \n "\r
+ "\n "\r
+ "\n "\r
+ "\n /* "\r
+ "\n ** Vector3 blending modes "\r
+ "\n */ "\r
+ "\n "\r
+ "\n#define Blend(base, blend, funcf) vec3(funcf(base.r, blend.r), funcf(base.g, blend.g), funcf(base.b, blend.b)) \n "\r
+ "\n \n "\r
+ "\n#define BlendNormal(base, blend) (blend) \n "\r
+ "\n#define BlendLighten BlendLightenf \n "\r
+ "\n#define BlendDarken BlendDarkenf \n "\r
+ "\n#define BlendMultiply(base, blend) (base * blend) \n "\r
+ "\n#define BlendAverage(base, blend) ((base + blend) / 2.0) \n "\r
+ "\n#define BlendAdd(base, blend) min(base + blend, vec3(1.0)) \n "\r
+ "\n#define BlendSubstract(base, blend) max(base + blend - vec3(1.0), vec3(0.0)) \n "\r
+ "\n#define BlendDifference(base, blend) abs(base - blend) \n "\r
+ "\n#define BlendNegation(base, blend) (vec3(1.0) - abs(vec3(1.0) - base - blend)) \n "\r
+ "\n#define BlendExclusion(base, blend) (base + blend - 2.0 * base * blend) \n "\r
+ "\n#define BlendScreen(base, blend) Blend(base, blend, BlendScreenf) \n "\r
+ "\n#define BlendOverlay(base, blend) Blend(base, blend, BlendOverlayf) \n "\r
+ "\n#define BlendSoftLight(base, blend) Blend(base, blend, BlendSoftLightf) \n "\r
+ "\n#define BlendHardLight(base, blend) BlendOverlay(blend, base) \n "\r
+ "\n#define BlendColorDodge(base, blend) Blend(base, blend, BlendColorDodgef) \n "\r
+ "\n#define BlendColorBurn(base, blend) Blend(base, blend, BlendColorBurnf) \n "\r
+ "\n#define BlendLinearDodge BlendAdd \n "\r
+ "\n#define BlendLinearBurn BlendSubstract \n "\r
+ "\n#define BlendLinearLight(base, blend) Blend(base, blend, BlendLinearLightf) \n "\r
+ "\n#define BlendVividLight(base, blend) Blend(base, blend, BlendVividLightf) \n "\r
+ "\n#define BlendPinLight(base, blend) Blend(base, blend, BlendPinLightf) \n "\r
+ "\n#define BlendHardMix(base, blend) Blend(base, blend, BlendHardMixf) \n "\r
+ "\n#define BlendReflect(base, blend) Blend(base, blend, BlendReflectf) \n "\r
+ "\n#define BlendGlow(base, blend) BlendReflect(blend, base) \n "\r
+ "\n#define BlendPhoenix(base, blend) (min(base, blend) - max(base, blend) + vec3(1.0)) \n "\r
+ "\n#define BlendOpacity(base, blend, F, O) (F(base, blend) * O + blend * (1.0 - O)) \n "\r
+ "\n "\r
+ "\n "\r
+ "\n vec3 BlendHue(vec3 base, vec3 blend) "\r
+ "\n { "\r
+ "\n vec3 baseHSL = RGBToHSL(base); "\r
+ "\n return HSLToRGB(vec3(RGBToHSL(blend).r, baseHSL.g, baseHSL.b)); "\r
+ "\n } "\r
+ "\n "\r
+ "\n vec3 BlendSaturation(vec3 base, vec3 blend) "\r
+ "\n { "\r
+ "\n vec3 baseHSL = RGBToHSL(base); "\r
+ "\n return HSLToRGB(vec3(baseHSL.r, RGBToHSL(blend).g, baseHSL.b)); "\r
+ "\n } "\r
+ "\n "\r
+ "\n vec3 BlendColor(vec3 base, vec3 blend) "\r
+ "\n { "\r
+ "\n vec3 blendHSL = RGBToHSL(blend); "\r
+ "\n return HSLToRGB(vec3(blendHSL.r, blendHSL.g, RGBToHSL(base).b)); "\r
+ "\n } "\r
+ "\n "\r
+ "\n vec3 BlendLuminosity(vec3 base, vec3 blend) "\r
+ "\n { "\r
+ "\n vec3 baseHSL = RGBToHSL(base); "\r
+ "\n return HSLToRGB(vec3(baseHSL.r, baseHSL.g, RGBToHSL(blend).b)); "\r
+ "\n } "\r
+ "\n "\r
+ "\n "\r
+ "\n /* "\r
+ "\n ** Gamma correction "\r
+ "\n ** Details: http://blog.mouaif.org/2009/01/22/photoshop-gamma-correction-shader/ "\r
+ "\n */ "\r
+ "\n "\r
+ "\n#define GammaCorrection(color, gamma) pow(color, 1.0 / gamma) \n "\r
+ "\n "\r
+ "\n /* "\r
+ "\n ** Levels control (input (+gamma), output) "\r
+ "\n ** Details: http://blog.mouaif.org/2009/01/28/levels-control-shader/ "\r
+ "\n */ "\r
+ "\n "\r
+ "\n#define LevelsControlInputRange(color, minInput, maxInput) min(max(color - vec3(minInput), vec3(0.0)) / (vec3(maxInput) - vec3(minInput)), vec3(1.0)) \n "\r
+ "\n#define LevelsControlInput(color, minInput, gamma, maxInput) GammaCorrection(LevelsControlInputRange(color, minInput, maxInput), gamma) \n "\r
+ "\n#define LevelsControlOutputRange(color, minOutput, maxOutput) mix(vec3(minOutput), vec3(maxOutput), color) \n "\r
+ "\n#define LevelsControl(color, minInput, gamma, maxInput, minOutput, maxOutput) LevelsControlOutputRange(LevelsControlInput(color, minInput, gamma, maxInput), minOutput, maxOutput) \n "\r
+ ;\r
+ \r
+ return glsl;\r
+}
\ No newline at end of file
#include "../../stdafx.h"\r
\r
#include "image_kernel.h"\r
+#include "blending_glsl.h"\r
\r
#include <common/exception/exceptions.h>\r
#include <common/gl/gl_check.h>\r
glUniform1i(glGetUniformLocation(program_, "plane[2]"), 2);\r
glUniform1i(glGetUniformLocation(program_, "plane[3]"), 3);\r
glUniform1i(glGetUniformLocation(program_, "plane[4]"), 4);\r
+ glUniform1i(glGetUniformLocation(program_, "plane[5]"), 5);\r
}\r
\r
GLint get_location(const char* name)\r
std::unordered_map<core::pixel_format::type, shader_program>& shaders()\r
{\r
GL(glEnable(GL_POLYGON_STIPPLE));\r
- GL(glEnable(GL_BLEND));\r
\r
if(shaders_.empty())\r
{\r
" gl_Position = ftransform(); "\r
"} ";\r
\r
- std::string common_fragment = \r
- "uniform sampler2D plane[5]; "\r
+ std::string common_fragment = std::string() +\r
+ "uniform sampler2D plane[6]; "\r
"uniform float gain; "\r
"uniform bool HD; "\r
"uniform bool local_key; "\r
"uniform bool layer_key; "\r
+ "uniform int blend_mode; "\r
+\r
+ +\r
+\r
+ get_blend_glsl()\r
+\r
+ +\r
+\r
+ "\nvec3 get_blend_color(vec3 back, vec3 fore) "\r
+ "\n{ "\r
+ "\n switch(blend_mode) "\r
+ "\n { "\r
+ "\n case 0: return BlendNormal(back, fore); "\r
+ "\n case 1: return BlendLighten(back, fore); "\r
+ "\n case 2: return BlendDarken(back, fore); "\r
+ "\n case 3: return BlendMultiply(back, fore); "\r
+ "\n case 4: return BlendAverage(back, fore); "\r
+ "\n case 5: return BlendAdd(back, fore); "\r
+ "\n case 6: return BlendSubstract(back, fore); "\r
+ "\n case 7: return BlendDifference(back, fore); "\r
+ "\n case 8: return BlendNegation(back, fore); "\r
+ "\n case 9: return BlendExclusion(back, fore); "\r
+ "\n case 10: return BlendScreen(back, fore); "\r
+ "\n case 11: return BlendOverlay(back, fore); "\r
+ //"\n case 12: return BlendSoftLight(back, fore); "\r
+ //"\n case 13: return BlendHardLight(back, fore); "\r
+ "\n case 14: return BlendColorDodge(back, fore); "\r
+ "\n case 15: return BlendColorBurn(back, fore); "\r
+ "\n case 16: return BlendLinearDodge(back, fore); "\r
+ "\n case 17: return BlendLinearBurn(back, fore); "\r
+ "\n case 18: return BlendLinearLight(back, fore); "\r
+ "\n case 19: return BlendVividLight(back, fore); "\r
+ "\n case 20: return BlendPinLight(back, fore); "\r
+ "\n case 21: return BlendHardMix(back, fore); "\r
+ "\n case 22: return BlendReflect(back, fore); "\r
+ "\n case 23: return BlendGlow(back, fore); "\r
+ "\n case 24: return BlendPhoenix(back, fore); "\r
+ "\n case 25: return BlendHue(back, fore); "\r
+ "\n case 26: return BlendSaturation(back, fore); "\r
+ "\n case 27: return BlendColor(back, fore); "\r
+ "\n case 28: return BlendLuminosity(back, fore); "\r
+ "\n } "\r
+ "\n "\r
+ "\n return BlendNormal(back, fore); "\r
+ "\n} "\r
+ \r
+ "vec4 get_color(vec4 fore) "\r
+ "{ "\r
+ " vec4 back = texture2D(plane[5], gl_TexCoord[1].st); "\r
+ " fore.rgb = get_blend_color(back.rgb, fore.rgb);"\r
+ " return vec4(fore.rgb * fore.a + back.rgb * (1.0-fore.a), back.a + fore.a);"\r
+ "} "\r
\r
// NOTE: YCbCr, ITU-R, http://www.intersil.com/data/an/an9717.pdf \r
// TODO: Support for more yuv formats might be needed. \r
" rgba.a *= texture2D(plane[3], gl_TexCoord[1].st).r; "\r
" if(layer_key) "\r
" rgba.a *= texture2D(plane[4], gl_TexCoord[1].st).r; "\r
- " gl_FragColor = rgba * gain; "\r
+ " gl_FragColor = get_color(rgba * gain); "\r
"} ");\r
\r
shaders_[core::pixel_format::abgr] = shader_program(common_vertex, common_fragment +\r
" abgr.b *= texture2D(plane[3], gl_TexCoord[1].st).r; "\r
" if(layer_key) "\r
" abgr.b *= texture2D(plane[4], gl_TexCoord[1].st).r; "\r
- " gl_FragColor = abgr.argb * gain; "\r
+ " gl_FragColor = get_color(abgr.argb * gain); "\r
"} ");\r
\r
shaders_[core::pixel_format::argb]= shader_program(common_vertex, common_fragment +\r
" argb.b *= texture2D(plane[3], gl_TexCoord[1].st).r; "\r
" if(layer_key) "\r
" argb.b *= texture2D(plane[4], gl_TexCoord[1].st).r; "\r
- " gl_FragColor = argb.grab * gl_Color * gain; "\r
+ " gl_FragColor = get_color(argb.grab * gl_Color * gain); "\r
"} ");\r
\r
shaders_[core::pixel_format::bgra]= shader_program(common_vertex, common_fragment +\r
" bgra.a *= texture2D(plane[3], gl_TexCoord[1].st).r; "\r
" if(layer_key) "\r
" bgra.a *= texture2D(plane[4], gl_TexCoord[1].st).r; "\r
- " gl_FragColor = bgra.rgba * gl_Color * gain; "\r
+ " gl_FragColor = get_color(bgra.rgba * gl_Color * gain); "\r
"} ");\r
\r
shaders_[core::pixel_format::rgba] = shader_program(common_vertex, common_fragment +\r
" rgba.a *= texture2D(plane[3], gl_TexCoord[1].st).r; "\r
" if(layer_key) "\r
" rgba.a *= texture2D(plane[4], gl_TexCoord[1].st).r; "\r
- " gl_FragColor = rgba.bgra * gl_Color * gain; "\r
+ " gl_FragColor = get_color(rgba.bgra * gl_Color * gain); "\r
"} ");\r
\r
shaders_[core::pixel_format::ycbcr] = shader_program(common_vertex, common_fragment +\r
" if(layer_key) "\r
" a *= texture2D(plane[4], gl_TexCoord[1].st).r; "\r
" if(HD) "\r
- " gl_FragColor = ycbcra_to_bgra_hd(y, cb, cr, a) * gl_Color * gain;"\r
+ " gl_FragColor = get_color(ycbcra_to_bgra_hd(y, cb, cr, a) * gl_Color * gain);"\r
" else "\r
- " gl_FragColor = ycbcra_to_bgra_sd(y, cb, cr, a) * gl_Color * gain;"\r
+ " gl_FragColor = get_color(ycbcra_to_bgra_sd(y, cb, cr, a) * gl_Color * gain);"\r
"} ");\r
\r
shaders_[core::pixel_format::ycbcra] = shader_program(common_vertex, common_fragment +\r
" if(layer_key) "\r
" a *= texture2D(plane[4], gl_TexCoord[1].st).r; "\r
" if(HD) "\r
- " gl_FragColor = ycbcra_to_bgra_hd(y, cb, cr, a) * gl_Color * gain;"\r
+ " gl_FragColor = get_color(ycbcra_to_bgra_hd(y, cb, cr, a) * gl_Color * gain);"\r
" else "\r
- " gl_FragColor = ycbcra_to_bgra_sd(y, cb, cr, a) * gl_Color * gain;"\r
+ " gl_FragColor = get_color(ycbcra_to_bgra_sd(y, cb, cr, a) * gl_Color * gain);"\r
"} ");\r
}\r
return shaders_;\r
\r
void image_kernel::draw(size_t width, size_t height, const core::pixel_format_desc& pix_desc, const core::image_transform& transform, bool local_key, bool layer_key)\r
{\r
- if(transform.get_opacity() < 0.001)\r
- return;\r
-\r
- switch(transform.get_blend_mode())\r
- {\r
- case image_transform::screen:\r
- GL(glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_COLOR, GL_ONE, GL_ONE));\r
- break;\r
- default:\r
- GL(glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE));\r
- }\r
-\r
GL(glEnable(GL_TEXTURE_2D));\r
GL(glDisable(GL_DEPTH_TEST)); \r
+ \r
+ if(transform.get_mode() == core::video_mode::upper)\r
+ glPolygonStipple(upper_pattern);\r
+ else if(transform.get_mode() == core::video_mode::lower)\r
+ glPolygonStipple(lower_pattern);\r
+ else\r
+ glPolygonStipple(progressive_pattern);\r
\r
impl_->shaders()[pix_desc.pix_fmt].use();\r
\r
GL(glUniform1i(impl_->shaders()[pix_desc.pix_fmt].get_location("HD"), pix_desc.planes.at(0).height > 700 ? 1 : 0));\r
GL(glUniform1i(impl_->shaders()[pix_desc.pix_fmt].get_location("local_key"), local_key ? 1 : 0));\r
GL(glUniform1i(impl_->shaders()[pix_desc.pix_fmt].get_location("layer_key"), layer_key ? 1 : 0));\r
+ GL(glUniform1i(impl_->shaders()[pix_desc.pix_fmt].get_location("blend_mode"), transform.get_blend_mode()));\r
\r
- if(transform.get_mode() == core::video_mode::upper)\r
- glPolygonStipple(upper_pattern);\r
- else if(transform.get_mode() == core::video_mode::lower)\r
- glPolygonStipple(lower_pattern);\r
- else\r
- glPolygonStipple(progressive_pattern);\r
- \r
GL(glColor4d(1.0, 1.0, 1.0, transform.get_opacity()));\r
GL(glViewport(0, 0, width, height));\r
\r
{ \r
static const size_t LOCAL_KEY_INDEX = 3;\r
static const size_t LAYER_KEY_INDEX = 4;\r
+ static const size_t BASE_INDEX = 5;\r
\r
video_channel_context& channel_;\r
\r
std::stack<core::image_transform> transform_stack_;\r
\r
- std::queue<std::queue<std::queue<render_item>>> render_queue_; // layer/stream/items\r
+ std::queue<std::queue<std::deque<render_item>>> render_queue_; // layer/stream/items\r
\r
image_kernel kernel_;\r
\r
- safe_ptr<device_buffer> draw_buffer_;\r
- safe_ptr<device_buffer> write_buffer_;\r
+ std::shared_ptr<device_buffer> draw_buffer_[2];\r
+ std::shared_ptr<device_buffer> write_buffer_;\r
\r
- safe_ptr<device_buffer> stream_key_buffer_;\r
- safe_ptr<device_buffer> layer_key_buffer_;\r
+ std::shared_ptr<device_buffer> stream_key_buffer_[2];\r
+ std::shared_ptr<device_buffer> layer_key_buffer_;\r
\r
bool local_key_;\r
bool layer_key_;\r
public:\r
implementation(video_channel_context& video_channel) \r
: channel_(video_channel)\r
- , draw_buffer_(video_channel.ogl().create_device_buffer(video_channel.get_format_desc().width, channel_.get_format_desc().height, 4))\r
, write_buffer_ (video_channel.ogl().create_device_buffer(video_channel.get_format_desc().width, channel_.get_format_desc().height, 4))\r
- , stream_key_buffer_(video_channel.ogl().create_device_buffer(video_channel.get_format_desc().width, channel_.get_format_desc().height, 1))\r
, layer_key_buffer_(video_channel.ogl().create_device_buffer(video_channel.get_format_desc().width, channel_.get_format_desc().height, 1))\r
, local_key_(false)\r
, layer_key_(false)\r
{\r
+ draw_buffer_[0] = channel_.ogl().create_device_buffer(video_channel.get_format_desc().width, channel_.get_format_desc().height, 4);\r
+ draw_buffer_[1] = channel_.ogl().create_device_buffer(video_channel.get_format_desc().width, channel_.get_format_desc().height, 4);\r
+ stream_key_buffer_[0] = video_channel.ogl().create_device_buffer(video_channel.get_format_desc().width, channel_.get_format_desc().height, 1);\r
+ stream_key_buffer_[1] = video_channel.ogl().create_device_buffer(video_channel.get_format_desc().width, channel_.get_format_desc().height, 1);\r
+\r
transform_stack_.push(core::image_transform());\r
\r
channel_.ogl().invoke([=]\r
auto& layer = render_queue_.back();\r
\r
if(layer.empty() || (!layer.back().empty() && layer.back().back().tag != frame.tag()))\r
- layer.push(std::queue<render_item>());\r
+ layer.push(std::deque<render_item>());\r
\r
- layer.back().push(item);\r
+ layer.back().push_back(item);\r
}\r
\r
void end()\r
\r
void begin_layer()\r
{\r
- render_queue_.push(std::queue<std::queue<render_item>>());\r
+ render_queue_.push(std::queue<std::deque<render_item>>());\r
}\r
\r
void end_layer()\r
\r
void reinitialize_buffers()\r
{\r
- draw_buffer_ = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 4);\r
- write_buffer_ = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 4);\r
- stream_key_buffer_ = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 1);\r
- layer_key_buffer_ = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 1);\r
+ draw_buffer_[0] = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 4);\r
+ draw_buffer_[1] = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 4);\r
+ write_buffer_ = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 4);\r
+ stream_key_buffer_[0] = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 1);\r
+ stream_key_buffer_[1] = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 1);\r
+ layer_key_buffer_ = channel_.ogl().create_device_buffer(channel_.get_format_desc().width, channel_.get_format_desc().height, 1);\r
channel_.ogl().gc();\r
}\r
\r
\r
return channel_.ogl().invoke([=]() mutable -> safe_ptr<host_buffer>\r
{\r
- if(draw_buffer_->width() != channel_.get_format_desc().width || draw_buffer_->height() != channel_.get_format_desc().height)\r
+ if(draw_buffer_[0]->width() != channel_.get_format_desc().width || draw_buffer_[0]->height() != channel_.get_format_desc().height)\r
reinitialize_buffers();\r
\r
return do_render(std::move(render_queue));\r
});\r
}\r
\r
- safe_ptr<host_buffer> do_render(std::queue<std::queue<std::queue<render_item>>>&& render_queue)\r
+ safe_ptr<host_buffer> do_render(std::queue<std::queue<std::deque<render_item>>>&& render_queue)\r
{\r
auto read_buffer = channel_.ogl().create_host_buffer(channel_.get_format_desc().size, host_buffer::read_only);\r
\r
layer_key_buffer_->clear();\r
- draw_buffer_->clear();\r
+ draw_buffer_[0]->clear();\r
+ draw_buffer_[1]->clear();\r
+ stream_key_buffer_[0]->clear();\r
+ stream_key_buffer_[1]->clear();\r
+\r
+ bool local_key = false;\r
+ bool layer_key = false;\r
\r
while(!render_queue.empty())\r
{ \r
- stream_key_buffer_->clear();\r
+ stream_key_buffer_[0]->clear();\r
\r
auto layer = std::move(render_queue.front());\r
render_queue.pop();\r
- \r
+\r
while(!layer.empty())\r
{\r
auto stream = std::move(layer.front());\r
layer.pop();\r
+ \r
+ render(stream, local_key, layer_key);\r
+ \r
+ local_key = stream.front().transform.get_is_key();\r
+ if(!local_key)\r
+ stream_key_buffer_[0]->clear();\r
\r
- bool last_is_key = stream.empty() ? false : stream.back().transform.get_is_key();\r
-\r
- while(!stream.empty())\r
- {\r
- auto item = std::move(stream.front());\r
- stream.pop();\r
-\r
- render(item);\r
-\r
- channel_.ogl().yield(); // Allow quick buffer allocation to execute.\r
- } \r
-\r
- if(!last_is_key)\r
- stream_key_buffer_->clear();\r
+ channel_.ogl().yield();\r
}\r
\r
- std::swap(stream_key_buffer_, layer_key_buffer_);\r
+ layer_key = local_key;\r
+ local_key = false;\r
+ std::swap(stream_key_buffer_[0], layer_key_buffer_);\r
}\r
\r
- std::swap(draw_buffer_, write_buffer_);\r
+ std::swap(draw_buffer_[0], write_buffer_);\r
\r
// Start transfer from device to host. \r
write_buffer_->write(*read_buffer);\r
return read_buffer;\r
}\r
\r
- void render(render_item& item)\r
+ void render(std::deque<render_item>& stream, bool local_key, bool layer_key)\r
{\r
- for(size_t n = 0; n < item.textures.size(); ++n)\r
- item.textures[n]->bind(n); \r
- \r
- if(item.transform.get_is_key())\r
+ while(stream.size() > 2)\r
+ stream.pop_front();\r
+ \r
+ BOOST_FOREACH(auto item2, stream)\r
{\r
- stream_key_buffer_->attach();\r
+ for(size_t n = 0; n < item2.textures.size(); ++n)\r
+ item2.textures[n]->bind(n); \r
+ }\r
\r
- kernel_.draw(channel_.get_format_desc().width, channel_.get_format_desc().height, item.desc, item.transform, false, false); \r
+ if(stream.front().transform.get_is_key())\r
+ {\r
+ stream_key_buffer_[0]->bind(BASE_INDEX); \r
+ stream_key_buffer_[1]->attach();\r
+ \r
+ BOOST_FOREACH(auto item2, stream)\r
+ kernel_.draw(channel_.get_format_desc().width, channel_.get_format_desc().height, item2.desc, item2.transform, false, false);\r
+ \r
+ std::swap(stream_key_buffer_[0], stream_key_buffer_[1]);\r
+\r
+ stream_key_buffer_[1]->bind();\r
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, channel_.get_format_desc().width, channel_.get_format_desc().height); \r
}\r
else\r
{\r
- stream_key_buffer_->bind(LOCAL_KEY_INDEX); \r
+ stream_key_buffer_[0]->bind(LOCAL_KEY_INDEX); \r
layer_key_buffer_->bind(LAYER_KEY_INDEX);\r
- \r
- draw_buffer_->attach(); \r
-\r
- kernel_.draw(channel_.get_format_desc().width, channel_.get_format_desc().height, item.desc, item.transform, !stream_key_buffer_->empty(), !layer_key_buffer_->empty()); \r
+ \r
+ draw_buffer_[0]->bind(BASE_INDEX); \r
+ draw_buffer_[1]->attach(); \r
+ \r
+ BOOST_FOREACH(auto item2, stream)\r
+ kernel_.draw(channel_.get_format_desc().width, channel_.get_format_desc().height, item2.desc, item2.transform, local_key, layer_key); \r
+ \r
+ std::swap(draw_buffer_[0], draw_buffer_[1]);\r
+ \r
+ draw_buffer_[1]->bind();\r
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, channel_.get_format_desc().width, channel_.get_format_desc().height);\r
}\r
}\r
\r
+++ /dev/null
-#pragma once\r
-\r
-static std::string get_math_glsl()\r
-{\r
- static std::string glsl = \r
- "/* "\r
- "** Photoshop & misc math "\r
- "** Blending modes, RGB/HSL/Contrast/Desaturate, levels control "\r
- "** "\r
- "** Romain Dura | Romz "\r
- "** Blog: http://blog.mouaif.org "\r
- "** Post: http://blog.mouaif.org/?p=94 "\r
- "*/ "\r
- " "\r
- " "\r
- "/* "\r
- "** Desaturation "\r
- "*/ "\r
- " "\r
- "vec4 Desaturate(vec3 color, float Desaturation) "\r
- "{ "\r
- " vec3 grayXfer = vec3(0.3, 0.59, 0.11); "\r
- " vec3 gray = vec3(dot(grayXfer, color)); "\r
- " return vec4(mix(color, gray, Desaturation), 1.0); "\r
- "} "\r
- " "\r
- " "\r
- "/* "\r
- "** Hue, saturation, luminance "\r
- "*/ "\r
- " "\r
- "vec3 RGBToHSL(vec3 color) "\r
- "{ "\r
- " vec3 hsl; // init to 0 to avoid warnings ? (and reverse if + remove first part) "\r
- " "\r
- " float fmin = min(min(color.r, color.g), color.b); //Min. value of RGB "\r
- " float fmax = max(max(color.r, color.g), color.b); //Max. value of RGB "\r
- " float delta = fmax - fmin; //Delta RGB value "\r
- " "\r
- " hsl.z = (fmax + fmin) / 2.0; // Luminance "\r
- " "\r
- " if (delta == 0.0) //This is a gray, no chroma... "\r
- " { "\r
- " hsl.x = 0.0; // Hue "\r
- " hsl.y = 0.0; // Saturation "\r
- " } "\r
- " else //Chromatic data... "\r
- " { "\r
- " if (hsl.z < 0.5) "\r
- " hsl.y = delta / (fmax + fmin); // Saturation "\r
- " else "\r
- " hsl.y = delta / (2.0 - fmax - fmin); // Saturation "\r
- " "\r
- " float deltaR = (((fmax - color.r) / 6.0) + (delta / 2.0)) / delta; "\r
- " float deltaG = (((fmax - color.g) / 6.0) + (delta / 2.0)) / delta; "\r
- " float deltaB = (((fmax - color.b) / 6.0) + (delta / 2.0)) / delta; "\r
- " "\r
- " if (color.r == fmax ) "\r
- " hsl.x = deltaB - deltaG; // Hue "\r
- " else if (color.g == fmax) "\r
- " hsl.x = (1.0 / 3.0) + deltaR - deltaB; // Hue "\r
- " else if (color.b == fmax) "\r
- " hsl.x = (2.0 / 3.0) + deltaG - deltaR; // Hue "\r
- " "\r
- " if (hsl.x < 0.0) "\r
- " hsl.x += 1.0; // Hue "\r
- " else if (hsl.x > 1.0) "\r
- " hsl.x -= 1.0; // Hue "\r
- " } "\r
- " "\r
- " return hsl; "\r
- "} "\r
- " "\r
- "float HueToRGB(float f1, float f2, float hue) "\r
- "{ "\r
- " if (hue < 0.0) "\r
- " hue += 1.0; "\r
- " else if (hue > 1.0) "\r
- " hue -= 1.0; "\r
- " float res; "\r
- " if ((6.0 * hue) < 1.0) "\r
- " res = f1 + (f2 - f1) * 6.0 * hue; "\r
- " else if ((2.0 * hue) < 1.0) "\r
- " res = f2; "\r
- " else if ((3.0 * hue) < 2.0) "\r
- " res = f1 + (f2 - f1) * ((2.0 / 3.0) - hue) * 6.0; "\r
- " else "\r
- " res = f1; "\r
- " return res; "\r
- "} "\r
- " "\r
- "vec3 HSLToRGB(vec3 hsl) "\r
- "{ "\r
- " vec3 rgb; "\r
- " "\r
- " if (hsl.y == 0.0) "\r
- " rgb = vec3(hsl.z); // Luminance "\r
- " else "\r
- " { "\r
- " float f2; "\r
- " "\r
- " if (hsl.z < 0.5) "\r
- " f2 = hsl.z * (1.0 + hsl.y); "\r
- " else "\r
- " f2 = (hsl.z + hsl.y) - (hsl.y * hsl.z); "\r
- " "\r
- " float f1 = 2.0 * hsl.z - f2; "\r
- " "\r
- " rgb.r = HueToRGB(f1, f2, hsl.x + (1.0/3.0)); "\r
- " rgb.g = HueToRGB(f1, f2, hsl.x); "\r
- " rgb.b= HueToRGB(f1, f2, hsl.x - (1.0/3.0)); "\r
- " } "\r
- " "\r
- " return rgb; "\r
- "} "\r
- " "\r
- " "\r
- "/* "\r
- "** Contrast, saturation, brightness "\r
- "** Code of this function is from TGM's shader pack "\r
- "** http://irrlicht.sourceforge.net/phpBB2/viewtopic.php?t=21057 "\r
- "*/ "\r
- " "\r
- "// For all settings: 1.0 = 100% 0.5=50% 1.5 = 150% "\r
- "vec3 ContrastSaturationBrightness(vec3 color, float brt, float sat, float con) "\r
- "{ "\r
- " // Increase or decrease theese values to adjust r, g and b color channels seperately "\r
- " const float AvgLumR = 0.5; "\r
- " const float AvgLumG = 0.5; "\r
- " const float AvgLumB = 0.5; "\r
- " "\r
- " const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721); "\r
- " "\r
- " vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB); "\r
- " vec3 brtColor = color * brt; "\r
- " vec3 intensity = vec3(dot(brtColor, LumCoeff)); "\r
- " vec3 satColor = mix(intensity, brtColor, sat); "\r
- " vec3 conColor = mix(AvgLumin, satColor, con); "\r
- " return conColor; "\r
- "} "\r
- " "\r
- " "\r
- "/* "\r
- "** Float blending modes "\r
- "** Adapted from here: http://www.nathanm.com/photoshop-blending-math/ "\r
- "** But I modified the HardMix (wrong condition), Overlay, SoftLight, ColorDodge, ColorBurn, VividLight, PinLight (inverted layers) ones to have correct results "\r
- "*/ "\r
- " "\r
- "#define BlendLinearDodgef BlendAddf "\r
- "#define BlendLinearBurnf BlendSubstractf "\r
- "#define BlendAddf(base, blend) min(base + blend, 1.0) "\r
- "#define BlendSubstractf(base, blend) max(base + blend - 1.0, 0.0) "\r
- "#define BlendLightenf(base, blend) max(blend, base) "\r
- "#define BlendDarkenf(base, blend) min(blend, base) "\r
- "#define BlendLinearLightf(base, blend) (blend < 0.5 ? BlendLinearBurnf(base, (2.0 * blend)) : BlendLinearDodgef(base, (2.0 * (blend - 0.5)))) "\r
- "#define BlendScreenf(base, blend) (1.0 - ((1.0 - base) * (1.0 - blend))) "\r
- "#define BlendOverlayf(base, blend) (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend))) "\r
- "#define BlendSoftLightf(base, blend) ((blend < 0.5) ? (2.0 * base * blend + base * base * (1.0 - 2.0 * blend)) : (sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend))) "\r
- "#define BlendColorDodgef(base, blend) ((blend == 1.0) ? blend : min(base / (1.0 - blend), 1.0)) "\r
- "#define BlendColorBurnf(base, blend) ((blend == 0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0)) "\r
- "#define BlendVividLightf(base, blend) ((blend < 0.5) ? BlendColorBurnf(base, (2.0 * blend)) : BlendColorDodgef(base, (2.0 * (blend - 0.5)))) "\r
- "#define BlendPinLightf(base, blend) ((blend < 0.5) ? BlendDarkenf(base, (2.0 * blend)) : BlendLightenf(base, (2.0 *(blend - 0.5)))) "\r
- "#define BlendHardMixf(base, blend) ((BlendVividLightf(base, blend) < 0.5) ? 0.0 : 1.0) "\r
- "#define BlendReflectf(base, blend) ((blend == 1.0) ? blend : min(base * base / (1.0 - blend), 1.0)) "\r
- " "\r
- " "\r
- "/* "\r
- "** Vector3 blending modes "\r
- "*/ "\r
- " "\r
- "// Component wise blending "\r
- "#define Blend(base, blend, funcf) vec3(funcf(base.r, blend.r), funcf(base.g, blend.g), funcf(base.b, blend.b)) "\r
- " "\r
- "#define BlendNormal(base, blend) (blend) "\r
- "#define BlendLighten BlendLightenf "\r
- "#define BlendDarken BlendDarkenf "\r
- "#define BlendMultiply(base, blend) (base * blend) "\r
- "#define BlendAverage(base, blend) ((base + blend) / 2.0) "\r
- "#define BlendAdd(base, blend) min(base + blend, vec3(1.0)) "\r
- "#define BlendSubstract(base, blend) max(base + blend - vec3(1.0), vec3(0.0)) "\r
- "#define BlendDifference(base, blend) abs(base - blend) "\r
- "#define BlendNegation(base, blend) (vec3(1.0) - abs(vec3(1.0) - base - blend)) "\r
- "#define BlendExclusion(base, blend) (base + blend - 2.0 * base * blend) "\r
- "#define BlendScreen(base, blend) Blend(base, blend, BlendScreenf) "\r
- "#define BlendOverlay(base, blend) Blend(base, blend, BlendOverlayf) "\r
- "#define BlendSoftLight(base, blend) Blend(base, blend, BlendSoftLightf) "\r
- "#define BlendHardLight(base, blend) BlendOverlay(blend, base) "\r
- "#define BlendColorDodge(base, blend) Blend(base, blend, BlendColorDodgef) "\r
- "#define BlendColorBurn(base, blend) Blend(base, blend, BlendColorBurnf) "\r
- "#define BlendLinearDodge BlendAdd "\r
- "#define BlendLinearBurn BlendSubstract "\r
- "// Linear Light is another contrast-increasing mode "\r
- "// If the blend color is darker than midgray, Linear Light darkens the image by decreasing the brightness. If the blend color is lighter than midgray, the result is a brighter image due to increased brightness."\r
- "#define BlendLinearLight(base, blend) Blend(base, blend, BlendLinearLightf) "\r
- "#define BlendVividLight(base, blend) Blend(base, blend, BlendVividLightf) "\r
- "#define BlendPinLight(base, blend) Blend(base, blend, BlendPinLightf) "\r
- "#define BlendHardMix(base, blend) Blend(base, blend, BlendHardMixf) "\r
- "#define BlendReflect(base, blend) Blend(base, blend, BlendReflectf) "\r
- "#define BlendGlow(base, blend) BlendReflect(blend, base) "\r
- "#define BlendPhoenix(base, blend) (min(base, blend) - max(base, blend) + vec3(1.0)) "\r
- "#define BlendOpacity(base, blend, F, O) (F(base, blend) * O + blend * (1.0 - O)) "\r
- " "\r
- " "\r
- "// Hue Blend mode creates the result color by combining the luminance and saturation of the base color with the hue of the blend color. "\r
- "vec3 BlendHue(vec3 base, vec3 blend) "\r
- "{ "\r
- " vec3 baseHSL = RGBToHSL(base); "\r
- " return HSLToRGB(vec3(RGBToHSL(blend).r, baseHSL.g, baseHSL.b)); "\r
- "} "\r
- " "\r
- "// Saturation Blend mode creates the result color by combining the luminance and hue of the base color with the saturation of the blend color. "\r
- "vec3 BlendSaturation(vec3 base, vec3 blend) "\r
- "{ "\r
- " vec3 baseHSL = RGBToHSL(base); "\r
- " return HSLToRGB(vec3(baseHSL.r, RGBToHSL(blend).g, baseHSL.b)); "\r
- "} "\r
- " "\r
- "// Color Mode keeps the brightness of the base color and applies both the hue and saturation of the blend color. "\r
- "vec3 BlendColor(vec3 base, vec3 blend) "\r
- "{ "\r
- " vec3 blendHSL = RGBToHSL(blend); "\r
- " return HSLToRGB(vec3(blendHSL.r, blendHSL.g, RGBToHSL(base).b)); "\r
- "} "\r
- " "\r
- "// Luminosity Blend mode creates the result color by combining the hue and saturation of the base color with the luminance of the blend color. "\r
- "vec3 BlendLuminosity(vec3 base, vec3 blend) "\r
- "{ "\r
- " vec3 baseHSL = RGBToHSL(base); "\r
- " return HSLToRGB(vec3(baseHSL.r, baseHSL.g, RGBToHSL(blend).b)); "\r
- "} "\r
- " "\r
- " "\r
- "/* "\r
- "** Gamma correction "\r
- "** Details: http://blog.mouaif.org/2009/01/22/photoshop-gamma-correction-shader/ "\r
- "*/ "\r
- " "\r
- "#define GammaCorrection(color, gamma) pow(color, 1.0 / gamma) "\r
- " "\r
- "/* "\r
- "** Levels control (input (+gamma), output) "\r
- "** Details: http://blog.mouaif.org/2009/01/28/levels-control-shader/ "\r
- "*/ "\r
- " "\r
- "#define LevelsControlInputRange(color, minInput, maxInput) min(max(color - vec3(minInput), vec3(0.0)) / (vec3(maxInput) - vec3(minInput)), vec3(1.0)) "\r
- "#define LevelsControlInput(color, minInput, gamma, maxInput) GammaCorrection(LevelsControlInputRange(color, minInput, maxInput), gamma) "\r
- "#define LevelsControlOutputRange(color, minOutput, maxOutput) mix(vec3(minOutput), vec3(maxOutput), color) "\r
- "#define LevelsControl(color, minInput, gamma, maxInput, minOutput, maxOutput) LevelsControlOutputRange(LevelsControlInput(color, minInput, gamma, maxInput), minOutput, maxOutput) ";\r
- \r
- return glsl;\r
-}
\ No newline at end of file
\r
#include <common/utility/assert.h>\r
\r
+#include <boost/algorithm/string.hpp>\r
+\r
namespace caspar { namespace core {\r
\r
image_transform::image_transform() \r
if(other.mode_ != video_mode::invalid)\r
mode_ = other.mode_;\r
\r
- blend_mode_ = other.blend_mode_;\r
+ blend_mode_ = std::max(blend_mode_, other.blend_mode_);\r
gain_ *= other.gain_;\r
deinterlace_ |= other.deinterlace_;\r
is_key_ |= other.is_key_;\r
\r
image_transform result; \r
result.set_mode (dest.get_mode() != video_mode::invalid ? dest.get_mode() : source.get_mode());\r
- result.set_blend_mode (dest.get_blend_mode());\r
+ result.set_blend_mode (std::max(source.get_blend_mode(), dest.get_blend_mode()));\r
result.set_is_key (source.get_is_key() | dest.get_is_key());\r
result.set_deinterlace (source.get_deinterlace() | dest.get_deinterlace());\r
result.set_gain (do_tween(time, source.get_gain(), dest.get_gain(), duration, tweener));\r
return result;\r
}\r
\r
+image_transform::blend_mode get_blend_mode(const std::wstring& str)\r
+{\r
+ if(boost::iequals(str, L"normal"))\r
+ return image_transform::normal;\r
+ else if(boost::iequals(str, L"lighten"))\r
+ return image_transform::lighten;\r
+ else if(boost::iequals(str, L"darken"))\r
+ return image_transform::darken;\r
+ else if(boost::iequals(str, L"multiply"))\r
+ return image_transform::multiply;\r
+ else if(boost::iequals(str, L"average"))\r
+ return image_transform::average;\r
+ else if(boost::iequals(str, L"add"))\r
+ return image_transform::add;\r
+ else if(boost::iequals(str, L"subtract"))\r
+ return image_transform::subtract;\r
+ else if(boost::iequals(str, L"difference"))\r
+ return image_transform::difference;\r
+ else if(boost::iequals(str, L"negation"))\r
+ return image_transform::negation;\r
+ else if(boost::iequals(str, L"exclusion"))\r
+ return image_transform::exclusion;\r
+ else if(boost::iequals(str, L"screen"))\r
+ return image_transform::screen;\r
+ else if(boost::iequals(str, L"overlay"))\r
+ return image_transform::overlay;\r
+ else if(boost::iequals(str, L"soft_light"))\r
+ return image_transform::soft_light;\r
+ else if(boost::iequals(str, L"hard_light"))\r
+ return image_transform::hard_light;\r
+ else if(boost::iequals(str, L"color_dodge"))\r
+ return image_transform::color_dodge;\r
+ else if(boost::iequals(str, L"color_burn"))\r
+ return image_transform::color_burn;\r
+ else if(boost::iequals(str, L"linear_dodge"))\r
+ return image_transform::linear_dodge;\r
+ else if(boost::iequals(str, L"linear_burn"))\r
+ return image_transform::linear_burn;\r
+ else if(boost::iequals(str, L"linear_light"))\r
+ return image_transform::linear_light;\r
+ else if(boost::iequals(str, L"vivid_light"))\r
+ return image_transform::vivid_light;\r
+ else if(boost::iequals(str, L"pin_light"))\r
+ return image_transform::pin_light;\r
+ else if(boost::iequals(str, L"hard_mix"))\r
+ return image_transform::hard_mix;\r
+ else if(boost::iequals(str, L"reflect"))\r
+ return image_transform::reflect;\r
+ else if(boost::iequals(str, L"glow"))\r
+ return image_transform::glow;\r
+ else if(boost::iequals(str, L"phoenix"))\r
+ return image_transform::phoenix;\r
+ else if(boost::iequals(str, L"hue"))\r
+ return image_transform::hue;\r
+ else if(boost::iequals(str, L"saturation"))\r
+ return image_transform::saturation;\r
+ else if(boost::iequals(str, L"color"))\r
+ return image_transform::color;\r
+ else if(boost::iequals(str, L"luminosity"))\r
+ return image_transform::luminosity;\r
+ \r
+ return image_transform::normal;\r
+}\r
+\r
}}
\ No newline at end of file
\r
enum blend_mode\r
{\r
- normal,\r
- screen\r
+ normal = 0,\r
+ lighten,\r
+ darken,\r
+ multiply,\r
+ average,\r
+ add,\r
+ subtract,\r
+ difference,\r
+ negation,\r
+ exclusion,\r
+ screen,\r
+ overlay,\r
+ soft_light,\r
+ hard_light,\r
+ color_dodge,\r
+ color_burn,\r
+ linear_dodge,\r
+ linear_burn,\r
+ linear_light,\r
+ vivid_light,\r
+ pin_light,\r
+ hard_mix,\r
+ reflect,\r
+ glow,\r
+ phoenix,\r
+ hue,\r
+ saturation,\r
+ color,\r
+ luminosity,\r
+ blend_mode_count \r
};\r
\r
image_transform();\r
blend_mode blend_mode_;\r
};\r
\r
+image_transform::blend_mode get_blend_mode(const std::wstring& str);\r
+\r
image_transform tween(double time, const image_transform& source, const image_transform& dest, double duration, const tweener_t& tweener);\r
\r
inline bool operator==(const image_transform& lhs, const image_transform& rhs)\r
{ \r
enum type\r
{\r
- progressive,\r
+ progressive = 0,\r
lower,\r
upper,\r
count,\r
\r
\r
/* File created by MIDL compiler version 7.00.0555 */\r
-/* at Thu Jun 23 10:58:47 2011\r
+/* at Sat Jun 25 15:44:58 2011\r
*/\r
/* Compiler settings for interop\DeckLinkAPI.idl:\r
Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 \r
\r
\r
/* File created by MIDL compiler version 7.00.0555 */\r
-/* at Thu Jun 23 10:58:47 2011\r
+/* at Sat Jun 25 15:44:58 2011\r
*/\r
/* Compiler settings for interop\DeckLinkAPI.idl:\r
Oicf, W1, Zp8, env=Win32 (32b run), target_arch=X86 7.00.0555 \r
auto blend_str = _parameters.at(2);\r
auto transform = [=](image_transform transform) -> image_transform\r
{\r
- if(blend_str == L"NORMAL")\r
- transform.set_blend_mode(image_transform::normal);\r
- else if(blend_str == L"SCREEN")\r
- transform.set_blend_mode(image_transform::screen);\r
- \r
+ transform.set_blend_mode(get_blend_mode(blend_str));\r
return transform;\r
};\r
\r