View Full Version : Strange color behaviour

03 March 2008, 03:47 AM
I was writing a saturation function today, and I ran across some strange behaviour. Maxscript is 'truncating' the return of a float4 color (with alpha), but internally it is still there... here is the relevant code, and the return of each line if I set val = color 1000 1000 1000 1000

fn saturateF val = (
local newVal
if val < 0 then newVal = 0
else if val > 1 then newVal = 1
else newVal = val
return newVal

newVal = val --I have to do this so newVal is the same class as val, since this is a generalized function

val /= 255 --returns (color 3.92157 3.92157 3.92157 3.92157)

newVal.r = saturateF val.r --returns 1
newVal.g = saturateF val.g --returns 1
newVal.b = saturateF val.b --returns 1

try (newVal.a = saturateF val.a) catch () --returns 1

--printing newVal at this point returns (color 1 1 1 1), as expected

newVal *= 255 --returns (color 255 255 255), WTF?

newVal.a --returns 255.0, WTF?

When I multiply my float4 color newVal, it appears to truncate itself to a float3, but the data is still there. What accounts for this strange behaviour? It doesn't appear to break anything but it is definitely something I want to fix, especially since this is a general and generalized function. I know there are various workarounds but I'm curious if there are any legitimate reasons for this behaviour (other than 'well that is maxscript for you...)

03 March 2008, 03:53 AM
Since day one (which means Max 2.0), Color values with an alpha of 255 have been displayed without the alpha. Don't use Color values, use Point4 values if you want to work with floating point colors (like HDRI etc.)

Here are the Notes from the upcoming Max 2009 version of the help:


The addition and subtraction operations are performed on the R, G, B and A channels equally:

aColor = color 1 1 1

--> (color 1 1 1)
aColor + aColor

--> (color 2 2 2 510)

The high Alpha value is caused by the fact that MAXScript does not print the Alpha value if it is 255, but internally the value of the variable aColor is (color 1 1 1 255). Thus, adding the Alpha channels of 255 to 255 produces an Alpha of 512, analogous to the R,G and B channels.

While the Color Values allow floating point components, when originally implemented in 3ds Max 2, it was assumed that they would be used mainly for 8 bit per channel RGBA values because MAXScript did not support floating point color bitmaps at that point in time. An internal conversion is performed when printing color values or converting other values to color.

Thus, multiplication of two color values leads to seemingly strange results:

aColor = color 1 1 1

aColor * aColor

--> (color 0.00392157 0.00392157 0.00392157)

aColor * [1,1,1]

--> (color 0.00392157 0.00392157 0.00392157)

aColor = color 128 128 128

aColor * aColor

--> (color 64.251 64.251 64.251)

The reason for these results when multiplying color values is that the actual component values are float values normally in the range 0 to 1.

The scaling from 0-1 to 0-255 is an operation MAXScript performs to the underlying color value when the value is printed or converted to some other value type.

A gray value of 128 multiplied by a gray value of 128 is not really 128*128 = 16384, which is a blown out white, but

(128/255.0 * 128/255.0)*255or (.501961*.501961)*255

which is the DARKER shade of gray(color 64.251 64.251 64.251)

So when (color 1 1 1 255)is converted to components in the range from 0 to 1, it also results in RGB components of (1.0/255*1.0/255)*255 = 0.00392157, while the Alpha of 255 turns into 1.0 and then back into 255.

Thus, the Color Value is not well suited for High Dynamic Range Image calculations with floating point color components.

For that type of operations, MAXScript provides a Point4 value which can be used to represent floating point colors without implicit conversion from/to the 0-255 range. This value was introduced in 3ds Max 6 to support the color parameters of mental ray shaders.

03 March 2008, 08:38 PM
Awesome, thanks.

Personally I get frustrated by the whole 0-1 and 0-255 and colors/point3/point4 stuff. Give me everything between 0 and 1 and get rid of colors all together, thanks :)

03 March 2008, 09:35 PM
Awesome, thanks.

Personally I get frustrated by the whole 0-1 and 0-255 and colors/point3/point4 stuff. Give me everything between 0 and 1 and get rid of colors all together, thanks :)

In this case, just stop using Colors and Point3s.
Switch to Point4 which is the color value for mental ray.

For example,

b = bitmap 200 200 color:(point4 1 0 0.5 0.5)
display b

will create a bitmap with pink color and half alpha. No need to use Color to do it. Just forget it ever existed...

Of course, some places in Max will still return a Color value, but you can always convert it to Point4 and store/use that.

For example,

rollout test "Color Picker"
colorpicker clr_test alpha:true
on clr_test changed val do print (val as point4)
createDialog test

CGTalk Moderation
03 March 2008, 09:35 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.