From 725d593db3fb5d48f53361cd21001a72aacbe17a Mon Sep 17 00:00:00 2001 From: Struma Date: Mon, 29 Nov 2021 21:58:18 -0500 Subject: [PATCH] add Sprite.pattern_blend_type --- binding/sprite-binding.cpp | 2 ++ shader/sprite.frag | 62 ++++++++++++++++++++++++++++++++++---- shader/sprite.vert | 8 ++--- src/display/gl/shader.cpp | 6 ++++ src/display/gl/shader.h | 3 +- src/display/sprite.cpp | 22 ++++++++++++++ src/display/sprite.h | 1 + 7 files changed, 93 insertions(+), 11 deletions(-) diff --git a/binding/sprite-binding.cpp b/binding/sprite-binding.cpp index 49336321..c697ee8b 100644 --- a/binding/sprite-binding.cpp +++ b/binding/sprite-binding.cpp @@ -65,6 +65,7 @@ DEF_GFX_PROP_I(Sprite, BushDepth) DEF_GFX_PROP_I(Sprite, BushOpacity) DEF_GFX_PROP_I(Sprite, Opacity) DEF_GFX_PROP_I(Sprite, BlendType) +DEF_GFX_PROP_I(Sprite, PatternBlendType) DEF_GFX_PROP_I(Sprite, PatternOpacity) DEF_GFX_PROP_I(Sprite, PatternScrollX) DEF_GFX_PROP_I(Sprite, PatternScrollY) @@ -141,6 +142,7 @@ void spriteBindingInit() { INIT_PROP_BIND(Sprite, BushOpacity, "bush_opacity"); INIT_PROP_BIND(Sprite, Pattern, "pattern"); + INIT_PROP_BIND(Sprite, PatternBlendType, "pattern_blend_type"); INIT_PROP_BIND(Sprite, PatternTile, "pattern_tile"); INIT_PROP_BIND(Sprite, PatternOpacity, "pattern_opacity"); INIT_PROP_BIND(Sprite, PatternScrollX, "pattern_scroll_x"); diff --git a/shader/sprite.frag b/shader/sprite.frag index 95851507..0053bed4 100644 --- a/shader/sprite.frag +++ b/shader/sprite.frag @@ -10,6 +10,7 @@ uniform float bushDepth; uniform lowp float bushOpacity; uniform sampler2D pattern; +uniform int patternBlendType; uniform lowp float patternOpacity; uniform bool renderPattern; @@ -21,6 +22,47 @@ varying vec2 v_patCoord; const vec3 lumaF = vec3(.299, .587, .114); const vec2 repeat = vec2(1, 1); + +// = = = = = = = = = = = +// mixing functions, from https://github.com/jamieowen/glsl-blend +// = = = = = = = = = = = + +// Normal +vec3 blendNormal(vec3 base, vec3 blend) { + return blend; +} + +vec3 blendNormal(vec3 base, vec3 blend, float opacity) { + return (blendNormal(base, blend) * opacity + base * (1.0 - opacity)); +} + +// Add +float blendAdd(float base, float blend) { + return min(base+blend,1.0); +} + +vec3 blendAdd(vec3 base, vec3 blend) { + return min(base+blend,vec3(1.0)); +} + +vec3 blendAdd(vec3 base, vec3 blend, float opacity) { + return (blendAdd(base, blend) * opacity + base * (1.0 - opacity)); +} + +// Substract +float blendSubstract(float base, float blend) { + return max(base+blend-1.0,0.0); +} + +vec3 blendSubstract(vec3 base, vec3 blend) { + return max(base+blend-vec3(1.0),vec3(0.0)); +} + +vec3 blendSubstract(vec3 base, vec3 blend, float opacity) { + return (blendSubstract(base, blend) * opacity + blend * (1.0 - opacity)); +} +// = = = = = = = = = = = + void main() { /* Sample source color */ @@ -29,12 +71,15 @@ void main() /* Apply pattern */ if (renderPattern) { vec4 pattfrag = texture2D(pattern, mod(v_patCoord, repeat)); - frag.rgb = mix(frag.rgb, pattfrag.rgb, pattfrag.a * patternOpacity); - } - - /* Apply color inversion */ - if (invert) { - frag.rgb = vec3(1.0 - frag.r, 1.0 - frag.g, 1.0 - frag.b); + if (patternBlendType == 1) { + frag.rgb = frag.rgb = blendAdd(frag.rgb, pattfrag.rgb, pattfrag.a * patternOpacity); + } + else if (patternBlendType == 2) { + frag.rgb = blendSubstract(frag.rgb, pattfrag.rgb, pattfrag.a * patternOpacity); + } + else { + frag.rgb = blendNormal(frag.rgb, pattfrag.rgb, pattfrag.a * patternOpacity); + } } /* Apply gray */ @@ -49,6 +94,11 @@ void main() /* Apply color */ frag.rgb = mix(frag.rgb, color.rgb, color.a); + + /* Apply color inversion */ + if (invert) { + frag.rgb = vec3(1.0 - frag.r, 1.0 - frag.g, 1.0 - frag.b); + } /* Apply bush alpha by mathematical if */ lowp float underBush = float(v_texCoord.y < bushDepth); diff --git a/shader/sprite.vert b/shader/sprite.vert index b058553d..3fc3abc3 100644 --- a/shader/sprite.vert +++ b/shader/sprite.vert @@ -24,12 +24,12 @@ void main() if (renderPattern) { if (patternTile) { - vec2 scroll = patternScroll * patternZoom; - v_patCoord = (texCoord * patternSizeInv) - (scroll * patternSizeInv); + vec2 scroll = patternScroll * (patternSizeInv / texSizeInv); + v_patCoord = (texCoord * (patternSizeInv / patternZoom)) - (scroll * patternSizeInv); } else { - vec2 scroll = patternScroll * (patternSizeInv / texSizeInv) * patternZoom; - v_patCoord = (texCoord * texSizeInv) - (scroll * texSizeInv); + vec2 scroll = patternScroll * (patternSizeInv / texSizeInv); + v_patCoord = (texCoord * (texSizeInv / patternZoom)) - (scroll * texSizeInv); } } } diff --git a/src/display/gl/shader.cpp b/src/display/gl/shader.cpp index 92e1abae..0a0642c8 100644 --- a/src/display/gl/shader.cpp +++ b/src/display/gl/shader.cpp @@ -469,6 +469,7 @@ SpriteShader::SpriteShader() GET_U(bushDepth); GET_U(bushOpacity); GET_U(pattern); + GET_U(patternBlendType); GET_U(patternTile); GET_U(renderPattern); GET_U(patternSizeInv); @@ -514,6 +515,11 @@ void SpriteShader::setPattern(const TEX::ID pattern, const Vec2 &dimensions) gl.Uniform2f(u_patternSizeInv, 1.f / dimensions.x, 1.f / dimensions.y); } +void SpriteShader::setPatternBlendType(int blendType) +{ + gl.Uniform1i(u_patternBlendType, blendType); +} + void SpriteShader::setPatternTile(bool value) { gl.Uniform1i(u_patternTile, value); diff --git a/src/display/gl/shader.h b/src/display/gl/shader.h index 587e1181..6024d21c 100644 --- a/src/display/gl/shader.h +++ b/src/display/gl/shader.h @@ -192,6 +192,7 @@ public: void setBushDepth(float value); void setBushOpacity(float value); void setPattern(const TEX::ID pattern, const Vec2 &dimensions); + void setPatternBlendType(int blendType); void setPatternTile(bool value); void setShouldRenderPattern(bool value); void setPatternOpacity(float value); @@ -201,7 +202,7 @@ public: private: GLint u_spriteMat, u_tone, u_opacity, u_color, u_bushDepth, u_bushOpacity, u_pattern, u_renderPattern, - u_patternSizeInv, u_patternTile, u_patternOpacity, u_patternScroll, u_patternZoom, u_invert; + u_patternBlendType, u_patternSizeInv, u_patternTile, u_patternOpacity, u_patternScroll, u_patternZoom, u_invert; }; class PlaneShader : public ShaderBase diff --git a/src/display/sprite.cpp b/src/display/sprite.cpp index 504621ae..3e7f1d5c 100644 --- a/src/display/sprite.cpp +++ b/src/display/sprite.cpp @@ -61,6 +61,7 @@ struct SpritePrivate BlendType blendType; Bitmap *pattern; + BlendType patternBlendType; bool patternTile; NormValue patternOpacity; Vec2 patternScroll; @@ -337,6 +338,7 @@ DEF_ATTR_RD_SIMPLE(Sprite, Mirror, bool, p->mirrored) DEF_ATTR_RD_SIMPLE(Sprite, BushDepth, int, p->bushDepth) DEF_ATTR_RD_SIMPLE(Sprite, BlendType, int, p->blendType) DEF_ATTR_RD_SIMPLE(Sprite, Pattern, Bitmap*, p->pattern) +DEF_ATTR_RD_SIMPLE(Sprite, PatternBlendType, int, p->patternBlendType) DEF_ATTR_RD_SIMPLE(Sprite, Width, int, p->srcRect->width) DEF_ATTR_RD_SIMPLE(Sprite, Height, int, p->srcRect->height) DEF_ATTR_RD_SIMPLE(Sprite, WaveAmp, int, p->wave.amp) @@ -512,6 +514,25 @@ void Sprite::setPattern(Bitmap *value) value->ensureNonMega(); } +void Sprite::setPatternBlendType(int type) +{ + guardDisposed(); + + switch (type) + { + default : + case BlendNormal : + p->patternBlendType = BlendNormal; + return; + case BlendAddition : + p->patternBlendType = BlendAddition; + return; + case BlendSubstraction : + p->patternBlendType = BlendSubstraction; + return; + } +} + #define DEF_WAVE_SETTER(Name, name, type) \ void Sprite::setWave##Name(type value) \ { \ @@ -582,6 +603,7 @@ void Sprite::draw() if (p->pattern && p->patternOpacity > 0) { shader.setPattern(p->pattern->getGLTypes().tex, Vec2(p->pattern->width(), p->pattern->height())); + shader.setPatternBlendType(p->patternBlendType); shader.setPatternTile(p->patternTile); shader.setPatternZoom(p->patternZoom); shader.setPatternOpacity(p->patternOpacity.norm); diff --git a/src/display/sprite.h b/src/display/sprite.h index 17cd88eb..c440b61a 100644 --- a/src/display/sprite.h +++ b/src/display/sprite.h @@ -63,6 +63,7 @@ public: DECL_ATTR( Color, Color& ) DECL_ATTR( Tone, Tone& ) DECL_ATTR( Pattern, Bitmap* ) + DECL_ATTR( PatternBlendType, int) DECL_ATTR( PatternTile, bool ) DECL_ATTR( PatternOpacity, int ) DECL_ATTR( PatternScrollX, int )