summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xlibdimension-python/tests/color.py1
-rw-r--r--libdimension-python/wrapper.pxd4
-rw-r--r--libdimension-python/wrapper.pyx23
-rw-r--r--libdimension/color.c80
-rw-r--r--libdimension/dimension/color.h9
-rw-r--r--libdimension/tests/render.c16
6 files changed, 77 insertions, 56 deletions
diff --git a/libdimension-python/tests/color.py b/libdimension-python/tests/color.py
index 47ac975..1299a88 100755
--- a/libdimension-python/tests/color.py
+++ b/libdimension-python/tests/color.py
@@ -50,3 +50,4 @@ assert Cyan == Color(0, 1, 1), Cyan
assert Red + Blue == Magenta, Red + Blue
assert 0.5*White == Color(0.5, 0.5, 0.5), 0.5*White
+assert White/2 == Color(0.5, 0.5, 0.5), White/2
diff --git a/libdimension-python/wrapper.pxd b/libdimension-python/wrapper.pxd
index 920f6f2..94966f3 100644
--- a/libdimension-python/wrapper.pxd
+++ b/libdimension-python/wrapper.pxd
@@ -155,8 +155,10 @@ cdef extern from "../libdimension/dimension.h":
dmnsn_color dmnsn_new_color5(double R, double G, double B,
double trans, double filter)
- dmnsn_color dmnsn_color_from_sRGB(dmnsn_color color)
+ double dmnsn_sRGB_gamma(double Clinear)
dmnsn_color dmnsn_color_to_sRGB(dmnsn_color color)
+ double dmnsn_sRGB_inverse_gamma(double CsRGB)
+ dmnsn_color dmnsn_color_from_sRGB(dmnsn_color color)
double dmnsn_color_intensity(dmnsn_color color)
dmnsn_color dmnsn_color_add(dmnsn_color color1, dmnsn_color color2)
diff --git a/libdimension-python/wrapper.pyx b/libdimension-python/wrapper.pyx
index 5431e75..2ed85e0 100644
--- a/libdimension-python/wrapper.pyx
+++ b/libdimension-python/wrapper.pyx
@@ -465,6 +465,8 @@ cdef class Color:
return _sRGBColor(dmnsn_color_mul(rhs, (<Color>lhs)._sRGB))
else:
return _sRGBColor(dmnsn_color_mul(lhs, (<Color?>rhs)._sRGB))
+ def __truediv__(Color lhs not None, double rhs):
+ return _sRGBColor(dmnsn_color_mul(1/rhs, lhs._sRGB))
def __richcmp__(lhs, rhs, int op):
cdef clhs = Color(lhs)
@@ -831,9 +833,9 @@ cdef class Diffuse(Finish):
Keyword arguments:
diffuse -- the intensity of the diffuse reflection
"""
- cdef dmnsn_color gray = dmnsn_color_mul(diffuse, dmnsn_white)
- diffuse = dmnsn_color_intensity(dmnsn_color_from_sRGB(gray))
- self._finish.diffuse = dmnsn_new_lambertian(diffuse)
+ self._finish.diffuse = dmnsn_new_lambertian(
+ dmnsn_sRGB_inverse_gamma(diffuse)
+ )
cdef class Phong(Finish):
"""Phong specular highlight."""
@@ -841,7 +843,10 @@ cdef class Phong(Finish):
"""
Create a Phong highlight.
"""
- self._finish.specular = dmnsn_new_phong(strength, size)
+ self._finish.specular = dmnsn_new_phong(
+ dmnsn_sRGB_inverse_gamma(strength),
+ size
+ )
cdef class Reflection(Finish):
"""Reflective finish."""
@@ -857,10 +862,8 @@ cdef class Reflection(Finish):
if max is None:
max = min
- # Use sRGB value because Reflection(0.5) should really mean "reflect half
- # the light"
- self._finish.reflection = dmnsn_new_basic_reflection(Color(min)._sRGB,
- Color(max)._sRGB,
+ self._finish.reflection = dmnsn_new_basic_reflection(Color(min)._c,
+ Color(max)._c,
falloff)
############
@@ -1317,9 +1320,7 @@ cdef class PointLight(Light):
location -- the origin of the light rays
color -- the color and intensity of the light
"""
- # Take the sRGB component because "color = 0.5*White" should really mean
- # a half-intensity white light
- self._light = dmnsn_new_point_light(Vector(location)._v, Color(color)._sRGB)
+ self._light = dmnsn_new_point_light(Vector(location)._v, Color(color)._c)
Light.__init__(self)
###########
diff --git a/libdimension/color.c b/libdimension/color.c
index efa4f4a..39f9b3d 100644
--- a/libdimension/color.c
+++ b/libdimension/color.c
@@ -97,69 +97,83 @@ const dmnsn_color dmnsn_cyan = {
.trans = 0.0,
};
-/** Inverse function of sRGB's `C' function, for the reverse conversion. */
-static double
-dmnsn_sRGB_C_inv(double CsRGB)
+/* sRGB's `C' function. */
+static inline double
+dmnsn_sRGB_C(double Clinear)
{
/*
- * If C represents R, G, and B, then the Clinear values are now found as
- * follows:
+ * If C represents R, G, and B, then the sRGB values are now found as follows:
*
- * { Csrgb/12.92, Csrgb <= 0.04045
- * Clinear = { 1/2.4
- * { ((Csrgb + 0.055)/1.055) , Csrgb > 0.04045
+ * { 12.92*Clinear, Clinear <= 0.0031308
+ * Csrgb = { 1/2.4
+ * { (1.055)*Clinear - 0.055, Clinear > 0.0031308
*/
- if (CsRGB == 1.0) {
+ if (Clinear == 1.0) {
return 1.0; /* Map 1.0 to 1.0 instead of 0.9999999999999999 */
- } else if (CsRGB <= 0.040449936) {
- return CsRGB/12.92;
+ } else if (Clinear > 0.0031308) {
+ return 1.055*pow(Clinear, 1.0/2.4) - 0.055;
} else {
- return pow((CsRGB + 0.055)/1.055, 2.4);
+ return 12.92*Clinear;
}
}
-/* Convert from sRGB space */
+/* Export dmnsn_sRGB_C */
+double
+dmnsn_sRGB_gamma(double Clinear)
+{
+ return dmnsn_sRGB_C(Clinear);
+}
+
+/* Convert to sRGB space */
dmnsn_color
-dmnsn_color_from_sRGB(dmnsn_color color)
+dmnsn_color_to_sRGB(dmnsn_color color)
{
dmnsn_color ret = {
- .R = dmnsn_sRGB_C_inv(color.R),
- .G = dmnsn_sRGB_C_inv(color.G),
- .B = dmnsn_sRGB_C_inv(color.B),
+ .R = dmnsn_sRGB_C(color.R),
+ .G = dmnsn_sRGB_C(color.G),
+ .B = dmnsn_sRGB_C(color.B),
.trans = color.trans,
.filter = color.filter,
};
return ret;
}
-/** sRGB's `C' function. */
-static double
-dmnsn_sRGB_C(double Clinear)
+/* Inverse function of sRGB's `C' function, for the reverse conversion. */
+double
+dmnsn_sRGB_C_inv(double CsRGB)
{
/*
- * If C represents R, G, and B, then the sRGB values are now found as follows:
+ * If C represents R, G, and B, then the Clinear values are now found as
+ * follows:
*
- * { 12.92*Clinear, Clinear <= 0.0031308
- * Csrgb = { 1/2.4
- * { (1.055)*Clinear - 0.055, Clinear > 0.0031308
+ * { Csrgb/12.92, Csrgb <= 0.04045
+ * Clinear = { 1/2.4
+ * { ((Csrgb + 0.055)/1.055) , Csrgb > 0.04045
*/
- if (Clinear == 1.0) {
+ if (CsRGB == 1.0) {
return 1.0; /* Map 1.0 to 1.0 instead of 0.9999999999999999 */
- } else if (Clinear <= 0.0031308) {
- return 12.92*Clinear;
+ } else if (CsRGB <= 0.040449936) {
+ return CsRGB/12.92;
} else {
- return 1.055*pow(Clinear, 1.0/2.4) - 0.055;
+ return pow((CsRGB + 0.055)/1.055, 2.4);
}
}
-/* Convert to sRGB space */
+/* Export dmnsn_sRGB_C_inv */
+double
+dmnsn_sRGB_inverse_gamma(double CsRGB)
+{
+ return dmnsn_sRGB_C_inv(CsRGB);
+}
+
+/* Convert from sRGB space */
dmnsn_color
-dmnsn_color_to_sRGB(dmnsn_color color)
+dmnsn_color_from_sRGB(dmnsn_color color)
{
dmnsn_color ret = {
- .R = dmnsn_sRGB_C(color.R),
- .G = dmnsn_sRGB_C(color.G),
- .B = dmnsn_sRGB_C(color.B),
+ .R = dmnsn_sRGB_C_inv(color.R),
+ .G = dmnsn_sRGB_C_inv(color.G),
+ .B = dmnsn_sRGB_C_inv(color.B),
.trans = color.trans,
.filter = color.filter,
};
diff --git a/libdimension/dimension/color.h b/libdimension/dimension/color.h
index 8470957..295400b 100644
--- a/libdimension/dimension/color.h
+++ b/libdimension/dimension/color.h
@@ -85,10 +85,15 @@ dmnsn_color_saturate(dmnsn_color color)
/* Perceptual color manipulation */
-/** Convert from sRGB space. */
-dmnsn_color dmnsn_color_from_sRGB(dmnsn_color color);
+/** Apply sRGB gamma */
+double dmnsn_sRGB_gamma(double Clinear);
/** Convert to sRGB space. */
dmnsn_color dmnsn_color_to_sRGB(dmnsn_color color);
+/** Remove sRGB gamma */
+double dmnsn_sRGB_inverse_gamma(double CsRGB);
+/** Convert from sRGB space. */
+dmnsn_color dmnsn_color_from_sRGB(dmnsn_color color);
+
/** Greyscale color intensity. */
double dmnsn_color_intensity(dmnsn_color color);
/** Add two colors together. */
diff --git a/libdimension/tests/render.c b/libdimension/tests/render.c
index ae4a644..abd88d6 100644
--- a/libdimension/tests/render.c
+++ b/libdimension/tests/render.c
@@ -31,11 +31,7 @@ dmnsn_test_scene_set_defaults(dmnsn_scene *scene)
default_finish->ambient = dmnsn_new_basic_ambient(
dmnsn_color_from_sRGB(dmnsn_color_mul(0.1, dmnsn_white))
);
- default_finish->diffuse = dmnsn_new_lambertian(
- dmnsn_color_intensity(
- dmnsn_color_from_sRGB(dmnsn_color_mul(0.7, dmnsn_white))
- )
- );
+ default_finish->diffuse = dmnsn_new_lambertian(dmnsn_sRGB_inverse_gamma(0.7));
}
static void
@@ -130,9 +126,10 @@ dmnsn_test_scene_add_hollow_cube(dmnsn_scene *scene)
cube->texture = dmnsn_new_texture();
cube->texture->pigment = dmnsn_new_solid_pigment(cube_color);
- dmnsn_color reflect = dmnsn_color_mul(0.5, dmnsn_white);
- cube->texture->finish.reflection
- = dmnsn_new_basic_reflection(dmnsn_black, reflect, 1.0);
+ dmnsn_color reflect =
+ dmnsn_color_from_sRGB(dmnsn_color_mul(0.5, dmnsn_white));
+ cube->texture->finish.reflection =
+ dmnsn_new_basic_reflection(dmnsn_black, reflect, 1.0);
cube->interior = dmnsn_new_interior();
cube->interior->ior = 1.1;
@@ -140,7 +137,8 @@ dmnsn_test_scene_add_hollow_cube(dmnsn_scene *scene)
dmnsn_object *sphere = dmnsn_new_sphere();
sphere->texture = dmnsn_new_texture();
sphere->texture->pigment = dmnsn_new_solid_pigment(dmnsn_green);
- sphere->texture->finish.specular = dmnsn_new_phong(0.2, 40.0);
+ sphere->texture->finish.specular =
+ dmnsn_new_phong(dmnsn_sRGB_inverse_gamma(0.2), 40.0);
sphere->trans = dmnsn_scale_matrix(dmnsn_new_vector(1.25, 1.25, 1.25));
dmnsn_object *hollow_cube = dmnsn_new_csg_difference(cube, sphere);