summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdimension/color.c104
-rw-r--r--libdimension/dimension/color.h9
-rw-r--r--tests/libdimension/tests.c12
3 files changed, 99 insertions, 26 deletions
diff --git a/libdimension/color.c b/libdimension/color.c
index 79def12..0ec9e0b 100644
--- a/libdimension/color.c
+++ b/libdimension/color.c
@@ -28,9 +28,41 @@ const dmnsn_CIE_XYZ dmnsn_whitepoint = { .X = 0.9504060171449392,
/* Standard colors */
const dmnsn_color dmnsn_black = { .X = 0.0, .Y = 0.0, .Z = 0.0 };
-const dmnsn_color dmnsn_white = { .X = 0.9504060171449392,
- .Y = 0.9999085943425312,
- .Z = 1.089062231497274 };
+const dmnsn_color dmnsn_white = {
+ .X = 0.9504060171449392,
+ .Y = 0.9999085943425312,
+ .Z = 1.089062231497274
+};
+const dmnsn_color dmnsn_red = {
+ .X = 0.4123808838268995,
+ .Y = 0.2126198631048975,
+ .Z = 0.0193434956789248
+};
+const dmnsn_color dmnsn_green = {
+ .X = 0.3575728355732478,
+ .Y = 0.7151387878413206,
+ .Z = 0.1192121694056356
+};
+const dmnsn_color dmnsn_blue = {
+ .X = 0.1804522977447919,
+ .Y = 0.0721499433963131,
+ .Z = 0.950506566412713
+};
+const dmnsn_color dmnsn_magenta = {
+ .X = 0.5928331815716914,
+ .Y = 0.2847698065012106,
+ .Z = 0.9698500620916378
+};
+const dmnsn_color dmnsn_yellow = {
+ .X = 0.7699537194001473,
+ .Y = 0.9277586509462181,
+ .Z = 0.1385556650845604
+};
+const dmnsn_color dmnsn_cyan = {
+ .X = 0.5380251333180397,
+ .Y = 0.7872887312376337,
+ .Z = 1.069718735818349
+};
/* Convert a CIE XYZ color to a dmnsn_color (actually a no-op) */
dmnsn_color
@@ -45,11 +77,26 @@ dmnsn_color_from_XYZ(dmnsn_CIE_XYZ XYZ)
dmnsn_color
dmnsn_color_from_xyY(dmnsn_CIE_xyY xyY)
{
- dmnsn_color ret = { .X = xyY.Y*xyY.x/xyY.y,
- .Y = xyY.Y,
- .Z = xyY.Y*(1.0 - xyY.x - xyY.y)/xyY.y,
- .filter = 0.0,
- .trans = 0.0 };
+ dmnsn_color ret = {
+ .X = xyY.Y*xyY.x/xyY.y,
+ .Y = xyY.Y,
+ .Z = xyY.Y*(1.0 - xyY.x - xyY.y)/xyY.y,
+ .filter = 0.0,
+ .trans = 0.0
+ };
+ return ret;
+}
+
+dmnsn_color
+dmnsn_color_from_RGB(dmnsn_CIE_RGB RGB)
+{
+ dmnsn_color ret = {
+ .X = 0.49*RGB.R + 0.31*RGB.G + 0.20*RGB.B,
+ .Y = 0.17697*RGB.R + 0.81240*RGB.G + 0.01063*RGB.B,
+ .Z = 0.00*RGB.R + 0.01*RGB.G + 0.99*RGB.B,
+ .filter = 0.0,
+ .trans = 0.0
+ };
return ret;
}
@@ -168,9 +215,25 @@ dmnsn_XYZ_from_color(dmnsn_color color)
dmnsn_CIE_xyY
dmnsn_xyY_from_color(dmnsn_color color)
{
- dmnsn_CIE_xyY ret = { .x = color.X/(color.X + color.Y + color.Z),
- .y = color.Y/(color.X + color.Y + color.Z),
- .Y = color.Y };
+ dmnsn_CIE_xyY ret = {
+ .x = color.X/(color.X + color.Y + color.Z),
+ .y = color.Y/(color.X + color.Y + color.Z),
+ .Y = color.Y
+ };
+ return ret;
+}
+
+dmnsn_CIE_RGB
+dmnsn_RGB_from_color(dmnsn_color color)
+{
+ dmnsn_CIE_RGB ret = {
+ .R = 2.36461384653836548*color.X + -0.89654057073966797*color.Y
+ + -0.46807327579869740*color.Z,
+ .G = -0.51516620844788796*color.X + 1.42640810385638872*color.Y
+ + 0.08875810459149917*color.Z,
+ .B = 0.00520369907523119*color.X + -0.01440816266521605*color.Y
+ + 1.00920446358998483*color.Z
+ };
return ret;
}
@@ -298,15 +361,20 @@ dmnsn_color_mul(double n, dmnsn_color color)
dmnsn_color
dmnsn_color_illuminate(dmnsn_color light, dmnsn_color color)
{
- /* TODO: make this work in a perceptually uniform colorspace */
- dmnsn_sRGB sRGB1 = dmnsn_sRGB_from_color(light);
- dmnsn_sRGB sRGB2 = dmnsn_sRGB_from_color(color);
+ static dmnsn_CIE_RGB white = { 0.0 };
+ if (!white.R)
+ white = dmnsn_RGB_from_color(dmnsn_white);
+
+ dmnsn_CIE_RGB RGB1 = dmnsn_RGB_from_color(light);
+ dmnsn_CIE_RGB RGB2 = dmnsn_RGB_from_color(color);
- dmnsn_sRGB sRGB = { .R = sRGB1.R*sRGB2.R,
- .G = sRGB1.G*sRGB2.G,
- .B = sRGB1.B*sRGB2.B };
+ dmnsn_CIE_RGB RGB = {
+ .R = RGB1.R*RGB2.R/white.R,
+ .G = RGB1.G*RGB2.G/white.G,
+ .B = RGB1.B*RGB2.B/white.B
+ };
- dmnsn_color ret = dmnsn_color_from_sRGB(sRGB);
+ dmnsn_color ret = dmnsn_color_from_RGB(RGB);
ret.filter = color.filter;
ret.trans = color.trans;
diff --git a/libdimension/dimension/color.h b/libdimension/dimension/color.h
index a72de98..ad50334 100644
--- a/libdimension/dimension/color.h
+++ b/libdimension/dimension/color.h
@@ -46,6 +46,10 @@ typedef struct {
} dmnsn_CIE_xyY;
typedef struct {
+ double R, G, B; /* CIE 1931 RGB, a linear transformation of CIE XYZ */
+} dmnsn_CIE_RGB;
+
+typedef struct {
double L, a, b; /* L is luminence (100 = diffuse white); a and b are color-
opponent dimensions. This color space is used for color
arithmetic. */
@@ -61,7 +65,8 @@ typedef struct {
} dmnsn_sRGB;
/* Standard colors */
-extern const dmnsn_color dmnsn_black, dmnsn_white;
+extern const dmnsn_color dmnsn_black, dmnsn_white, dmnsn_red, dmnsn_green,
+ dmnsn_blue, dmnsn_magenta, dmnsn_yellow, dmnsn_cyan;
/* Standard whitepoint, determined by the conversion of sRGB white to CIE XYZ */
extern const dmnsn_CIE_XYZ dmnsn_whitepoint;
@@ -70,12 +75,14 @@ extern const dmnsn_CIE_XYZ dmnsn_whitepoint;
dmnsn_color dmnsn_color_from_XYZ(dmnsn_CIE_XYZ XYZ);
dmnsn_color dmnsn_color_from_xyY(dmnsn_CIE_xyY xyY);
+dmnsn_color dmnsn_color_from_RGB(dmnsn_CIE_RGB RGB);
dmnsn_color dmnsn_color_from_Lab(dmnsn_CIE_Lab Lab, dmnsn_CIE_XYZ white);
dmnsn_color dmnsn_color_from_Luv(dmnsn_CIE_Luv Luv, dmnsn_CIE_XYZ white);
dmnsn_color dmnsn_color_from_sRGB(dmnsn_sRGB sRGB);
dmnsn_CIE_XYZ dmnsn_XYZ_from_color(dmnsn_color color);
dmnsn_CIE_xyY dmnsn_xyY_from_color(dmnsn_color color);
+dmnsn_CIE_RGB dmnsn_RGB_from_color(dmnsn_color color);
dmnsn_CIE_Lab dmnsn_Lab_from_color(dmnsn_color color, dmnsn_CIE_XYZ white);
dmnsn_CIE_Luv dmnsn_Luv_from_color(dmnsn_color color, dmnsn_CIE_XYZ white);
dmnsn_sRGB dmnsn_sRGB_from_color(dmnsn_color color);
diff --git a/tests/libdimension/tests.c b/tests/libdimension/tests.c
index 62c4454..b2670f8 100644
--- a/tests/libdimension/tests.c
+++ b/tests/libdimension/tests.c
@@ -22,17 +22,15 @@
dmnsn_scene *
dmnsn_new_default_scene()
{
- dmnsn_scene *scene;
-
/* Allocate a new scene */
- scene = dmnsn_new_scene();
+ dmnsn_scene *scene = dmnsn_new_scene();
if (!scene) {
return NULL;
}
/* Default finish */
- scene->default_texture->finish = dmnsn_new_phong_finish(1.0, 0.2, 50.0);
+ scene->default_texture->finish = dmnsn_new_phong_finish(1.0, 0.5, 50.0);
if (!scene->default_texture->finish) {
dmnsn_delete_scene(scene);
return NULL;
@@ -90,7 +88,7 @@ dmnsn_new_default_scene()
return NULL;
}
- sphere->texture->pigment = dmnsn_new_solid_pigment(dmnsn_white);
+ sphere->texture->pigment = dmnsn_new_solid_pigment(dmnsn_yellow);
if (!sphere->texture->pigment) {
dmnsn_delete_scene(scene);
return NULL;
@@ -111,7 +109,7 @@ dmnsn_new_default_scene()
return NULL;
}
- cube->texture->pigment = dmnsn_new_solid_pigment(dmnsn_white);
+ cube->texture->pigment = dmnsn_new_solid_pigment(dmnsn_magenta);
if (!cube->texture->pigment) {
dmnsn_delete_scene(scene);
return NULL;
@@ -123,7 +121,7 @@ dmnsn_new_default_scene()
dmnsn_light *light = dmnsn_new_point_light(
dmnsn_vector_construct(-15.0, 20.0, 10.0),
- dmnsn_white
+ dmnsn_cyan
);
if (!light) {
dmnsn_delete_scene(scene);