POV-Ray : Newsgroups : povray.binaries.images : Yet still another color question: spectral cyan Server Time
1 Nov 2024 04:13:38 EDT (-0400)
  Yet still another color question: spectral cyan (Message 1 to 2 of 2)  
From: Cousin Ricky
Subject: Yet still another color question: spectral cyan
Date: 10 Feb 2014 20:32:30
Message: <52f97dae@news.povray.org>
When the spectrum is rendered into the sRGB color space, the greens are 
dull, and the yellows and cyans are dark.  The darkness of the yellows 
surprised me, but after examining real life spectra, I'm satisfied that 
they really are that dark.  OTOH, the quality of the greens and cyans 
was expected, as they are far outside the sRGB gamut.

One way to get a realistic impression of a spectrum in a restricted 
color space is to desaturate the spectrum as a whole until the 
representative colors of all wavelengths are in gamut.  My attempt at 
this, desat_submission.png, compares well with a Wikimedia illustration:

   http://commons.wikimedia.org/wiki/File:Rendered_Spectrum.png

Image spectral_desat-pbi.png is a similar effort using Ive's SpectralRender.

The greens turned out brilliantly; however, the cyans are still 
muddy-looking compared to the other colors.  This does not jibe with my 
experiences.  Occasionally, sunlight refracts off the edge of a glass 
pane, and the cyan is incredibly rich.  JPEG photographs of rainbows 
show a rich cyan, even when the backdrop is not blue sky.

I considered two things: perhaps pure spectral cyan isn't very bright, 
but when smeared with neighboring colors (due to the size of the 
refracting object) it brightens up; and perhaps the cyans would look 
brighter if the spectrum is rendered "in situ."  The images 
rich_teal_montage-d65.png and rich_teal_montage-d50.png show terrestrial 
sunlight dispersed onto a white surface under various ambient lights, 
with D65 and D50 white balances respectively.  (Artificial lights are 
modeled because one serendipitous sunbeam that impressed me was 
dispersed inside a retail establishment.)  Progressively larger prisms 
are used from bottom to top.  The intensities of the sunlight and the 
ambient lights were adjusted such that no pixel was out of gamut or 
exceeded the 8-bit dynamic range.

The cyan does brighten up when the wavelengths are smeared, but then so 
does the yellow, way more than in a real spectrum or rainbow, and at the 
expense of the orange and red area.  Smearing also turned out not to be 
the answer.  I noticed a spectrum diffracted in an old CD one night, and 
I realized I could use it to examine various light sources.  (The 
difference between a CFL and the last incandescent bulb in my house was 
striking.)  When I used it to look at sunlight, not only was the cyan 
bright and rich, but I could make out some of the Fraunhofer lines, 
which means that there was no smearing going on.

The source for desat_submission.png follows.  It requires Lightsys IV.

=============================[BEGIN CODE]=============================
#version 3.7;

global_settings { assumed_gamma 1 }

#include "CIE.inc"

camera
{ orthographic
   location <555, 0.5, -1>
   right 350 * x
}

#declare SHORTEST = 378;
#declare LONGEST = 826;
#declare STEP = 2;

#declare Max = 0;
#declare Min = 0;
#declare c_Values = array [(LONGEST - SHORTEST) / STEP + 1]
#local I = 0;
#for (Wl, SHORTEST, LONGEST, STEP)
   #declare c_Values[I] = Wavelength2RGB (Wl);
   #declare Max = max (Max, c_Values[I].x, c_Values[I].y, c_Values[I].z);
   #declare Min = min (Min, c_Values[I].x, c_Values[I].y, c_Values[I].z);
   #local I = I + 1;
#end

#declare cm_Spectrum = color_map
{ #local I = 0;
   #for (Wl, SHORTEST, LONGEST, STEP)
     [Wl/1000 rgb (c_Values[I] - Min) / (Max - Min)]
     #local I = I + 1;
   #end
}

box
{ 0, 1
   pigment { gradient x color_map { cm_Spectrum } }
   finish { ambient 0 diffuse 0 emission 1 }
   scale <1000, 1, 1>
}
==============================[END CODE]==============================

The source for the rich_teal_montage-*.png images (rich_teal.pov) 
follows.  It requires Lightsys IV and SpectralRender.  The file 
SpectralComposer.inc is just a version of SpectralComposer.pov which I 
modified by wrapping the user setting #declares with #ifndefs.

The spectra for the ambient lights were prepared with 
integratelight.inc, which integrates spectral curves rather than 
sampling points on the curves.  I haven't yet released the code, but the 
scene file will render without it.  Except for the Mitsubishi runs, the 
results look virtually identical either way.

=============================[BEGIN CODE]=============================
#version 3.7;

#ifndef (Preview) #declare Preview = off; #end
#ifndef (Ph) #declare Ph = 0.001; #end
#ifndef (Ambient) #declare Ambient = 1; #end

#if (clock_on | Preview)

   #include "screen.inc"
   #include "spectral.inc"
   #declare UseIL = file_exists ("integratelight.inc");
   #if (UseIL) #include "integratelight.inc" #end

   #declare s_Ambients = array[8][3]
   { { "Daylight", "D50", "" },
     { "Daylight", "D65", "" },
     { "Daylight", "D75", "" },
     { "Daylight", "D93", "" },
     { "GTE 341", "warm white", "" },
     { "GTE 341", "cool white", "" },
     { "Mitsubishi", "standard", "fluorescent" },
     { "Osram Fluor", "36 watt", "" },
   }
   #switch (Ambient)
     #case (0) #declare Ambience = E_D50; #break
     #case (1) #declare Ambience = E_D65; #break
     #case (2) #declare Ambience = E_D75; #break
     #case (3) #declare Ambience = E_D93; #break
   #end
   #if (UseIL)
     #switch (Ambient)
       #case (4)
         #declare Ambience = ILight_Continuous
         ( ES_GTE_341_Warm, no, ILIGHT_XYZ, ILIGHT_LIGHTSYS_LEVEL
         );
         #break
       #case (5)
         #declare Ambience = ILight_Continuous
         ( ES_GTE_341_Cool, no, ILIGHT_XYZ, ILIGHT_LIGHTSYS_LEVEL
         );
         #break
       #case (6)
         #declare Ambience = ILight_Continuous
         ( ES_Mitsubishi_Standard_Fluorescent, no, ILIGHT_XYZ,
           ILIGHT_LIGHTSYS_LEVEL
         );
         #break
       #case (7)
         #declare Ambience = ILight_Continuous
         ( ES_Osram_CoolFluor_36w, no, ILIGHT_XYZ, ILIGHT_LIGHTSYS_LEVEL
         );
         #break
     #end
     #declare Reflux = array[8] { 1, 1.094, 1.187, 1.303, 1, 1, 1, 1 }
   #else
     #switch (Ambient)
       #case (4) #declare Ambience = E_GTE_341_Warm; #break
       #case (5) #declare Ambience = E_GTE_341_Cool; #break
       #case (6) #declare Ambience = E_Mitsubishi_Standard_Fluorescent; 
#break
       #case (7) #declare Ambience = E_Osram_CoolFluor_36w; #break
     #end
     #declare Reflux = array[8]
     { 1, 1.094, 1.187, 1.303, 0.2958, 0.3013, 3.7875, 3.0149
     }
   #end

  //--------------------- ENVIRONMENT ------------------------

   global_settings
   { assumed_gamma 1
     max_trace_level 50
     #if (Ph != 0)
       photons { spacing Ph autostop 0 }
     #end
   }
   #default { finish { ambient 0 diffuse 1 } }

   light_source //ambient light
   { 10000 * y, SpectralEmission (Ambience) * Reflux [Ambient] * 0.2
     parallel point_at 0
     photons { reflection off refraction off  }
     media_interaction off
     shadowless
   }

   plane
   { y, 0
     pigment { C_Spectral (D_CC_A4) }
   }

   #declare PRISM = 0.025;
   #declare YPRISM = 10;

   Set_Camera (<YPRISM * 0.36, 2.2, -1.65>, <YPRISM * 0.36, 0, 0>, 20)
   Set_Camera_Aspect_Ratio (1)

  //------------------------- RIG ----------------------------

   light_source //direct light
   { vrotate (-10000 * x, -30 * z),
     SpectralEmission (E_Sunlight) * 0.42
     parallel point_at 0
   }

   #declare Prism = prism
   { -1, 0, 4, <0, 0>, <-1, sqrt(3)>, <1, sqrt(3)>, <0, 0>
     rotate <-90, 0, 15>
     scale <PRISM, PRISM, 1>
     M_Spectral_Filter (Value_1, IOR_Glass_BK7, 100)
     photons { target collect off reflection on refraction on }
   }
   #for (I, 0, 6)
     object
     { Prism
       scale <I * 0.5 + 1, I * 0.5 + 1, 0.165>
       translate <0, YPRISM, I * 0.165 - 0.5>
     }
   #end

   box //block the direct light
   { y - 1, 1 - x scale YPRISM
     pigment { C_Spectral (D_CC_C4) }
   }

  //---------------------- ANNOTATION ------------------------

   Screen_Object
   ( union
     { #declare Line = 0;
       #while (Line < 3)
         #if (s_Ambients [Ambient][Line] = "")
           #declare Line = 3;
         #else
           text
           { ttf "cyrvetic" s_Ambients [Ambient][Line] 0.001, 0
             translate -Line * y
           }
           #declare Line = Line + 1;
         #end
       #end
       pigment { rgb 0 }
       scale 0.07
     },
     <0, 1>, <0.03, 0.03>, yes, 1
   )
   #if (Preview)
     Screen_Object
     ( text
       { ttf "cyrvetic" "Preview" 0.001, 0
         pigment { rgb 0 }
         scale 0.06 rotate 90 * z
       },
       <0, 0>, <0.03, 0.03>, yes, 0.1
     )
   #end

//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
#else

   #declare FName = "rich_teal"
   #include "SpectralComposer.inc"

#end
==============================[END CODE]==============================

So, you color gurus, where are the rich, deep spectral cyans?


Post a reply to this message


Attachments:
Download 'desat_submission.png' (2 KB) Download 'spectral_desat-pbi.png' (2 KB) Download 'rich_teal_montage-d65.png' (218 KB) Download 'rich_teal_montage-d50.png' (129 KB)

Preview of image 'desat_submission.png'
desat_submission.png

Preview of image 'spectral_desat-pbi.png'
spectral_desat-pbi.png

Preview of image 'rich_teal_montage-d65.png'
rich_teal_montage-d65.png

Preview of image 'rich_teal_montage-d50.png'
rich_teal_montage-d50.png


 

From: Cousin Ricky
Subject: Re: Yet still another color question: spectral cyan
Date: 16 Nov 2016 16:10:00
Message: <web.582ccadbd6f89a52e8ae267f0@news.povray.org>
Cousin Ricky <ric### [at] yahoocom> wrote:
> The spectra for the ambient lights were prepared with
> integratelight.inc, which integrates spectral curves rather than
> sampling points on the curves.  I haven't yet released the code, but the
> scene file will render without it.  Except for the Mitsubishi runs, the
> results look virtually identical either way.

IntegrateLight is now available at the Object Collection.  IntegrateLight has
had a major bug fix and a feature change since the OP, which require this change
to the section of rich_teal.pov that #declares Ambience:

==========[BEGIN CODE CHANGE]==========
  #if (UseIL)
    #switch (Ambient)
      #case (4)
        #declare Ambience = ILight_Continuous
        ( ES_GTE_341_Warm, no, ILIGHT_XYZ, 1
        );
        #break
      #case (5)
        #declare Ambience = ILight_Continuous
        ( ES_GTE_341_Cool, no, ILIGHT_XYZ, 1
        );
        #break
      #case (6)
        #declare Ambience = ILight_Continuous
        ( ES_Mitsubishi_Standard_Fluorescent, no, ILIGHT_XYZ, 1
        );
        #break
      #case (7)
        #declare Ambience = ILight_Continuous
        ( ES_Osram_CoolFluor_36w, no, ILIGHT_XYZ, 1
        );
        #break
    #end
    #declare Reflux = array[8] { 1, 1.094, 1.187, 1.303, 3.6, 3.6, 3.6, 3.6 }
===========[END CODE CHANGE]===========


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.