Difference between revisions of "Reference:Color Expressions"
Jholsenback (talk | contribs) m (added link) |
Jholsenback (talk | contribs) m (typo) |
||
Line 312: | Line 312: | ||
#declare Second_Component = Color.green; | #declare Second_Component = Color.green; | ||
#declare Third_Component = Color.blue; | #declare Third_Component = Color.blue; | ||
− | #declare | + | #declare Fourth_Component = Color.filter; |
#declare Fifth_Component = Color.transmit; | #declare Fifth_Component = Color.transmit; | ||
</pre> | </pre> |
Revision as of 11:50, 10 July 2016
COLOR: COLOR_BODY | color COLOR_BODY | (this means the keyword color or colour COLOR_BODY colour may optionally precede any color specification) COLOR_BODY: COLOR_VECTOR | COLOR_KEYWORD_GROUP | COLOR_IDENTIFIER COLOR_VECTOR: rgb <3_Term_Vector> | rgbf <4_Term_Vector> | rgbt <4_Term_Vector> | [ rgbft ] <5_Term_Vector> | srgb <3_Term_Vector> | srgbf <4_Term_Vector> | srgbt <4_Term_Vector> | srgbft <5_Term_Vector> COLOR_KEYWORD_GROUP: [ COLOR_KEYWORD_ITEM ]... COLOR_KEYWORD_ITEM: COLOR_IDENTIFIER | red Red_Amount | blue Blue_Amount | green Green_Amount | filter Filter_Amount | transmit Transmit_Amount
Note: COLOR_IDENTIFIERS are identifiers previously declared to have color values. The 3, 4, and 5 term vectors are usually vector literals but may be vector expressions or floats promoted to vectors. See Operator Promotion and the sections below.
POV-Ray often requires you to specify a color. Colors consist of five
values or color components. The first three are called red
,
green
, and blue
. They specify the intensity of the
primary colors red, green and blue using an additive color system like the
one used by the red, green and blue color phosphors on a color monitor.
The 4th component, called filter
, specifies the amount of
filtered transparency of a substance. Some real-world examples of filtered
transparency are stained glass windows or tinted cellophane. The light
passing through such objects is tinted by the appropriate color as the
material selectively absorbs some frequencies of light while allowing others
to pass through. The color of the object is subtracted from the light passing
through so this is called subtractive transparency.
The 5th component, called transmit
, specifies the amount of
non-filtered light that is transmitted through a surface. Some real-world
examples of non-filtered transparency are thin see-through cloth, fine mesh
netting and dust on a surface. In these examples, all frequencies of light
are allowed to pass through tiny holes in the surface. Although the amount of
light passing through is diminished, the color of the light passing through
is unchanged.
The color of the object and the color transmitted through the object
together contribute 100% of the final color. So if transmit
is set to 0.9,
the transmitted color contributes 90% and the color of the object
contributes only 10%. This is also true outside of the 0-1 range, so for
example if transmit
is set to 1.7, the transmitted color contributes with
170% and the color of the object contributes with minus 70%. Using transmit
values outside of the 0-1 range can be used to create interesting special
effects, but does not correspond to any phenomena seen in the real world.
An example:
camera {location -2.5*z look_at 0 orthographic} box { 0,1 texture { pigment { gradient y colour_map { [0, red 1] [1, blue 1] } } finish{ambient 1} } texture { pigment { gradient x colour_map { [0, rgb 0.5 transmit -3] [1, rgb 0.5 transmit 3] } } finish{ambient 1} } translate <-0.5,-0.5,0> scale <3,2,1> }
When using the transmit
value for special effects, you can visualize it this way:
The transmit
value means contrast. 1.0 is no change in contrast, 0.5 is
half contrast, 2.0 is double contrast and so on. You could say that
transmit
scales the colors. The color of the object is the center value.
All colors will get closer to the center value if transmit
is between 0
and 1, and all colors will spread away from the center value if transmit
is greater than 1. If transmit
is negative the colors will be inverted
around the center value. Rgb 0.5 is common to use as center value, but
other values can be used for other effects. The center value really is a
color, and non-gray colors can be used for interesting effects. The red,
green and blue components are handled separately.
Note: Earlier versions of POV-Ray used the
keyword alpha
to
specify filtered transparency. However that word is often used to describe
non-filtered transparency. For this reason alpha
is no longer
used.
Each of the five components of a color are float values which are normally in the range between 0.0 and 1.0. However any values, even negatives may be used.
Under most circumstances the keyword color
is optional and may
be omitted. We also support the British or Canadian spelling
colour
. Colors may be specified using vectors, keywords with floats or
identifiers. You may also create very complex color expressions from
combinations of any of these using various familiar operators. The syntax for
specifying a color has evolved since POV-Ray was first released. We have
maintained the original keyword-based syntax and added a short-cut vector
notation. Either the old or new syntax is acceptable however the vector
syntax is easier to use when creating color expressions.
The syntax for combining color literals into color expressions is almost identical to the rules for vector and float expressions. In the syntax for vector expressions, some of the syntax items are defined in the section for float expressions. See Float Expressions for those definitions. Detailed explanations of color-specific issues are given in the following sub-sections.
Color Vectors
The syntax for a color vector is...
COLOR_VECTOR: rgb <3_Term_Vector> | rgbf <4_Term_Vector> | rgbt <4_Term_Vector> | [ rgbft ] <5_Term_Vector>
...where the vectors are any valid vector expressions of 3, 4 or 5 components. For example
color rgb <1.0, 0.5, 0.2>
This specifies a color whose red component is 1.0 or 100% of full intensity. The green component is 0.5 or 50% of full intensity and the blue component is 0.2 or 20% of full intensity. Although the filter and transmit components are not explicitly specified, they exist and are set to their default values of 0 or no transparency.
The rgbf
keyword requires a four component vector. The 4th
component is the filter component and the transmit component defaults to
zero. Similarly the rgbt
keyword requires four components where
the 4th value is moved to the 5th component which is transmit and then the
filter component is set to zero.
The rgbft
keyword allows you to specify all five components.
Internally in expressions all five are always used.
Under some circumstances, if the vector expression is a 5 component
expression or there is a color identifier in the expression then the
rgbft
keyword is optional.
sRGB Colors
While POV-Ray will normally expect colors to be expressed in whatever working gamma space you have set via assumed_gamma
, as of version 3.7 the srgb
, srgbf
, srgbt
and srgbft
keywords have been added to specify colors encoded according to the sRGB standard (roughly corresponding to a display gamma pre-correction of 2.2). Using these keywords instead of rgb
, rgbf
, rgbt
or rgbft
, respectively, instructs POV-Ray to automatically convert the color components to the working gamma space, being approximately equivalent to:
Effective_Red_Amount = pow ( Red_Amount, 2.2/AssumedGamma ) Effective_Green_Amount = pow ( Green_Amount, 2.2/AssumedGamma ) Effective_Blue_Amount = pow ( Blue_Amount, 2.2/AssumedGamma ) Effective_Filter_Amount = Filter_Amount Effective_Transmit_Amount = Transmit_Amount
Note: Defining sRGB colors before assumed_gamma
has been set will halt parsing and issue a warning.
The syntax is primarily intended for convenience when working with a physically accurate assumed_gamma
of 1.0, as many people find this way of specifying colors more intuitive (for instance a value of about srgb 0.5
is commonly perceived as a medium grey, despite having an actual brightness of no more than 21.4%), and most image processing software and tools also use gamma pre-corrected colours in their user interface; while those may use slightly different color spaces, sRGB is a good approximation, and also has the advantage of being the official recommendation for the World Wide Web.
Note: Colors specified this way are not a different flavor of colors, but are rather converted on the fly to linear color values. When interpreting such values as a vector or accessing individual components, you will get the linear values rather than the pre-corrected values you originally specified.
For instance, the following color statements are all fully equivalent (except for rounding errors):
#declare Foo = color srgbt <51,76,102,127>/255; #debug concat("<",vstr(5,Foo,",",0,3),">\n") #declare Foo = color srgbt <0.2, 0.3, 0.4, 0.5>; #debug concat("<",vstr(5,Foo,",",0,3),">\n") #declare Foo = color srgb <0.2, 0.3, 0.4> transmit 0.5; #debug concat("<",vstr(5,Foo,",",0,3),">\n") #declare Foo = color rgbt <0.033,0.073,0.133,0.5>; #debug concat("<",vstr(5,Foo,",",0,3),">\n")
Note: The srgb
, srgbf
, srgbt
and srgbft
keywords do not affect the way filter or transmit components are interpreted; these are always expected to be linear.
Color Keywords
The older keyword method of specifying a color is still useful and many users prefer it.
COLOR_KEYWORD_GROUP: [ COLOR_KEYWORD_ITEM ]... COLOR_KEYWORD_ITEM: COLOR_IDENTIFIER | red Red_Amount | blue Blue_Amount | green Green_Amount | filter Filter_Amount | transmit Transmit_Amount
Although the color
keyword at the beginning is optional, it
is more common to see it in this usage. This is followed by any of five
additional keywords red
, green
, blue
,
filter
, or transmit
. Each of these component
keywords is followed by a float expression. For example
color red 1.0 green 0.5
This specifies a color whose red component is 1.0 or 100% of full intensity and the green component is 0.5 or 50% of full intensity. Although the blue, filter and transmit components are not explicitly specified, they exist and are set to their default values of 0. The component keywords may be given in any order and if any component is unspecified its value defaults to zero. A COLOR_IDENTIFIER can also be specified but it should always be first in the group. See Common Color Pitfalls for details.
Color Identifiers
Color identifiers may be declared to make scene files more readable and to parameterize scenes so that changing a single declaration changes many values. An identifier is declared as follows.
COLOR_DECLARATION: #declare IDENTIFIER = COLOR; | #local IDENTIFIER = COLOR;
Where IDENTIFIER is the name of the identifier up to 40 characters long and COLOR is any valid specification.
Note: There should be a semi-colon at the end of the declaration. If omitted, it generates a warning and some macros may not work properly. See #declare vs. #local for information on identifier scope.
Here are some examples....
#declare White = rgb <1,1,1>; #declare Cyan = color blue 1.0 green 1.0; #declare Weird = rgb <Foo*2,Bar-1,Bob/3>; #declare LightGray = White*0.8; #declare LightCyan = Cyan red 0.6;
As the LightGray
example shows you do not need any color
keywords when creating color expressions based on previously declared colors.
The last example shows you may use a color identifier with the keyword style
syntax. Make sure that the identifier comes first before any other component
keywords.
Like floats and vectors, you may re-define colors throughout a scene but the need to do so is rare.
Color Operators
Color vectors may be combined in expressions the same as float or vector
values. Operations are performed on a component by component basis. For
example rgb <1.0,0.5,0.2>*0.9
evaluates the same as
rgb<1.0,0.5,0.2>*<0.9,0.9,0.9>
or
rgb<0.9,0.45,0.18>
. Other operations are done on a similar
component by component basis.
You may use the dot operator to extract a single component from a color.
Suppose the identifier Shade
was previously defined as a color.
Then Shade.red
is the float value of the red component of
Shade
. Similarly Shade.green
, Shade.blue
,
Shade.filter
and Shade.transmit
extract the float
value of the other color components. shade.gray
returns the gray value of the
color vector.
Dot Item Access for Colors
POV-Ray provides an easy method to access the individual components of different types of color expressions, as illustrated in the following code examples:
#declare Color = <1, 2, 3>; #declare First_Component = Color.red; #declare Second_Component = Color.green; #declare Third_Component = Color.blue; #declare Color = <1, 2, 3, 4, 5>; #declare First_Component = Color.red; #declare Second_Component = Color.green; #declare Third_Component = Color.blue; #declare Fourth_Component = Color.filter; #declare Fifth_Component = Color.transmit;
See also: Dot Item Access for Vectors.
Common Color Pitfalls
The variety and complexity of color specification methods can lead to some common mistakes. Here are some things to consider when specifying a color.
When using filter transparency, the colors which come through are multiplied
by the primary color components. For example if gray light such as
rgb<0.9,0.9,0.9>
passes through a filter such as
rgbf<1.0,0.5,0.0,1.0>
the result is
rgb<0.9,0.45,0.0>
with the red let through 100%, the green cut
in half from 0.9 to 0.45 and the blue totally blocked. Often users mistakenly
specify a clear object by
color filter 1.0
but this has implied red, green and blue values of zero. You have just specified a totally black filter so no light passes through. The correct way is either
color red 1.0 green 1.0 blue 1.0 filter 1.0
or
color transmit 1.0
In the 2nd example it does not matter what the rgb values are. All of the light passes through untouched. Another pitfall is the use of color identifiers and expressions with color keywords. For example...
color My_Color red 0.5
this substitutes whatever was the red component of My_Color
with a red component of 0.5 however...
color My_Color + red 0.5
adds 0.5 to the red component of My_Color
and even less
obvious...
color My_Color * red 0.5
that cuts the red component in half as you would expect but it also
multiplies the green, blue, filter and transmit components by zero! The part
of the expression after the multiply operator evaluates to
rgbft<0.5,0,0,0,0>
as a full 5 component color.
The following example results in no change to My_Color
.
color red 0.5 My_Color
This is because the identifier fully overwrites the previous value. When using identifiers with color keywords, the identifier should be first. Another issue to consider: some POV-Ray syntax allows full color specifications but only uses the rgb part. In these cases it is legal to use a float where a color is needed. For example:
finish { ambient 1 }
The ambient keyword expects a color so the value 1
is
promoted to <1,1,1,1,1>
which is no problem. However
pigment { color 0.4 }
is legal but it may or may not be what you intended. The 0.4
is promoted to <0.4,0.4,0.4,0.4,0.4>
with the filter and
transmit set to 0.4 as well. It is more likely you wanted...
pigment { color rgb 0.4 }
in which case a 3 component vector is expected. Therefore the
0.4
is promoted to <0.4,0.4,0.4,0.0,0.0>
with
default zero for filter and transmit. Finally there is another problem which
arises when using color dot operators in #declare
or #local
directives. Consider the directive:
#declare MyColor = rgb <0.75, 0.5, 0.75>; #declare RedAmt = MyColor.red;
Now RedAmt
should be a float but unfortunately it is a color.
POV-Ray looks at the first keyword after the equals to try to guess what type
of identifier you want. It sees the color identifier MyColor
and assumes you want to declare a color. It then computes the float value as
0.75 then promotes that into
rgbft<0.75,0.75,0.75,0.75,0.75>
. It would take a major rewrite
to fix this problem so we are just warning you about it. Any of the
following work-arounds will work properly.
#declare RedAmt = 0.0+MyColor.red; #declare RedAmt = 1.0*MyColor.red; #declare RedAmt = (MyColor.red);