RenderColor¶
Under Construction
This documentation is auto-generated, and is a work in progress. Please see the source code at https://github.com/phetsims/alpenglow/blob/main/js/render-program/RenderColor.ts for the most up-to-date information.
Overview¶
RenderColor displays a single solid color everywhere, and is a basic building-block for many other RenderPrograms.
@author Jonathan Olson <jonathan.olson@colorado.edu>
Class RenderColor¶
Constructor¶
new RenderColor( color : Vector4 )¶
Instance Methods¶
getName() : string¶
withChildren( children : RenderProgram[] ) : RenderColor¶
equalsTyped( other : this ) : boolean¶
(protected)
evaluate( context : RenderEvaluationContext ) : Vector4¶
writeInstructions( instructions : RenderInstruction[] )¶
getExtraDebugString() : string¶
(protected)
serialize() : SerializedRenderColor¶
Static Methods¶
applyProgram( vector : Vector4, color : Vector4 )¶
sRGBToLinear( sRGB : Vector4 ) : Vector4¶
linearToSRGB( linear : Vector4 ) : Vector4¶
linearToOklab( linear : Vector4 ) : Vector4¶
Oklab is a perceptually uniform color space, which is useful for color blending. https://bottosson.github.io/posts/oklab/ returned as (L,a,b,alpha)
oklabToLinear( oklab : Vector4 ) : Vector4¶
multiplyMatrixTimesColor( matrix : Matrix3, color : Vector4 ) : Vector4¶
linearToLinearDisplayP3( color : Vector4 ) : Vector4¶
linearDisplayP3ToLinear( color : Vector4 ) : Vector4¶
linearDisplayP3ToDisplayP3( linear : Vector4 ) : Vector4¶
displayP3ToLinearDisplayP3( displayP3 : Vector4 ) : Vector4¶
oklabToOklch( oklab : Vector4 ) : Vector4¶
A radian-based oklch?
oklchToOklab( oklch : Vector4 ) : Vector4¶
A radian-based oklch
linearToOklch( linear : Vector4 ) : Vector4¶
oklchToLinear( oklch : Vector4 ) : Vector4¶
TODO: consistent "linear" naming? (means linear SRGB here)
linearDisplayP3ToOklch( linear : Vector4 ) : Vector4¶
oklchToLinearDisplayP3( oklch : Vector4 ) : Vector4¶
isColorInRange( color : Vector4 ) : boolean¶
public static convert( color: Vector4, fromSpace: RenderColorSpace, toSpace: RenderColorSpace ): Vector4 { if ( fromSpace === toSpace ) { return color; }
if ( assert ) { // If we add more, add in the conversions here const spaces = [ RenderColorSpace.XYZ, RenderColorSpace.xyY, RenderColorSpace.sRGB, RenderColorSpace.premultipliedSRGB, RenderColorSpace.linearSRGB, RenderColorSpace.premultipliedLinearSRGB, RenderColorSpace.displayP3, RenderColorSpace.premultipliedDisplayP3, RenderColorSpace.linearDisplayP3, RenderColorSpace.premultipliedLinearDisplayP3, RenderColorSpace.oklab, RenderColorSpace.premultipliedOklab ];
assert( spaces.includes( fromSpace ) );
assert( spaces.includes( toSpace ) );
}
if ( fromSpace.name === toSpace.name ) { if ( fromSpace.isLinear === toSpace.isLinear ) { // Just a premultiply change! return fromSpace.isPremultiplied ? RenderColor.unpremultiply( color ) : RenderColor.premultiply( color ); } else { // We're different in linearity! if ( fromSpace.isPremultiplied ) { color = RenderColor.unpremultiply( color ); } if ( fromSpace.name === 'srgb' || fromSpace.name === 'display-p3' ) { // sRGB transfer function color = fromSpace.isLinear ? RenderColor.linearToSRGB( color ) : RenderColor.sRGBToLinear( color ); } if ( toSpace.isPremultiplied ) { color = RenderColor.premultiply( color ); } return color; } } else { // essentially, we'll convert to linear sRGB and back
if ( fromSpace.isPremultiplied ) {
color = RenderColor.unpremultiply( color );
}
if ( fromSpace === RenderColorSpace.xyY ) {
color = color.y === 0 ? new Vector4( 0, 0, 0, color.w ) : new Vector4(
// TODO: separate out into a function
color.x * color.z / color.y,
color.z,
( 1 - color.x - color.y ) * color.z / color.y,
color.w
);
}
if ( fromSpace === RenderColorSpace.xyY || fromSpace === RenderColorSpace.XYZ ) {
color = RenderColor.multiplyMatrixTimesColor( RenderColor.XYZTosRGBMatrix, color );
}
if (
fromSpace === RenderColorSpace.sRGB ||
fromSpace === RenderColorSpace.premultipliedSRGB ||
fromSpace === RenderColorSpace.displayP3 ||
fromSpace === RenderColorSpace.premultipliedDisplayP3
) {
color = RenderColor.sRGBToLinear( color );
}
if ( fromSpace === RenderColorSpace.displayP3 || fromSpace === RenderColorSpace.premultipliedDisplayP3 ) {
color = RenderColor.linearDisplayP3ToLinear( color );
}
if ( fromSpace === RenderColorSpace.oklab || fromSpace === RenderColorSpace.premultipliedOklab ) {
color = RenderColor.oklabToLinear( color );
}
// Now reverse the process, but for the other color space
if ( toSpace === RenderColorSpace.oklab || toSpace === RenderColorSpace.premultipliedOklab ) {
color = RenderColor.linearToOklab( color );
}
if ( toSpace === RenderColorSpace.displayP3 || toSpace === RenderColorSpace.premultipliedDisplayP3 ) {
color = RenderColor.linearToLinearDisplayP3( color );
}
if (
toSpace === RenderColorSpace.sRGB ||
toSpace === RenderColorSpace.premultipliedSRGB ||
toSpace === RenderColorSpace.displayP3 ||
toSpace === RenderColorSpace.premultipliedDisplayP3
) {
color = RenderColor.linearToSRGB( color );
}
if ( toSpace === RenderColorSpace.xyY || toSpace === RenderColorSpace.XYZ ) {
color = RenderColor.multiplyMatrixTimesColor( RenderColor.sRGBToXYZMatrix, color );
}
if ( toSpace === RenderColorSpace.xyY ) {
color = ( color.x + color.y + color.z === 0 ) ? new Vector4(
// TODO: white point change to the other functions, I think we have some of this duplicated.
// TODO: separate out into a function
// using white point for D65
sRGBWhiteChromaticity.x,
sRGBWhiteChromaticity.y,
0,
color.w
) : new Vector4(
color.x / ( color.x + color.y + color.z ),
color.y / ( color.x + color.y + color.z ),
color.y,
color.w
);
}
if ( toSpace.isPremultiplied ) {
color = RenderColor.premultiply( color );
}
return color;
} } ONLY remaps the r,g,b parts, not alpha
gamutMapColor( color : Vector4, toOklab : ( c: Vector4 ) => Vector4, fromOklab : ( c: Vector4 ) => Vector4 ) : Vector4¶
Relative colorimetric mapping. We could add more of a perceptual intent, but this is a good start.
Modeled after https://drafts.csswg.org/css-color-4/#binsearch
gamutMapLinearSRGB( color : Vector4 ) : Vector4¶
gamutMapLinearDisplayP3( color : Vector4 ) : Vector4¶
gamutMapSRGB( color : Vector4 ) : Vector4¶
gamutMapDisplayP3( color : Vector4 ) : Vector4¶
gamutMapPremultipliedSRGB( color : Vector4 ) : Vector4¶
OUTPUTS unpremultiplied sRGB, with a valid alpha value
gamutMapPremultipliedDisplayP3( color : Vector4 ) : Vector4¶
OUTPUTS unpremultiplied Display P3, with a valid alpha value
oklabToLinearDisplayP3( oklab : Vector4 ) : Vector4¶
linearDisplayP3ToOklab( linearP3 : Vector4 ) : Vector4¶
premultiply( color : Vector4 ) : Vector4¶
unpremultiply( color : Vector4 ) : Vector4¶
xyYToXYZ( xyY : Vector3 ) : Vector3¶
xyToXYZ( xy : Vector2 ) : Vector3¶
xyzToLinear( xyz : Vector4 ) : Vector4¶
linearToXYZ( linear : Vector4 ) : Vector4¶
getMatrixRGBToXYZ( redChromaticity : Vector2, greenChromaticity : Vector2, blueChromaticity : Vector2, whiteChromaticity : Vector2 ) : Matrix3¶
canvasSupportsDisplayP3() : boolean¶
ratioBlend( zeroColor : Vector4, oneColor : Vector4, ratio : number ) : Vector4¶
Static Properties¶
sRGBToXYZMatrix¶
XYZTosRGBMatrix¶
displayP3ToXYZMatrix¶
XYZToDisplayP3Matrix¶
sRGBToDisplayP3Matrix¶
displayP3TosRGBMatrix¶
TRANSPARENT : RenderColor¶
(readonly)
Type SerializedRenderColor¶
- type: "RenderColor"
- color:
- r: number
- g: number
- b: number
- a: number
Source Code¶
See the source for RenderColor.ts in the alpenglow repository.