[PlutoLib/PlutoShader] The initial implementation of the color API

This commit is contained in:
Tefek 2020-10-22 18:05:34 +02:00 committed by Tefek
parent ffa84ff1f4
commit 3bc8b5335c
13 changed files with 1077 additions and 6 deletions

View File

@ -5,6 +5,8 @@
* Rethink the class loader system. * Rethink the class loader system.
* `[PlutoLib]` Redo the resource system * `[PlutoLib]` Redo the resource system
* `[PlutoLib]` Create a new Color API and port renderer code to it * `[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 ## Features targeted for 20.2.0.0-alpha.4
* The stage subsystem * The stage subsystem
@ -38,6 +40,11 @@
instances instances
* Allow stages to be inherited from, creating a stack-like structure * Allow stages to be inherited from, creating a stack-like structure
* `[PlutoAudio]` Integrate the Audio API with the Stage API * `[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 * 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 * The long term goal is to allow an unlimited amount of Pluto applications at any given time

View File

@ -45,18 +45,18 @@ See `NEXT_RELEASE_DRAFT.md` for details.
### Very high priority ### Very high priority
[ *Implemented in the current release.* ] [ *Implemented in the current release.* ]
* Rewrite the ModLoader * Rewrite the ModLoader
* Finish PlutoCommandParser
* Streamline PlutoLib, remove bad APIs and improve code quality * Streamline PlutoLib, remove bad APIs and improve code quality
* The stage system and automated asset loading
### High priority ### High priority
[ *Implemented in the next release.* ] [ *Implemented in the next release.* ]
* Rewrite PlutoGUI
* Finish PlutoAudio * Finish PlutoAudio
* Depends on the stage system * Depends on the stage system
* The stage system and automated asset loading * Finish PlutoCommandParser
### Normal priority ### Normal priority
[ *Planned for an upcoming release.* ] [ *Planned for an upcoming release.* ]
* Rewrite PlutoGUI
* The collision system for PlutoStatic * The collision system for PlutoStatic
* Improve image loading capabilities, possibly rewrite PlutoLib#TPL * Improve image loading capabilities, possibly rewrite PlutoLib#TPL
@ -66,3 +66,7 @@ See `NEXT_RELEASE_DRAFT.md` for details.
* Alternatively, if this deems too difficult to implement, * Alternatively, if this deems too difficult to implement,
prohibit the creation of more than instance per VM to avoid issues prohibit the creation of more than instance per VM to avoid issues
* A networking API * A networking API
* Expand upon the Color API
* Color mixing and blending
* Color transformation
* High-performance serialization

View File

@ -5,11 +5,17 @@
* `[PlutoLib]` Added the `@ConstantExpression` annotation * `[PlutoLib]` Added the `@ConstantExpression` annotation
* `[PlutoLib]` The `RAID#getIDOf` method now returns `OptionalInt` to avoid NPEs * `[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]` 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: Awaiting implementation:
* `[PlutoLib]` Moved `cz.tefek.pluto.io.pluto.pp` to `cz.tefek.pluto.io.plutopackage` * `[PlutoLib]` Moved `cz.tefek.pluto.io.pluto.pp` to `cz.tefek.pluto.io.plutopackage`
* `[PlutoLib]` Completely reworked the module system * `[PlutoLib]` Completely reworked the module system
* `[PlutoLib]` Created a simple Color API
## 20.2.0.0-alpha.2 ## 20.2.0.0-alpha.2
* `build.gradle` Extracted the version numbers into separate variables * `build.gradle` Extracted the version numbers into separate variables

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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<Float> SATURATION_RANGE = Range.between(0.0f, 1.0f);
/**
* Value/Brightness [0..1]
* */
protected float b;
private final static Range<Float> 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;
}
}

View File

@ -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<Float> 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);
}
}

View File

@ -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();
}

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}