Skip to content

Commit

Permalink
Allow color properties for shader effects.
Browse files Browse the repository at this point in the history
  • Loading branch information
MaurycyLiebner committed Jan 27, 2021
1 parent 8e2d419 commit 67f81b1
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 2 deletions.
82 changes: 82 additions & 0 deletions examples/shaderEffects/eColorize2.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
// enve - 2D animations software
// Copyright (C) 2016-2020 Maurycy Liebner

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

#version 330 core
layout(location = 0) out vec4 fragColor;

in vec2 texCoord;

uniform sampler2D texture;

uniform vec4 colorizeColor;

vec3 HUEtoRGB(in float H) {
float R = abs(H * 6 - 3) - 1;
float G = 2 - abs(H * 6 - 2);
float B = 2 - abs(H * 6 - 4);
return clamp(vec3(R,G,B), 0., 1.);
}

float Epsilon = 1e-10;

vec3 RGBtoHCV(in vec3 RGB) {
// Based on work by Sam Hocevar and Emil Persson
vec4 P = (RGB.g < RGB.b) ? vec4(RGB.bg, -1.0, 2.0/3.0) : vec4(RGB.gb, 0.0, -1.0/3.0);
vec4 Q = (RGB.r < P.x) ? vec4(P.xyw, RGB.r) : vec4(RGB.r, P.yzx);
float C = Q.x - min(Q.w, Q.y);
float H = abs((Q.w - Q.y) / (6 * C + Epsilon) + Q.z);
return vec3(H, C, Q.x);
}

vec3 HSLtoRGB(in vec3 HSL) {
vec3 RGB = HUEtoRGB(HSL.x);
float C = (1 - abs(2 * HSL.z - 1)) * HSL.y;
return (RGB - 0.5) * C + HSL.z;
}

vec3 RGBtoHSL(in vec3 RGB) {
vec3 HCV = RGBtoHCV(RGB);
float L = HCV.z - HCV.y * 0.5;
float S = HCV.y / (1 - abs(L * 2 - 1) + Epsilon);
return vec3(HCV.x, S, L);
}

void main(void) {
vec4 texColor = texture2D(texture, texCoord);
if(texColor.a < 0.00001f) {
fragColor = texColor;
} else {
vec3 hslColorize = RGBtoHSL(colorizeColor.rgb);

float hue = hslColorize.x;
float saturation = hslColorize.y;
float lightness = hslColorize.z;
float alpha = colorizeColor.a;

vec4 tmpColor = texColor;
tmpColor.rgb /= tmpColor.a;
tmpColor.xyz = RGBtoHSL(tmpColor.rgb);
tmpColor.x = hue;
tmpColor.y = saturation;
tmpColor.z = clamp(tmpColor.z + lightness, 0., 1.);
tmpColor.rgb = HSLtoRGB(tmpColor.xyz) * tmpColor.a;
if(alpha > 0.99999f) {
fragColor = tmpColor;
} else {
fragColor = tmpColor*alpha + texColor*(1 - alpha);
}
}
}
21 changes: 21 additions & 0 deletions examples/shaderEffects/eColorize2.gre
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!-- enve - 2D animations software -->
<!-- Copyright (C) 2016-2020 Maurycy Liebner -->

<!-- This program is free software: you can redistribute it and/or modify -->
<!-- it under the terms of the GNU General Public License as published by -->
<!-- the Free Software Foundation, either version 3 of the License, or -->
<!-- (at your option) any later version. -->

<!-- This program is distributed in the hope that it will be useful, -->
<!-- but WITHOUT ANY WARRANTY; without even the implied warranty of -->
<!-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -->
<!-- GNU General Public License for more details. -->

<!-- You should have received a copy of the GNU General Public License -->
<!-- along with this program. If not, see <http://www.gnu.org/licenses/>. -->

<ShaderEffect name="Colorize 2" menuPath="Examples">
<Properties>
<Property name="colorizeColor" type="color" ini="[1, 0, 0, 1]" glValue="true"/>
</Properties>
</ShaderEffect>
55 changes: 53 additions & 2 deletions src/core/ShaderEffects/shadereffectcreator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ bool ShaderEffectCreator::compatible(const QList<ShaderPropertyType> &props) con
const bool iCompatible = enve_cast<QPointFAnimatorCreator*>(prop);
if(!iCompatible) return false;
} break;
case ShaderPropertyType::colorProperty: {
const bool iCompatible = enve_cast<ColorAnimatorCreator*>(prop);
if(!iCompatible) return false;
} break;
default: return false;
};
}
Expand Down Expand Up @@ -77,6 +81,8 @@ ShaderPropertyType creatorPropertyType(ShaderPropertyCreator* const prop) {
return ShaderPropertyType::intProperty;
} else if(enve_cast<QPointFAnimatorCreator*>(prop)) {
return ShaderPropertyType::vec2Property;
} else if(enve_cast<ColorAnimatorCreator*>(prop)) {
return ShaderPropertyType::colorProperty;
} else RuntimeThrow("Unsupported type");
}

Expand Down Expand Up @@ -207,8 +213,8 @@ QPointF attrToQPointF(const QDomElement &elem,
const bool allowSingleValue) {
const QString valS = elem.attribute(attr, def);
const QRegExp rx("\\[" REGEX_TWO_FLOATS "\\]");
if(rx.exactMatch(attr)) {
rx.indexIn(attr);
if(rx.exactMatch(valS)) {
rx.indexIn(valS);
const QStringList xy = rx.capturedTexts();
return {xy.at(1).toDouble(), xy.at(2).toDouble()};
} else if(allowSingleValue) {
Expand All @@ -221,6 +227,34 @@ QPointF attrToQPointF(const QDomElement &elem,
elemName + "'.\nExpected \"[x, y]\".");
}

QColor attrToQColor(const QDomElement &elem,
const QString& elemName,
const QString& attr,
const QString& def) {
const QString valS = elem.attribute(attr, def);
const QRegExp rxRGBA("\\[" REGEX_FOUR_FLOATS "\\]");
if(rxRGBA.exactMatch(valS)) {
rxRGBA.indexIn(valS);
const QStringList rgba = rxRGBA.capturedTexts();
return QColor::fromRgbF(rgba.at(1).toDouble(),
rgba.at(2).toDouble(),
rgba.at(3).toDouble(),
rgba.at(4).toDouble());
} else {
const QRegExp rxRGB("\\[" REGEX_THREE_FLOATS "\\]");
if(rxRGB.exactMatch(valS)) {
rxRGB.indexIn(valS);
const QStringList rgb = rxRGB.capturedTexts();
return QColor::fromRgbF(rgb.at(1).toDouble(),
rgb.at(2).toDouble(),
rgb.at(3).toDouble());
} else {
RuntimeThrow("Invalid '" + attr + "' value \"" + valS + "\" for '" +
elemName + "'.\nExpected \"[r, g, b, a]\".");
}
}
}

void parseFloatPropertyCreators(const QString& name,
const QString& nameUI,
const QDomElement &elem,
Expand Down Expand Up @@ -286,6 +320,21 @@ void parseVec2PropertyCreators(const QString& name,
resolutionScaled, influenceScaled);
}

void parseColorPropertyCreators(const QString& name,
const QString& nameUI,
const QDomElement &elem,
stdsptr<ShaderPropertyCreator>& propC,
stdsptr<UniformSpecifierCreator>& uniC) {
const QColor iniVal = attrToQColor(elem, name, "ini", "[0, 0, 0]");
const bool glValue = attrToBool(elem, name, "glValue", "false");

propC = enve::make_shared<ColorAnimatorCreator>(
iniVal, glValue, name, nameUI);
uniC = enve::make_shared<UniformSpecifierCreator>(
ShaderPropertyType::colorProperty, glValue,
false, false);
}

void parsePropertyCreators(const QString& type,
const QString& name,
const QString& nameUI,
Expand All @@ -298,6 +347,8 @@ void parsePropertyCreators(const QString& type,
parseIntPropertyCreators(name, nameUI, elem, propC, uniC);
} else if(type == "vec2") {
parseVec2PropertyCreators(name, nameUI, elem, propC, uniC);
} else if(type == "color") {
parseColorPropertyCreators(name, nameUI, elem, propC, uniC);
} else {
RuntimeThrow("Invalid Property type '" + type + "' for " + name + ".");
}
Expand Down
10 changes: 10 additions & 0 deletions src/core/ShaderEffects/shadereffectjs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "shadereffectjs.h"

#include <QPointF>
#include <QColor>

#include "exceptions.h"

Expand Down Expand Up @@ -99,6 +100,15 @@ QJSValue ShaderEffectJS::toValue(const QPointF& val) {
return arr;
}

QJSValue ShaderEffectJS::toValue(const QColor& val) {
QJSValue arr = mEngine.newArray(4);
arr.setProperty(0, val.redF());
arr.setProperty(1, val.greenF());
arr.setProperty(2, val.blueF());
arr.setProperty(3, val.alphaF());
return arr;
}

#include <QRegularExpression>
QStringList extractExternFromScript(QString& calc) {
QStringList result;
Expand Down
1 change: 1 addition & 0 deletions src/core/ShaderEffects/shadereffectjs.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class CORE_EXPORT ShaderEffectJS {
void setSceneRect(const SkIRect& rect);

QJSValue toValue(const QPointF& val);
QJSValue toValue(const QColor& val);
private:
QJSEngine mEngine;
QJSValue m_eSetSceneRect;
Expand Down
31 changes: 31 additions & 0 deletions src/core/ShaderEffects/uniformspecifiercreator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,34 @@ void qPointFAnimatorCreate(
};
}

QString colorValScript(const QString& name, const QColor& value) {
return name + " = [" + QString::number(value.redF()) + "," +
QString::number(value.greenF()) + "," +
QString::number(value.blueF()) + "," +
QString::number(value.alphaF()) + "]";
}

void colorAnimatorCreate(
ShaderEffectJS &engine,
const bool glValue,
const GLint loc,
Property * const property,
const qreal relFrame,
QJSValueList& setterArgs,
UniformSpecifiers& uniSpec) {
const auto anim = static_cast<ColorAnimator*>(property);
const QColor val = anim->getColor(relFrame);
const QString valScript = colorValScript(anim->prp_getName(), val);
setterArgs << engine.toValue(val);

if(!glValue) return;
Q_ASSERT(loc >= 0);
uniSpec << [loc, val, valScript](QGL33 * const gl) {
gl->glUniform4f(loc, val.redF(), val.greenF(), val.blueF(),
val.alphaF());
};
}

void UniformSpecifierCreator::create(ShaderEffectJS &engine,
const GLint loc,
Property * const property,
Expand All @@ -112,6 +140,9 @@ void UniformSpecifierCreator::create(ShaderEffectJS &engine,
mResolutionScaled ? resolution : 1,
mInfluenceScaled ? influence : 1,
setterArgs, uniSpec);
case ShaderPropertyType::colorProperty:
return colorAnimatorCreate(engine, fGLValue, loc, property, relFrame,
setterArgs, uniSpec);
default: RuntimeThrow("Unsupported type");
}
}
1 change: 1 addition & 0 deletions src/core/ShaderEffects/uniformspecifiercreator.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "PropertyCreators/qrealanimatorcreator.h"
#include "PropertyCreators/intanimatorcreator.h"
#include "PropertyCreators/qpointfanimatorcreator.h"
#include "PropertyCreators/coloranimatorcreator.h"
#include "glhelpers.h"

class ShaderEffectJS;
Expand Down

0 comments on commit 67f81b1

Please sign in to comment.