Skip to content

Commit 33a0702

Browse files
committed
Fix spectrum to cieXYZ conversion.
1 parent a4f31d1 commit 33a0702

File tree

68 files changed

+470
-307
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+470
-307
lines changed

src/appleseed/foundation/image/colorspace.cpp

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,26 @@ const RegularSpectrum31f RGBCMFStilesBurch195910Deg[3] =
924924
RegularSpectrum31f::from_array(RGBCMFStilesBurch195910DegTabZ)
925925
};
926926

927+
// Cie normalization.
928+
929+
float initialize_CIE_normalization(const RegularSpectrum31f& color_matching_function)
930+
{
931+
float normalization = 0;
932+
for (unsigned int i = 0; i < color_matching_function.Samples; i++)
933+
normalization += color_matching_function[i];
934+
normalization = 1.0f / normalization;
935+
return normalization;
936+
}
937+
938+
const float NORMALIZATIONCIE19312Deg = initialize_CIE_normalization(XYZCMFCIE19312Deg[1]);
939+
940+
//
941+
// SIMID color matching functions.
942+
//
943+
944+
945+
const SIMDColorMatching XYZCMFCIE19312DegSIMD = SIMDColorMatching(XYZCMFCIE19312Deg);
946+
927947

928948
//
929949
// Basis spectra for RGB-to-spectrum conversion.
@@ -1462,7 +1482,6 @@ LightingConditions::LightingConditions(
14621482
m_cmf[w][0] = cmf[0][w] * illuminant[w];
14631483
m_cmf[w][1] = cmf[1][w] * illuminant[w];
14641484
m_cmf[w][2] = cmf[2][w] * illuminant[w];
1465-
m_cmf[w][3] = 0.0f;
14661485
}
14671486

14681487
// Integrate the luminance.
@@ -1477,6 +1496,24 @@ LightingConditions::LightingConditions(
14771496
}
14781497

14791498

1499+
//
1500+
// SIMID color matching functions.
1501+
//
1502+
1503+
SIMDColorMatching::SIMDColorMatching(const RegularSpectrum31f cmf[3])
1504+
{
1505+
for (unsigned int i = 0; i < 31; i++)
1506+
{
1507+
m_cmf[i][0] = cmf[0][i];
1508+
m_cmf[i][1] = cmf[1][i];
1509+
m_cmf[i][2] = cmf[2][i];
1510+
}
1511+
m_cmf[31][0] = 0.0f;
1512+
m_cmf[31][1] = 0.0f;
1513+
m_cmf[31][2] = 0.0f;
1514+
}
1515+
1516+
14801517
//
14811518
// Spectrum <-> CIE XYZ transformations implementation.
14821519
//
@@ -1488,7 +1525,7 @@ void spectrum_to_ciexyz_standard(
14881525
const LightingConditions lighting_conditions(IlluminantCIED65, XYZCMFCIE19312Deg);
14891526

14901527
const Color3f c =
1491-
spectrum_to_ciexyz<float, RegularSpectrum31f>(
1528+
spectrum_reflectance_to_ciexyz<float, RegularSpectrum31f>(
14921529
lighting_conditions,
14931530
RegularSpectrum31f::from_array(spectrum));
14941531

src/appleseed/foundation/image/colorspace.h

Lines changed: 78 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ extern const RegularSpectrum31f XYZCMFCIE196410Deg[3]; // CIE 1964 10-d
130130
extern const RegularSpectrum31f RGBCMFStilesBurch19552Deg[3]; // Stiles and Burch (1955) 2-deg
131131
extern const RegularSpectrum31f RGBCMFStilesBurch195910Deg[3]; // Stiles and Burch (1959) 10-deg (recommended)
132132

133+
// Color matching normalization:
134+
extern const float NORMALIZATIONCIE19312Deg;
133135

134136
//
135137
// Basis spectra for RGB-to-spectrum conversion.
@@ -171,6 +173,21 @@ class LightingConditions
171173
};
172174

173175

176+
//
177+
// SIMID color matching functions.
178+
//
179+
180+
class SIMDColorMatching
181+
{
182+
public:
183+
APPLESEED_SIMD4_ALIGN Color4f m_cmf[32];
184+
185+
SIMDColorMatching(const RegularSpectrum31f cmf[3]);
186+
};
187+
188+
extern const SIMDColorMatching XYZCMFCIE19312DegSIMD;
189+
190+
174191
//
175192
// HSV <-> linear RGB transformations.
176193
//
@@ -335,10 +352,14 @@ T luminance(const Color<T, 3>& linear_rgb);
335352

336353
// Convert a spectrum to a color in the CIE XYZ color space.
337354
template <typename T, typename SpectrumType>
338-
Color<T, 3> spectrum_to_ciexyz(
355+
Color<T, 3> spectrum_reflectance_to_ciexyz(
339356
const LightingConditions& lighting,
340357
const SpectrumType& spectrum);
341358

359+
template <typename T, typename SpectrumType>
360+
Color<T, 3> spectrum_illuminance_to_ciexyz(const SpectrumType& spectrum);
361+
362+
342363
// Convert a spectrum to a color in the CIE XYZ color space using the CIE D65 illuminant
343364
// and the CIE 1964 10-deg color matching functions.
344365
APPLESEED_DLLSYMBOL void spectrum_to_ciexyz_standard(
@@ -840,13 +861,13 @@ inline T luminance(const Color<T, 3>& linear_rgb)
840861
//
841862

842863
template <typename T, typename SpectrumType>
843-
Color<T, 3> spectrum_to_ciexyz(
864+
Color<T, 3> spectrum_reflectance_to_ciexyz(
844865
const LightingConditions& lighting,
845866
const SpectrumType& spectrum)
846867
{
847868
static_assert(
848869
SpectrumType::Samples == 31,
849-
"foundation::spectrum_to_ciexyz() expects 31-channel spectra");
870+
"foundation::spectrum_reflectance_to_ciexyz() expects 31-channel spectra");
850871

851872
T x = T(0.0);
852873
T y = T(0.0);
@@ -863,10 +884,36 @@ Color<T, 3> spectrum_to_ciexyz(
863884
return Color<T, 3>(x, y, z);
864885
}
865886

887+
template <typename T, typename SpectrumType>
888+
Color<T, 3> spectrum_illuminance_to_ciexyz(const SpectrumType& spectrum)
889+
{
890+
static_assert(
891+
SpectrumType::Samples == 31,
892+
"foundation::spectrum_illuminance_to_ciexyz() expects 31-channel spectra");
893+
894+
T x = T(0.0);
895+
T y = T(0.0);
896+
T z = T(0.0);
897+
898+
for (size_t w = 0; w < 31; ++w)
899+
{
900+
const T val = spectrum[w];
901+
x += XYZCMFCIE19312Deg[0][w] * val;
902+
y += XYZCMFCIE19312Deg[1][w] * val;
903+
z += XYZCMFCIE19312Deg[2][w] * val;
904+
}
905+
906+
x *= NORMALIZATIONCIE19312Deg;
907+
y *= NORMALIZATIONCIE19312Deg;
908+
z *= NORMALIZATIONCIE19312Deg;
909+
910+
return Color<T, 3>(x, y, z);
911+
}
912+
866913
#ifdef APPLESEED_USE_SSE
867914

868915
template <>
869-
inline Color3f spectrum_to_ciexyz<float, RegularSpectrum31f>(
916+
inline Color3f spectrum_reflectance_to_ciexyz<float, RegularSpectrum31f>(
870917
const LightingConditions& lighting,
871918
const RegularSpectrum31f& spectrum)
872919
{
@@ -893,6 +940,33 @@ inline Color3f spectrum_to_ciexyz<float, RegularSpectrum31f>(
893940
return Color3f(transfer[0], transfer[1], transfer[2]);
894941
}
895942

943+
template <>
944+
inline Color3f spectrum_illuminance_to_ciexyz<float, RegularSpectrum31f>(const RegularSpectrum31f& spectrum)
945+
{
946+
__m128 xyz1 = _mm_setzero_ps();
947+
__m128 xyz2 = _mm_setzero_ps();
948+
__m128 xyz3 = _mm_setzero_ps();
949+
__m128 xyz4 = _mm_setzero_ps();
950+
951+
for (size_t w = 0; w < 8; ++w)
952+
{
953+
xyz1 = _mm_add_ps(xyz1, _mm_mul_ps(_mm_set1_ps(spectrum[4 * w + 0]), _mm_load_ps(&XYZCMFCIE19312DegSIMD.m_cmf[4 * w + 0][0])));
954+
xyz2 = _mm_add_ps(xyz2, _mm_mul_ps(_mm_set1_ps(spectrum[4 * w + 1]), _mm_load_ps(&XYZCMFCIE19312DegSIMD.m_cmf[4 * w + 1][0])));
955+
xyz3 = _mm_add_ps(xyz3, _mm_mul_ps(_mm_set1_ps(spectrum[4 * w + 2]), _mm_load_ps(&XYZCMFCIE19312DegSIMD.m_cmf[4 * w + 2][0])));
956+
xyz4 = _mm_add_ps(xyz4, _mm_mul_ps(_mm_set1_ps(spectrum[4 * w + 3]), _mm_load_ps(&XYZCMFCIE19312DegSIMD.m_cmf[4 * w + 3][0])));
957+
}
958+
959+
xyz1 = _mm_add_ps(xyz1, xyz2);
960+
xyz3 = _mm_add_ps(xyz3, xyz4);
961+
xyz1 = _mm_add_ps(xyz1, xyz3);
962+
963+
xyz1 = _mm_mul_ps(xyz1, _mm_set1_ps(NORMALIZATIONCIE19312Deg));
964+
965+
APPLESEED_SIMD4_ALIGN float transfer[4];
966+
_mm_store_ps(transfer, xyz1);
967+
968+
return Color3f(transfer[0], transfer[1], transfer[2]);
969+
}
896970
#endif // APPLESEED_USE_SSE
897971

898972
template <typename T, typename SpectrumType>
@@ -1092,7 +1166,6 @@ void linear_rgb_illuminance_to_spectrum_unclamped(
10921166
const Color<T, 3>& linear_rgb,
10931167
SpectrumType& spectrum)
10941168
{
1095-
/* This gives an undesirable blue tint...
10961169
impl::linear_rgb_to_spectrum(
10971170
linear_rgb,
10981171
RGBToSpectrumWhiteIlluminance,
@@ -1102,17 +1175,6 @@ void linear_rgb_illuminance_to_spectrum_unclamped(
11021175
RGBToSpectrumRedIlluminance,
11031176
RGBToSpectrumGreenIlluminance,
11041177
RGBToSpectrumBlueIlluminance,
1105-
spectrum); */
1106-
1107-
impl::linear_rgb_to_spectrum(
1108-
linear_rgb,
1109-
RGBToSpectrumWhiteReflectance,
1110-
RGBToSpectrumCyanReflectance,
1111-
RGBToSpectrumMagentaReflectance,
1112-
RGBToSpectrumYellowReflectance,
1113-
RGBToSpectrumRedReflectance,
1114-
RGBToSpectrumGreenReflectance,
1115-
RGBToSpectrumBlueReflectance,
11161178
spectrum);
11171179
}
11181180

src/appleseed/foundation/meta/benchmarks/benchmark_colorspace.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ BENCHMARK_SUITE(Foundation_Image_ColorSpace)
8181

8282
BENCHMARK_CASE_F(SpectrumToCIEXYZ, SpectrumToCIEXYZFixture)
8383
{
84-
m_output = spectrum_to_ciexyz<float>(m_lighting_conditions, m_input);
84+
m_output = spectrum_reflectance_to_ciexyz<float>(m_lighting_conditions, m_input);
8585
}
8686

8787
struct LinearRGBToSpectrumFixture

src/appleseed/foundation/meta/tests/test_colorspace.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ TEST_SUITE(Foundation_Image_ColorSpace)
482482
{
483483
const RegularSpectrum31f spectrum = get_white_spectrum();
484484
const LightingConditions lighting_conditions(IlluminantCIED65, XYZCMFCIE19312Deg);
485-
const Color3f ciexyz = spectrum_to_ciexyz<float>(lighting_conditions, spectrum);
485+
const Color3f ciexyz = spectrum_reflectance_to_ciexyz<float>(lighting_conditions, spectrum);
486486

487487
EXPECT_FEQ_EPS(
488488
Color3f(0.701480f, 0.73824f, 0.804104f),

src/appleseed/renderer/kernel/lighting/lightpathstream.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ void LightPathStream::hit_reflector(const PathVertex& vertex)
107107
HitReflectorData data;
108108
data.m_object_instance = &vertex.m_shading_point->get_object_instance();
109109
data.m_vertex_position = Vector3f(vertex.get_point());
110-
data.m_path_throughput = vertex.m_throughput.to_rgb(g_std_lighting_conditions);
110+
data.m_path_throughput = vertex.m_throughput.illuminance_to_rgb();
111111
m_hit_reflector_data.push_back(data);
112112
}
113113

@@ -126,8 +126,8 @@ void LightPathStream::hit_emitter(
126126
HitEmitterData data;
127127
data.m_object_instance = &vertex.m_shading_point->get_object_instance();
128128
data.m_vertex_position = Vector3f(vertex.get_point());
129-
data.m_path_throughput = vertex.m_throughput.to_rgb(g_std_lighting_conditions);
130-
data.m_emitted_radiance = emitted_radiance.to_rgb(g_std_lighting_conditions);
129+
data.m_path_throughput = vertex.m_throughput.illuminance_to_rgb();
130+
data.m_emitted_radiance = emitted_radiance.illuminance_to_rgb();
131131
m_hit_emitter_data.push_back(data);
132132
}
133133

@@ -147,8 +147,8 @@ void LightPathStream::sampled_emitting_shape(
147147
shape.get_assembly_instance()->get_assembly().object_instances().get_by_index(
148148
shape.get_object_instance_index());
149149
data.m_vertex_position = Vector3f(emission_position);
150-
data.m_material_value = material_value.to_rgb(g_std_lighting_conditions);
151-
data.m_emitted_radiance = emitted_radiance.to_rgb(g_std_lighting_conditions);
150+
data.m_material_value = material_value.reflectance_to_rgb(g_std_lighting_conditions);
151+
data.m_emitted_radiance = emitted_radiance.illuminance_to_rgb();
152152
m_sampled_emitter_data.push_back(data);
153153
}
154154

@@ -166,8 +166,8 @@ void LightPathStream::sampled_non_physical_light(
166166
SampledEmitterData data;
167167
data.m_entity = &light;
168168
data.m_vertex_position = Vector3f(emission_position);
169-
data.m_material_value = material_value.to_rgb(g_std_lighting_conditions);
170-
data.m_emitted_radiance = emitted_radiance.to_rgb(g_std_lighting_conditions);
169+
data.m_material_value = material_value.reflectance_to_rgb(g_std_lighting_conditions);
170+
data.m_emitted_radiance = emitted_radiance.illuminance_to_rgb();
171171
m_sampled_emitter_data.push_back(data);
172172
}
173173

@@ -185,8 +185,8 @@ void LightPathStream::sampled_environment(
185185
SampledEnvData data;
186186
data.m_environment_edf = &environment_edf;
187187
data.m_emission_direction = emission_direction;
188-
data.m_material_value = material_value.to_rgb(g_std_lighting_conditions);
189-
data.m_emitted_radiance = emitted_radiance.to_rgb(g_std_lighting_conditions);
188+
data.m_material_value = material_value.reflectance_to_rgb(g_std_lighting_conditions);
189+
data.m_emitted_radiance = emitted_radiance.illuminance_to_rgb();
190190
m_sampled_env_data.push_back(data);
191191
}
192192

src/appleseed/renderer/kernel/lighting/lighttracing/lighttracingsamplegenerator.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@ namespace
515515
{
516516
assert(min_value(radiance) >= 0.0f);
517517

518-
const Color3f linear_rgb = radiance.to_rgb(g_std_lighting_conditions);
518+
const Color3f linear_rgb = radiance.illuminance_to_rgb();
519519

520520
Sample sample;
521521
sample.m_pixel_coords.x = static_cast<int>(position_ndc.x * m_canvas_width);

src/appleseed/renderer/meta/tests/test_inputarray.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ TEST_SUITE(Renderer_Modeling_Input_InputArray)
4545
TEST_CASE(Find_GivenNameOfExistingInput_ReturnsInputIterator)
4646
{
4747
InputArray inputs;
48-
inputs.declare("x", InputFormatFloat);
48+
inputs.declare("x", InputFormat::InputFormatFloat);
4949

5050
const InputArray::const_iterator i = inputs.find("x");
5151

@@ -55,7 +55,7 @@ TEST_SUITE(Renderer_Modeling_Input_InputArray)
5555
TEST_CASE(Find_GivenNameOfNonExistingInput_ReturnsEndIterator)
5656
{
5757
InputArray inputs;
58-
inputs.declare("x", InputFormatFloat);
58+
inputs.declare("x", InputFormat::InputFormatFloat);
5959

6060
const InputArray::const_iterator i = inputs.find("y");
6161

@@ -65,7 +65,7 @@ TEST_SUITE(Renderer_Modeling_Input_InputArray)
6565
TEST_CASE(Source_GivenNameOfNonExistingInput_ReturnsZero)
6666
{
6767
InputArray inputs;
68-
inputs.declare("x", InputFormatFloat);
68+
inputs.declare("x", InputFormat::InputFormatFloat);
6969

7070
const Source* source = inputs.source("y");
7171

@@ -75,7 +75,7 @@ TEST_SUITE(Renderer_Modeling_Input_InputArray)
7575
TEST_CASE(Source_GivenNameOfUnboundExistingInput_ReturnsZero)
7676
{
7777
InputArray inputs;
78-
inputs.declare("x", InputFormatFloat);
78+
inputs.declare("x", InputFormat::InputFormatFloat);
7979

8080
const Source* source = inputs.source("x");
8181

@@ -85,7 +85,7 @@ TEST_SUITE(Renderer_Modeling_Input_InputArray)
8585
TEST_CASE(Source_GivenNameOfBoundExistingInput_ReturnsBoundSource)
8686
{
8787
InputArray inputs;
88-
inputs.declare("x", InputFormatFloat);
88+
inputs.declare("x", InputFormat::InputFormatFloat);
8989

9090
Source* expected_source = new ScalarSource(1.0);
9191
inputs.find("x").bind(expected_source);

src/appleseed/renderer/modeling/aov/albedoaov.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ namespace
7474
ShadingResult& shading_result) override
7575
{
7676
shading_result.m_aovs[m_index].rgb() =
77-
aov_components.m_albedo.to_rgb(g_std_lighting_conditions);
77+
aov_components.m_albedo.reflectance_to_rgb(g_std_lighting_conditions);
7878

7979
shading_result.m_aovs[m_index].a = shading_result.m_main.a;
8080
}

src/appleseed/renderer/modeling/aov/diffuseaov.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ namespace
7474
ShadingResult& shading_result) override
7575
{
7676
shading_result.m_aovs[m_index].rgb() =
77-
shading_components.m_diffuse.to_rgb(g_std_lighting_conditions) +
78-
shading_components.m_indirect_diffuse.to_rgb(g_std_lighting_conditions);
77+
shading_components.m_diffuse.reflectance_to_rgb(g_std_lighting_conditions) +
78+
shading_components.m_indirect_diffuse.reflectance_to_rgb(g_std_lighting_conditions);
7979

8080
shading_result.m_aovs[m_index].a = shading_result.m_main.a;
8181
}
@@ -106,7 +106,7 @@ namespace
106106
ShadingResult& shading_result) override
107107
{
108108
shading_result.m_aovs[m_index].rgb() =
109-
shading_components.m_diffuse.to_rgb(g_std_lighting_conditions);
109+
shading_components.m_diffuse.reflectance_to_rgb(g_std_lighting_conditions);
110110

111111
shading_result.m_aovs[m_index].a = shading_result.m_main.a;
112112
}
@@ -137,7 +137,7 @@ namespace
137137
ShadingResult& shading_result) override
138138
{
139139
shading_result.m_aovs[m_index].rgb() =
140-
shading_components.m_indirect_diffuse.to_rgb(g_std_lighting_conditions);
140+
shading_components.m_indirect_diffuse.reflectance_to_rgb(g_std_lighting_conditions);
141141

142142
shading_result.m_aovs[m_index].a = shading_result.m_main.a;
143143
}

0 commit comments

Comments
 (0)