From 3bc8b5335c9fedfca82deadd2d1c390d02bd9b4d Mon Sep 17 00:00:00 2001 From: Tefek <493msi@gmail.com> Date: Thu, 22 Oct 2020 18:05:34 +0200 Subject: [PATCH] [PlutoLib/PlutoShader] The initial implementation of the color API --- NEXT_RELEASE_DRAFT.md | 7 + README.md | 12 +- UPDATE_NOTES.md | 10 +- .../java/cz/tefek/pluto/util/color/Color.java | 446 ++++++++++++++++++ .../pluto/util/color/EnumColorFormat.java | 81 ++++ .../java/cz/tefek/pluto/util/color/HSB.java | 145 ++++++ .../java/cz/tefek/pluto/util/color/HSBA.java | 51 ++ .../java/cz/tefek/pluto/util/color/IRGB.java | 31 ++ .../java/cz/tefek/pluto/util/color/IRGBA.java | 17 + .../java/cz/tefek/pluto/util/color/RGB.java | 121 +++++ .../java/cz/tefek/pluto/util/color/RGBA.java | 47 ++ .../engine/shader/uniform/UniformRGB.java | 58 +++ .../engine/shader/uniform/UniformRGBA.java | 57 +++ 13 files changed, 1077 insertions(+), 6 deletions(-) create mode 100644 plutolib/src/main/java/cz/tefek/pluto/util/color/Color.java create mode 100644 plutolib/src/main/java/cz/tefek/pluto/util/color/EnumColorFormat.java create mode 100644 plutolib/src/main/java/cz/tefek/pluto/util/color/HSB.java create mode 100644 plutolib/src/main/java/cz/tefek/pluto/util/color/HSBA.java create mode 100644 plutolib/src/main/java/cz/tefek/pluto/util/color/IRGB.java create mode 100644 plutolib/src/main/java/cz/tefek/pluto/util/color/IRGBA.java create mode 100644 plutolib/src/main/java/cz/tefek/pluto/util/color/RGB.java create mode 100644 plutolib/src/main/java/cz/tefek/pluto/util/color/RGBA.java create mode 100644 plutoshader/src/main/java/cz/tefek/pluto/engine/shader/uniform/UniformRGB.java create mode 100644 plutoshader/src/main/java/cz/tefek/pluto/engine/shader/uniform/UniformRGBA.java diff --git a/NEXT_RELEASE_DRAFT.md b/NEXT_RELEASE_DRAFT.md index bdaa04d..ad99b16 100644 --- a/NEXT_RELEASE_DRAFT.md +++ b/NEXT_RELEASE_DRAFT.md @@ -5,6 +5,8 @@ * Rethink the class loader system. * `[PlutoLib]` Redo the resource system * `[PlutoLib]` Create a new Color API and port renderer code to it + * `[PlutoGUI]` FontRenderer code will not receive these changes + as it is awaiting a rewrite anyway ## Features targeted for 20.2.0.0-alpha.4 * The stage subsystem @@ -38,6 +40,11 @@ instances * Allow stages to be inherited from, creating a stack-like structure * `[PlutoAudio]` Integrate the Audio API with the Stage API +* `[PlutoGUI]` Initial implementation of the new font renderer + * Full rewrite + * High quality font rendering + * Subpixel rendering support [?] + * Possibly a new system for bitmap fonts * Improve upon the support of thread-local Pluto instances * The long term goal is to allow an unlimited amount of Pluto applications at any given time diff --git a/README.md b/README.md index 3c653db..314feb1 100644 --- a/README.md +++ b/README.md @@ -45,18 +45,18 @@ See `NEXT_RELEASE_DRAFT.md` for details. ### Very high priority [ *Implemented in the current release.* ] * Rewrite the ModLoader - * Finish PlutoCommandParser * Streamline PlutoLib, remove bad APIs and improve code quality + * The stage system and automated asset loading ### High priority [ *Implemented in the next release.* ] + * Rewrite PlutoGUI * Finish PlutoAudio * Depends on the stage system - * The stage system and automated asset loading + * Finish PlutoCommandParser ### Normal priority [ *Planned for an upcoming release.* ] - * Rewrite PlutoGUI * The collision system for PlutoStatic * Improve image loading capabilities, possibly rewrite PlutoLib#TPL @@ -65,4 +65,8 @@ See `NEXT_RELEASE_DRAFT.md` for details. * Allow multiple running instances of Pluto * Alternatively, if this deems too difficult to implement, prohibit the creation of more than instance per VM to avoid issues - * A networking API \ No newline at end of file + * A networking API + * Expand upon the Color API + * Color mixing and blending + * Color transformation + * High-performance serialization \ No newline at end of file diff --git a/UPDATE_NOTES.md b/UPDATE_NOTES.md index 4c6f864..24f7905 100644 --- a/UPDATE_NOTES.md +++ b/UPDATE_NOTES.md @@ -5,11 +5,17 @@ * `[PlutoLib]` Added the `@ConstantExpression` annotation * `[PlutoLib]` The `RAID#getIDOf` method now returns `OptionalInt` to avoid NPEs * `[PlutoLib]` The transitive dependency JOML is now provided by `PlutoLib` instead of `PlutoStatic` - +* `[PlutoLib]` Created a simple Color API + * `[PlutoShader]` Added the 8-bit RGBA `Color` class as a counterpart to AWT's `Color` class + * `[PlutoShader]` Added the `RGBA` and `RGB` single precision float color objects + * `[PlutoShader]` Added the respective `IRGBA` and `IRGB` read-only interfaces + * `[PlutoShader]` Added the `HSBA` and `HSB` single precision float color objects + * `[PlutoShader]` Added methods to convert between HSBA, RGBA, HSB and RGB + * `[PlutoShader]` Added the `UniformRGBA` and `UniformRGB` shader uniform types + Awaiting implementation: * `[PlutoLib]` Moved `cz.tefek.pluto.io.pluto.pp` to `cz.tefek.pluto.io.plutopackage` * `[PlutoLib]` Completely reworked the module system -* `[PlutoLib]` Created a simple Color API ## 20.2.0.0-alpha.2 * `build.gradle` Extracted the version numbers into separate variables diff --git a/plutolib/src/main/java/cz/tefek/pluto/util/color/Color.java b/plutolib/src/main/java/cz/tefek/pluto/util/color/Color.java new file mode 100644 index 0000000..1130dac --- /dev/null +++ b/plutolib/src/main/java/cz/tefek/pluto/util/color/Color.java @@ -0,0 +1,446 @@ +package cz.tefek.pluto.util.color; + +import javax.annotation.Nonnull; + +/** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ +public final class Color +{ + // Black and white + public static Color WHITE = new Color(255, 255, 255); + public static Color BLACK = new Color(0, 0, 0); + + // Shades of gray + public static Color VERY_DARK_GRAY = new Color(40, 40, 40); + public static Color DARK_GRAY = new Color(85, 85, 85); + public static Color GRAY = new Color(128, 128, 128); + public static Color SILVER = new Color(192, 192, 192); + public static Color LIGHT_GRAY = new Color(212, 212, 212); + + // Basic colors + public static Color RED = new Color(255, 0, 0); + public static Color GREEN = new Color(0, 255, 0); + public static Color BLUE = new Color(0, 0, 255); + public static Color YELLOW = new Color(255, 255, 0); + + + public static Color TRANSPARENT = new Color(0, 0, 0, 0); + public static Color TRANSPARENT_WHITE = new Color(255, 255, 255, 0); + + public static Color AMBER = new Color(255, 190, 0); + public static Color AMETHYST = new Color(153, 102, 204); + public static Color APRICOT = new Color(235, 147, 115); + public static Color AZURE = new Color(0, 57, 169); + public static Color BROWN = new Color(150, 75, 0); + public static Color COBALT = new Color(0, 71, 171); + public static Color COPPER = new Color(184, 115, 51); + public static Color CORAL_RED = new Color(255, 50, 60); + public static Color CORNFLOWER_BLUE = new Color(112, 112, 255); + public static Color CRIMSON = new Color(220, 26, 64); + public static Color CYAN = new Color(0, 188, 212); + public static Color DARK_BROWN = new Color(66, 33, 0); + public static Color DARK_GREEN = new Color(0, 150, 0); + public static Color LIGHT_AZURE = new Color(0, 128, 255); + public static Color LIME = new Color(191, 255, 0); + public static Color MAGENTA = new Color(255, 0, 255); + public static Color MALACHITE = new Color(11, 218, 81); + public static Color NAVY_BLUE = new Color(0, 0, 128); + public static Color OBSIDIAN = new Color(16, 18, 29); + public static Color ORANGE = new Color(255, 102, 0); + public static Color ORANGE_RED = new Color(255, 55, 0); + public static Color PEAR = new Color(209, 226, 49); + public static Color PINK = new Color(253, 109, 134); + public static Color PUMPKIN_ORANGE = new Color(255, 117, 0); + public static Color SAPPHIRE = new Color(47, 81, 158); + public static Color TEAL = new Color(0, 140, 140); + public static Color TURQUOISE = new Color(10, 255, 141); + + + public static Color PASTEL_PINK = new Color(255, 192, 203); + public static Color PASTEL_LIME = new Color(221, 255, 192); + public static Color PASTEL_YELLOW = new Color(252, 255, 192); + public static Color PASTEL_CYAN = new Color(192, 255, 234); + public static Color PASTEL_BLUE = new Color(192, 199, 255); + public static Color PASTEL_VIOLET = new Color(192, 199, 255); + + public int red; + public int green; + public int blue; + public int alpha = 255; + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public Color(int red, int green, int blue, int alpha) + { + this.red = red; + this.green = green; + this.blue = blue; + this.alpha = alpha; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public Color(int red, int green, int blue) + { + this.red = red; + this.green = green; + this.blue = blue; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public static Color from(@Nonnull IRGBA colorComponents) + { + return new Color(Math.round(colorComponents.red() * 255), + Math.round(colorComponents.green() * 255), + Math.round(colorComponents.blue() * 255), + Math.round(colorComponents.alpha() * 255)); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public static Color from(@Nonnull IRGB colorComponents) + { + return new Color(Math.round(colorComponents.red() * 255), + Math.round(colorComponents.green() * 255), + Math.round(colorComponents.blue() * 255)); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public static Color from(int color, @Nonnull EnumColorFormat colorFormat) + { + switch (colorFormat) + { + case CF_INT_BGR: + return new Color(color & 0xff, (color >> 8) & 0xff, (color >> 16) & 0xff); + case CF_INT_RGB: + return new Color((color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); + case CF_INT_ABGR: + return new Color(color & 0xff, (color >> 8) & 0xff, (color >> 16) & 0xff, (color >> 24) & 0xff); + case CF_INT_ARGB: + return new Color((color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff, (color >> 24) & 0xff); + case CF_INT_BGRA: + return new Color((color >> 8) & 0xff, (color >> 16) & 0xff, (color >> 24) & 0xff, color & 0xff); + case CF_INT_RGBA: + return new Color((color >> 24) & 0xff, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff); + default: + throw new UnsupportedOperationException("Use the from(byte[], int, ColorFormat) for byte color formats!"); + } + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public static Color from(@Nonnull byte[] color, @Nonnull EnumColorFormat colorFormat) + { + return from(color, 0, colorFormat); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public static Color from(@Nonnull byte[] color, int offset, @Nonnull EnumColorFormat colorFormat) + { + switch (colorFormat) + { + case CF_3BYTE_BGR: + return new Color(color[offset + 2] & 0xFF, color[offset + 1] & 0xFF, color[offset] & 0xFF); + case CF_3BYTE_RGB: + return new Color(color[offset] & 0xFF, color[offset + 1] & 0xFF, color[offset + 2] & 0xFF); + case CF_4BYTE_ABGR: + return new Color(color[offset + 3] & 0xFF, color[offset + 2] & 0xFF, color[offset + 1] & 0xFF, color[offset] & 0xFF); + case CF_4BYTE_ARGB: + return new Color(color[offset + 1] & 0xFF, color[offset + 2] & 0xFF, color[offset + 3] & 0xFF, color[offset] & 0xFF); + case CF_4BYTE_BGRA: + return new Color(color[offset + 2] & 0xFF, color[offset + 1] & 0xFF, color[offset] & 0xFF, color[offset + 3] & 0xFF); + case CF_4BYTE_RGBA: + return new Color(color[offset] & 0xFF, color[offset + 1] & 0xFF, color[offset + 2] & 0xFF, color[offset + 3] & 0xFF); + default: + throw new UnsupportedOperationException("Use the from(int, ColorFormat) for int color formats!"); + } + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public int getIntRGBA() + { + return get(EnumColorFormat.CF_INT_RGBA); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public int getIntARGB() + { + return get(EnumColorFormat.CF_INT_ARGB); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public int get(@Nonnull EnumColorFormat colorFormat) + { + switch (colorFormat) + { + case CF_INT_BGR: + return (this.blue << 16) | (this.green << 8) | this.red; + case CF_INT_RGB: + return (this.red << 16) | (this.green << 8) | this.blue; + case CF_INT_ABGR: + return (this.alpha << 24) | (this.blue << 16) | (this.green << 8) | this.red; + case CF_INT_ARGB: + return (this.alpha << 24) | (this.red << 16) | (this.green << 8) | this.blue; + case CF_INT_BGRA: + return (this.blue << 24) | (this.green << 16) | (this.red << 8) | this.alpha; + case CF_INT_RGBA: + return (this.red << 24) | (this.green << 16) | (this.blue << 8) | this.alpha; + default: + throw new UnsupportedOperationException("Use the get(ColorFormat, byte[], int) for byte color formats!"); + } + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public void get(@Nonnull EnumColorFormat colorFormat, @Nonnull byte[] dataOut) + { + get(colorFormat, dataOut, 0); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public void get(@Nonnull EnumColorFormat colorFormat, @Nonnull byte[] dataOut, int offset) + { + switch (colorFormat) + { + case CF_3BYTE_BGR: + dataOut[offset++] = (byte) this.blue; + dataOut[offset++] = (byte) this.green; + dataOut[offset] = (byte) this.red; + break; + case CF_3BYTE_RGB: + dataOut[offset++] = (byte) this.red; + dataOut[offset++] = (byte) this.green; + dataOut[offset] = (byte) this.blue; + break; + case CF_4BYTE_ABGR: + dataOut[offset++] = (byte) this.alpha; + dataOut[offset++] = (byte) this.blue; + dataOut[offset++] = (byte) this.green; + dataOut[offset] = (byte) this.red; + break; + case CF_4BYTE_ARGB: + dataOut[offset++] = (byte) this.alpha; + dataOut[offset++] = (byte) this.red; + dataOut[offset++] = (byte) this.green; + dataOut[offset] = (byte) this.blue; + break; + case CF_4BYTE_BGRA: + dataOut[offset++] = (byte) this.blue; + dataOut[offset++] = (byte) this.green; + dataOut[offset++] = (byte) this.red; + dataOut[offset] = (byte) this.alpha; + break; + case CF_4BYTE_RGBA: + dataOut[offset++] = (byte) this.red; + dataOut[offset++] = (byte) this.green; + dataOut[offset++] = (byte) this.blue; + dataOut[offset] = (byte) this.alpha; + break; + default: + throw new UnsupportedOperationException("Use the get(ColorFormat) for int color formats!"); + } + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public int getRed() + { + return this.red; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public int getGreen() + { + return this.green; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public int getBlue() + { + return this.blue; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public int getAlpha() + { + return this.alpha; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public RGB getFloatComponentsRGB() + { + return new RGB(this.red / 255.0f, this.green / 255.0f, this.blue / 255.0f); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public RGBA getFloatComponentsRGBA() + { + return new RGBA(this.red / 255.0f, this.green / 255.0f, this.blue / 255.0f, this.alpha / 255.0f); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public HSB getFloatComponentsHSB() + { + return this.getFloatComponentsRGB().toHSB(); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public HSBA getFloatComponentsHSBA() + { + return this.getFloatComponentsRGBA().toHSBA(); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public void storeFloatComponentsRGBA(@Nonnull RGBA target) + { + storeFloatComponentsRGB(target); + target.a = this.alpha / 255.0f; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public void storeFloatComponentsRGB(@Nonnull RGB target) + { + target.r = this.red / 255.0f; + target.g = this.green / 255.0f; + target.b = this.blue / 255.0f; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public void storeFloatComponentsHSBA(@Nonnull HSBA target) + { + var hsb = this.getFloatComponentsHSBA(); + + target.h = hsb.h; + target.s = hsb.s; + target.b = hsb.b; + target.a = hsb.a; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public void storeFloatComponentsHSB(@Nonnull HSB target) + { + var hsb = this.getFloatComponentsHSB(); + + target.h = hsb.h; + target.s = hsb.s; + target.b = hsb.b; + } +} diff --git a/plutolib/src/main/java/cz/tefek/pluto/util/color/EnumColorFormat.java b/plutolib/src/main/java/cz/tefek/pluto/util/color/EnumColorFormat.java new file mode 100644 index 0000000..e2b6b58 --- /dev/null +++ b/plutolib/src/main/java/cz/tefek/pluto/util/color/EnumColorFormat.java @@ -0,0 +1,81 @@ +package cz.tefek.pluto.util.color; + +/** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ +public enum EnumColorFormat +{ + /** + * 8-bit RGBA stored in a big-endian 32-bit integer + */ + CF_INT_RGBA(4), + /** + * 8-bit BGRA stored in a big-endian 32-bit integer + */ + CF_INT_BGRA(4), + + /** + * 8-bit ARGB stored in a big-endian 32-bit integer + */ + CF_INT_ARGB(4), + /** + * 8-bit ABGR stored in a big-endian 32-bit integer + */ + CF_INT_ABGR(4), + + /** + * 8-bit RGB stored in a big-endian 32-bit integer, the highest 8-bits are unused + */ + CF_INT_RGB(4), + /** + * 8-bit RGB stored in a big-endian 32-bit integer, the highest 8-bits are unused + */ + CF_INT_BGR(4), + + /** + * 8-bit RGBA, one byte per color component + */ + CF_4BYTE_RGBA(4), + /** + * 8-bit BGRA, one byte per color component + */ + CF_4BYTE_BGRA(4), + + /** + * 8-bit ARGB, one byte per color component + */ + CF_4BYTE_ARGB(4), + /** + * 8-bit ABGR, one byte per color component + */ + CF_4BYTE_ABGR(4), + + /** + * 8-bit RGB, one byte per color component + */ + CF_3BYTE_RGB(3), + /** + * 8-bit BGR, one byte per color component + */ + CF_3BYTE_BGR(3); + + private final int size; + + EnumColorFormat(int size) + { + this.size = size; + } + + /** + * Returns the size in bytes. + * + * @return The size of the color format, in bytes + */ + public int getSize() + { + return this.size; + } +} diff --git a/plutolib/src/main/java/cz/tefek/pluto/util/color/HSB.java b/plutolib/src/main/java/cz/tefek/pluto/util/color/HSB.java new file mode 100644 index 0000000..d86429f --- /dev/null +++ b/plutolib/src/main/java/cz/tefek/pluto/util/color/HSB.java @@ -0,0 +1,145 @@ +package cz.tefek.pluto.util.color; + +import org.apache.commons.lang3.Range; + +/** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ +public class HSB +{ + /** + * Hue [0°..360°] + * */ + protected float h; + + /** + * Saturation [0..1] + * */ + protected float s; + private final static Range SATURATION_RANGE = Range.between(0.0f, 1.0f); + + /** + * Value/Brightness [0..1] + * */ + protected float b; + private final static Range BRIGHTNESS_RANGE = Range.between(0.0f, 1.0f); + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public HSB(float hue, float saturation, float brightness) + { + this.h = (360.0f + hue % 360.0f) % 360.0f; + this.s = SATURATION_RANGE.fit(saturation); + this.b = BRIGHTNESS_RANGE.fit(brightness); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public RGB toRGB() + { + return this.toRGBA(1.0f); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public RGB toRGBA() + { + return this.toRGBA(1.0f); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public RGBA toRGBA(float alpha) + { + float h6 = this.h / 60.0f; + + int hueSide = (int) h6; + + // The color component furthest on the hue wheel + float p = this.b * (1 - this.s); + + float hueFractCCW = h6 - hueSide; + // The second nearest color component on the hue wheel - counter-clockwise + float q = this.b * (1 - hueFractCCW * this.s); + + float hueFractCW = 1 - hueFractCCW; + // The second nearest color component on the hue wheel - clockwise + float t = this.b * (1 - hueFractCW * this.s); + + switch (hueSide % 6) + { + case 1: // Hues 60°-119° -- Green is the brightest color, no blue is present at max saturation + return new RGBA(q, this.b, p, alpha); + + case 2: // Hues 120°-179° -- Green is the brightest color, no red is present at max saturation + return new RGBA(p, this.b, t, alpha); + + case 3: // Hues 180°-239° -- Blue is the brightest color, no red is present at max saturation + return new RGBA(p, q, this.b, alpha); + + case 4: // Hues 240°-299° -- Blue is the brightest color, no green is present at max saturation + return new RGBA(t, p, this.b, alpha); + + case 5: // Hues 300°-359° -- Red is the brightest color, no green is present at max saturation + return new RGBA(this.b, p, q, alpha); + + case 0: // Hues 0°-59° -- Red is the brightest color, no blue is present at max saturation + return new RGBA(this.b, t, p, alpha); + + default: + throw new IllegalStateException("This HSB object's hue is negative - this is not legal."); + } + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public float hue() + { + return this.h; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public float saturation() + { + return this.s; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public float brightness() + { + return this.b; + } +} diff --git a/plutolib/src/main/java/cz/tefek/pluto/util/color/HSBA.java b/plutolib/src/main/java/cz/tefek/pluto/util/color/HSBA.java new file mode 100644 index 0000000..41d2be9 --- /dev/null +++ b/plutolib/src/main/java/cz/tefek/pluto/util/color/HSBA.java @@ -0,0 +1,51 @@ +package cz.tefek.pluto.util.color; + +import org.apache.commons.lang3.Range; + +/** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ +public class HSBA extends HSB +{ + protected float a; + private final static Range ALPHA_RANGE = Range.between(0.0f, 1.0f); + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public HSBA(float hue, float saturation, float lightness, float alpha) + { + super(hue, saturation, lightness); + + this.a = ALPHA_RANGE.fit(alpha); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public float alpha() + { + return this.a; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + @Override + public RGB toRGBA() + { + return this.toRGBA(this.a); + } +} diff --git a/plutolib/src/main/java/cz/tefek/pluto/util/color/IRGB.java b/plutolib/src/main/java/cz/tefek/pluto/util/color/IRGB.java new file mode 100644 index 0000000..bea3b13 --- /dev/null +++ b/plutolib/src/main/java/cz/tefek/pluto/util/color/IRGB.java @@ -0,0 +1,31 @@ +package cz.tefek.pluto.util.color; + +/** + * An interface for single precision RGB color objects. + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ +public interface IRGB +{ + /** + * Returns the red color component. + * + * @return The red component, in range 0..1 + */ + float red(); + + /** + * Returns the green color component. + * + * @return The green component, in range 0..1 + */ + float green(); + + /** + * Returns the blue color component. + * + * @return The blue color component, in range 0..1 + */ + float blue(); +} diff --git a/plutolib/src/main/java/cz/tefek/pluto/util/color/IRGBA.java b/plutolib/src/main/java/cz/tefek/pluto/util/color/IRGBA.java new file mode 100644 index 0000000..df63b42 --- /dev/null +++ b/plutolib/src/main/java/cz/tefek/pluto/util/color/IRGBA.java @@ -0,0 +1,17 @@ +package cz.tefek.pluto.util.color; + +/** + * An interface for single precision RGBA color objects. + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ +public interface IRGBA extends IRGB +{ + /** + * Returns the alpha color component. + * + * @return The alpha component, in range 0..1 + */ + float alpha(); +} diff --git a/plutolib/src/main/java/cz/tefek/pluto/util/color/RGB.java b/plutolib/src/main/java/cz/tefek/pluto/util/color/RGB.java new file mode 100644 index 0000000..ad4052e --- /dev/null +++ b/plutolib/src/main/java/cz/tefek/pluto/util/color/RGB.java @@ -0,0 +1,121 @@ +package cz.tefek.pluto.util.color; + +import org.apache.commons.lang3.math.NumberUtils; + +/** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ +public class RGB implements IRGB +{ + protected float r; + protected float g; + protected float b; + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public RGB(float r, float g, float b) + { + this.r = r; + this.g = g; + this.b = b; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public HSBA toHSB() + { + return this.toHSBA(1.0f); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public HSBA toHSBA() + { + return this.toHSBA(1.0f); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public HSBA toHSBA(float alpha) + { + float brightness = NumberUtils.max(this.r, this.g, this.b); + float min = NumberUtils.min(this.r, this.g, this.b); + + if (brightness == 0) + return new HSBA(0, 0, 0, alpha); + + float chroma = brightness - min; + + if (chroma == 0) + return new HSBA(0, 0, brightness, alpha); + + float saturation = chroma / brightness; + float hue; + + if (brightness == this.r) + if (this.g < this.b) + hue = (this.g - this.b) / chroma + 6; + else + hue = (this.g - this.b) / chroma; + else if (brightness == this.g) + hue = (this.b - this.r) / chroma + 2; + else + hue = (this.r - this.g) / chroma + 4; + + hue *= 60; + + return new HSBA(hue, saturation, brightness, alpha); + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public float red() + { + return this.r; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public float green() + { + return this.g; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public float blue() + { + return this.b; + } +} diff --git a/plutolib/src/main/java/cz/tefek/pluto/util/color/RGBA.java b/plutolib/src/main/java/cz/tefek/pluto/util/color/RGBA.java new file mode 100644 index 0000000..f4e4fca --- /dev/null +++ b/plutolib/src/main/java/cz/tefek/pluto/util/color/RGBA.java @@ -0,0 +1,47 @@ +package cz.tefek.pluto.util.color; + +/** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ +public class RGBA extends RGB implements IRGBA +{ + protected float a; + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public RGBA(float r, float g, float b, float a) + { + super(r, g, b); + this.a = a; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public float alpha() + { + return this.a; + } + + /** + * TODO + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + @Override + public HSBA toHSBA() + { + return this.toHSBA(this.a); + } +} diff --git a/plutoshader/src/main/java/cz/tefek/pluto/engine/shader/uniform/UniformRGB.java b/plutoshader/src/main/java/cz/tefek/pluto/engine/shader/uniform/UniformRGB.java new file mode 100644 index 0000000..32696cf --- /dev/null +++ b/plutoshader/src/main/java/cz/tefek/pluto/engine/shader/uniform/UniformRGB.java @@ -0,0 +1,58 @@ +package cz.tefek.pluto.engine.shader.uniform; + +import org.lwjgl.opengl.GL33; + +import cz.tefek.pluto.util.color.IRGB; +import cz.tefek.pluto.util.color.IRGBA; + +/** + * A uniform allowing loading RGBA color data into shader uniforms. + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ +public class UniformRGB extends UniformBase +{ + /** + * Creates a new instance of the {@link UniformRGB} uniform + * with the specified shader location. + * + * @param location The location within the shader + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public UniformRGB(int location) + { + super(location); + } + + /** + /** + * Loads the {@link IRGB} color components into the shader uniform. + * + * @param value The {@link IRGB} color object + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public void load(IRGB value) + { + GL33.glUniform3f(this.location, value.red(), value.green(), value.blue()); + } + + /** + * Loads the RGB color components into the shader uniform. + * + * @param r The red color component, in range [0..1] + * @param g The green color component, in range [0..1] + * @param b The blue color component, in range [0..1] + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public void load(float r, float g, float b) + { + GL33.glUniform3f(this.location, r, g, b); + } +} diff --git a/plutoshader/src/main/java/cz/tefek/pluto/engine/shader/uniform/UniformRGBA.java b/plutoshader/src/main/java/cz/tefek/pluto/engine/shader/uniform/UniformRGBA.java new file mode 100644 index 0000000..60b8f05 --- /dev/null +++ b/plutoshader/src/main/java/cz/tefek/pluto/engine/shader/uniform/UniformRGBA.java @@ -0,0 +1,57 @@ +package cz.tefek.pluto.engine.shader.uniform; + +import org.lwjgl.opengl.GL33; + +import cz.tefek.pluto.util.color.IRGBA; + +/** + * A uniform allowing loading RGBA color data into shader uniforms. + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ +public class UniformRGBA extends UniformBase +{ + /** + * Creates a new instance of the {@link UniformRGBA} uniform + * with the specified shader location. + * + * @param location The location within the shader + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public UniformRGBA(int location) + { + super(location); + } + + /** + * Loads the {@link IRGBA} color components into the shader uniform. + * + * @param value The {@link IRGBA} color object + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public void load(IRGBA value) + { + GL33.glUniform4f(this.location, value.red(), value.green(), value.blue(), value.alpha()); + } + + /** + * Loads the RGBA color components into the shader uniform. + * + * @param r The red color component, in range [0..1] + * @param g The green color component, in range [0..1] + * @param b The blue color component, in range [0..1] + * @param a The alpha component, in range [0..1] + * + * @since 20.2.0.0-alpha.3 + * @author 493msi + */ + public void load(float r, float g, float b, float a) + { + GL33.glUniform4f(this.location, r, g, b, a); + } +}