Last active
July 11, 2025 09:12
-
-
Save juliendehos/31b6a74eba60d95209a58deaf5440984 to your computer and use it in GitHub Desktop.
on handling colors in three.hs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// in three.js, there are various ways to define a color: | |
// using an int | |
const light1 = new THREE.AmbientLight(0xff0000); | |
// using a predefined color (string) | |
const light2 = new THREE.AmbientLight("green"); | |
// using a rgb triplet | |
const light3 = new THREE.AmbientLight(new THREE.Color(0,0,1)); | |
// using an existing color | |
const light4 = new THREE.AmbientLight(new THREE.Color(0xffff00)); | |
const light5 = new THREE.AmbientLight(new THREE.Color("cyan")); | |
const light6 = new THREE.AmbientLight(new THREE.Color(new THREE.Color(1,0,1))); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- we can do that in three.hs too, using typeclasses (like we do with Triplet for 3D vectors) | |
-- a typeclass for creating a Color using an int, a predefined color, a rgb triplet or an existing color | |
class RgbClass rgb where | |
toRgbVal :: rgb -> JSM JSVal | |
-- ints | |
instance RgbClass Int where | |
toRgbVal = toJSVal | |
-- predefined colors | |
data ColorKeyword | |
= Cyan | |
| Green | |
instance RgbClass ColorKeyword where | |
toRgbVal k = toJSVal $ case k of | |
Cyan -> "cyan" :: JSString | |
Green -> "green" | |
-- rgb triplets | |
-- we could also use (Double, Double, Double) but this requires FlexibleInstances and some type annotations | |
data Rgb = Rgb Double Double Double | |
instance RgbClass Rgb where | |
toRgbVal (Rgb r g b) = toJSVal (r, g, b) | |
-- existing colors | |
instance RgbClass Color where | |
toRgbVal = pure . unColor | |
-- a function for creating a color | |
newColor :: RgbClass rgb => rgb -> THREE.Three Color | |
newColor rgb' = THREE.new Color "Color" (toRgbVal rgb') | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- some three.js classes take a color parameter as an int, a string or an existing color, but not a rgb triplet | |
-- so we can define another typeclass: | |
class ColorClass color where | |
toColorVal :: color -> JSM JSVal | |
-- ints | |
instance ColorClass Int where | |
toColorVal = toRgbVal | |
-- predefined colors | |
instance ColorClass ColorKeyword where | |
toColorVal = toRgbVal | |
-- existing colors | |
instance ColorClass Color where | |
toColorVal = toRgbVal | |
-- no instance for rgb triplets |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- now we can use ColorClass to define a color argument | |
newAmbientLight :: ColorClass color => color -> THREE.Three AmbientLight | |
newAmbientLight color' = THREE.new AmbientLight "AmbientLight" (toColorVal color') | |
-- this works in the same way as in three.js | |
light1 <- newAmbientLight (0x110000 :: Int) | |
light2 <- newAmbientLight Green | |
light3 <- newAmbientLight =<< THREE.Color.newColor (Rgb 0 0 1) | |
light4 <- newAmbientLight =<< THREE.Color.newColor (0x111100 :: Int) | |
light5 <- newAmbientLight =<< THREE.Color.newColor Cyan | |
light6 <- newAmbientLight =<< THREE.Color.newColor =<< THREE.Color.newColor (Rgb 0 0 1) | |
-- not allowed: | |
-- light7 <- newAmbientLight (Rgb 0 0 1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Three.js also supports strings like:
So implementing string colors with something like
ColorKeyword
isn't enough.Anyway, the recommended way to define a color is:
🤷