Skip to content

ScalaMath/ColorLib

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ColorLib

A Scala library for color math.

Project goals

ColorLib is an extension of VecMatLib for color math, since colors can be seen as 3D or 4D vectors whose components are the r, g, b, and alpha components of the color.

Color classes are written in Scala to make the best use possible of Scala's operator overloading. All methods with symbolic names have an alias for better interoperability with java.

All operations in ColorLib are designed to not modify the object on which the operation is invoked to respect the principles of purity and immutability of functional programming.

Representation of colors

ColorLib offers 3 different representations of colors:

  • The Col3f class represents a color using three single-precision floating point numbers, representing the color's r, g, and b components in a range between 0.0 and 1.0.
  • The Col4f class represents a color using four single-precision floating point numbers, representing the color's r, g, b, and alpha components in a range between 0.0 and 1.0.
  • The Col1i class represents a color using a single 4-bytes integer.

The Col3f and Col4f also allow values outside the [0.0, 1.0] range. This representation matches the one used in the OpenGL Shading Language.

The Col1i class only allows values in the [0, 255] range. Values outside of this range are clamped. This representation uses significantly less memory than the other two.

val white = Col3f(1.0f, 1.0f, 1.0f)
val cadetBlue = Col3f(0.372549f, 0.619608f, 0.627451f)
val orangeRed = Col3f(1.0f, 0.270588f, 0.0f)
val springGreen = Col3f(0.0f, 1.0f, 0.498039f)
val transparent = Col4f(1.0f, 1.0f, 1.0f, 0.0f)

When writing a function that accepts a color, it is best to use the Color trait. This allows to use any representation of the color.

def function(color: Color): Unit = {
  println(color.r)
  println(color.g)
  println(color.b)
}

val color = Col4f(0.5f, 1.0f, 0.7f)
function(color) // Prints 0.5, 1.0, 0.7

Colors can also be created from their hex value.

val white = Col1i(0xffffffff) // Uses the RGBA format
val red = Col3f(0xff0000) // Uses the RGB format
val purple = Col3f(0xff00ff) // Equivalent to (1.0f, 0.0f, 1.0f)
val transparentGreen = Col4f(0x00ff0080) // Equivalent to (0.0f, 1.0f, 0.0f, 0.5f)

Gradients

ColorLib also contains a Gradient class that allows to create color gradients. A gradient is represented by a set of points, each of which is a pair made of a color and an offset.

val gradient = Gradient(
  0.0f -> Col4f(1.0f, 0.0f, 0.0f), // Red
  0.5f -> Col4f(1.0f, 1.0f, 0.0f), // Yellow
  1.0f -> Col4f(0.0f, 1.0f, 0.0f) // Green
)
Gradient gradient = new Gradient()
    .addPoint(0.0f, new Col4f(1.0f, 0.0f, 0.0f)) // Red
    .addPoint(0.5f, new Col4f(1.0f, 1.0f, 0.0f)) // Yellow
    .addPoint(1.0f, new Col4f(0.0f, 1.0f, 0.0f)); // Green

Colors can be sampled from a gradient given an offset. Considering the gradient from the previous example:

gradient.sample(0.0f) // Returns red
gradient.sample(0.25f) // Returns an interpolation between red and yellow
gradient.sample(0.5f) // Returns yellow
gradient.sample(0.75f) // Returns an interpolation between yellow and green
gradient.sample(1.0f) // Returns green

Gradients, like colors, are also immutable. The methods addPoint and removePoint do not modify the original gradient, they return a new one.

Using with LWJGL

ColorLib can be used together with LWJGL to load colors into shaders.

This example loads a color made of three floats into the active shader program.

public void loadUniform(String name, Color color) {
    int location = GL20.glGetUniformLocation(program, name);
    GL20.glUniform3f(location, color.r(), color.g(), color.b());
}

Notice how the Color trait is used instead of the concrete Col3f or Col4f classes.

Multithreading

Due to ColorLib not using any internal or temporal objects during any computations, neither modifying objects on which operations are called, it can be used safely in a multithreaded application.

Add ColorLib to your project

sbt

libraryDependencies += "io.github.scalamath" % "colorlib" % "1.1"

Maven

<dependency>
    <groupId>io.github.scalamath</groupId>
    <artifactId>colorlib</artifactId>
    <version>1.1</version>
</dependency>

Gradle

implementation 'io.github.scalamath:colorlib:1.1'

Questions and answers

Q: Why does ColorLib not use scala 3?

A: One of the design goals of ColorLib is to be usable both in Scala and Java. Support for Scala 3 in IDEs is still actively being developed, therefore a Scala 3 library may not be suitable to work with.

Q: Why is color math not included in VecMatLib?

A: Color math used to be a part of VecMatLib, although there may be applications where colors not necessary, therefore in that case one can depend on VecMatLib without having to include an unnecessary dependency for colors.

Contributing

ColorLib was developed by a single person as an extension of VecMatLib.

Your contributions are always welcome! Please submit a pull request or open an issue if you want to contribute with bug fixes, code improvements, documentation, and better unit test coverage.

Support

Support the project with a donation: