Babylon.js Apis – Color4

Constructors 构造函数

new Color4(r?: number, g?: number, b?: number, a?: number): Color4

上面的是 TypeScript 语法,

r?: number 表示参数是可选的且数据类型为 number 类型。

r, g, b, a 分别表示颜色中的 red, green, blue, alpha 红绿蓝透明度,和css中的设置

颜色有点类似: rgba(100, 100, 100, .5);

四个参数均为*可选*,取值范围均为 0 ~ 1 默认值均为 0

如果四个都不填直接 new Color4(); 其实就相当于 new Color4(0, 0, 0, 0);


创建一个颜色对象: const c = new BABYLON.Color4(0, 0, 0, 1);

console.log(c, 'color') 输出结果:

img

所有的 Color4 构造函数的调用都要基于 BABYLON 调用,

比如: new BABYLON.Color4();

Properties 属性

Methods 方法

add(right: DeepImmutable): Color4

将两个颜色值相加得到新的颜色对象:

1
2
3
const c1 = new Color4(0, 0.1, 0.2, 1);
const c2 = new Color4(1, 0.3, 0.5, 1);
c1.add(c2);

结果:

img

3.1

addInPlace(right: DeepImmutable): Color4

相加并替换,且返回原对象。

1
2
3
4
5
const c1 = new C4(0, 0.1, 0.2, 1)
const c2 = new C4(1, 0.3, 0.5, 1)
const c4 = c1.addInPlace(c2)
// const c3 = c1.add(c2)
console.log(c1, c4, c4 === c1, 'color4')

输出结果:

img

从结果可知该函数的作用会改变原始对象 c1

其作用是将 c2 对象的值和 c1 对象的值相加之后赋值给 c2 属性,然后将 c2 直接作为

返回值返回,因此才有结果中的输出内容一致,且 c4 === c1 结果为 true

3.2

asArray(): number[]

将颜色对象转换成新数组返回,值得对应关系为: r, g, b, a => [0, 0, 0, 0]

1
2
3
const c1 = new C4(0, 0.1, 0.2, 1)
const c2 = c1.asArray()
console.log(c1, c2, 'color4')

img

3.3

clampToRef

clampToRef(min: number|undefined, max: number|undefined, result: Color4)

Color4 对象的四个属性值按照 min~max 范围去进行截取,如果超出这个返回则取相应的临界值(min或max),

然后将截取后的结果设置在 result 这个对象上,该存储对象必须是个 Color4 类型的值,从下面的实例可知其实

只要传一个有效的对象即可(let c4 = {}),因为 new Color4() 最终结果也是个普通对象。

1
2
3
4
5
6
7
8
9
// 1. asArray
let c1 = new C4(2, 0.5, 0.8, 1)
let c2 = c1.asArray()
let c3 = c1.add(new C4(0, 0, 0, 0)) // new a color same with c1
// 2. clampToRef 截取值
// 完了之后 c3 应该是: {r: 1.5, g: 0.5, b: 0.8, a: 1}
let c4 = {} // 这里必须是有效的对象类型,不能是 null/undefined 非法制
c2 = c1.clampToRef(0, 1.5, c4)
console.log(c1, c4, 'color4')

如上,传 c3, c4 都可以,建议使用 c3 采用 BABYLON 内置对象的方式去使用,

c3 的创建使用了 add 方法和 Color4 对象的结合。

结果:

img

3.4

clone(): Color4

创建 Color4 对象的拷贝

clampToRef 中的例子使用 clone() 改造下:

1
2
3
4
5
6
7
8
9
10
11
12
// 1. asArray
let c1 = new C4(2, 0.5, 0.8, 1)
let c2 = c1.asArray()
const zero = new C4(0, 0, 0, 0)
//let c3 = c1.add(new C4(0, 0, 0, 0)) // new a color same with c1
let copy = zero.clone()
console.log(zero, copy, copy === zero, 'color4 - clone')
// 2. clampToRef 截取值
// 完了之后 c3 应该是: {r: 1.5, g: 0.5, b: 0.8, a: 1}
let c4 = {} // 这里必须是有效的对象类型,不能是 null/undefined 非法制
c2 = c1.clampToRef(0, 1.5, copy)
console.log(c1, copy, 'color4 - clampToRef')

输出结果和 clampToRef 中一样,且属于值得拷贝,因为 copy === zero 的结果为 false

img

3.5

copyFrom(source: Color4): Color4

source:Color4 中拷贝属性的值到当前的对象,并覆盖其中的属性值,然后返回更新之后的当前对象。

1
2
3
4
const src = new C4(1, 0, 1, 1)
const curr = new C4(0, 0, 0, 0)
const res = curr.copyFrom(src)
console.log(curr, src, res, res === curr, 'copyFrom')

img

3.6

copyFromFloats(r: number, g: number, b: number, a: number): Color4

这个函数和 copyFrom 功能一样,只不过要拷贝的属性值来源不一样,前者是从一个 Color4 对象

中拷贝而来,这个函数是直接采用传递参数的方式,从所传递的四个参数值中获取然后拷贝到当前的对象,

返回值都一样是返回当前已经更新的对象。

3.7

equals(otherColor:DeepImmutable): boolean

比较两个颜色对象的属性值(rgba)是否一样。

1
2
3
4
5
6
7
8
9
10
11
const c1 = new C4(1, 0, 1, 1)
const c2 = new C4(1, 0, 1, 1)
const c3 = c1
const c4 = new C4(2, 0, 1, 1)

const isC1EC2 = c1.equals(c2)
const isC1EC3 = c1.equals(c3)
const isC1EC4 = c1.equals(c4)
console.log('c1 = c2 ? ', isC1EC2, 'color4 equals')
console.log('c1 = c3 ? ', isC1EC3, 'color4 equals')
console.log('c1 = c4 ? ', isC1EC4, 'color4 equals')

结果:

img

3.8

getClassName(): string

返回 “Color4”。

img

3.9

getHashCode(): number

当前创建的 Color4 对象的一个唯一的数字(hashcode)。

img

3.10

multiply(color: Color4): Color4

两个对象的值相乘得到新的值,以新的对象返回。

1
2
3
4
const c1 = new C4(0.1, 0.2, 0.3, 0.4)
const c2 = new C4(0.3, 0.4, 0.5, 0.6)

console.log(c1.multiply(c2), 'color4 - multiply')

img

3.11

multiplyToRef(color: Color4, result: Color4): Color4

multiply 的功能一样,只不过得到的结果值放到 result 里面了,且返回值也是 result 这个对象。

img

3.12

scale(scale: number): Color4

将当前的对象的属性值放大多少倍之后产生新的 Color4 对象返回。

1
2
3
4
const c1 = new C4(0.1, 0.2, 0.3, 0.4)
const scaled = c1.scale(2)

console.log(scaled, 'color4 - scale')

结果:

{r: 0.2, g: 0.4, b: 0.6, a: 0.8} "color4 - scale"

3.13

scaleAndAddToRef(scale: number, result: Color4): Color4

将当前的对象的属性值放到 scale 倍之后与 result 对象的属性值相加之后再用相加之后的值去更新

result 属性的值。

返回值为没有更新的当前对象,即该函数不会改变原始对象。

该函数的另一种实现可以结合 addscale 完成:

result.addInPlace(current.scale(number))

上面的步骤:

  1. current.scale(number) 先放大然后返回放大之后的 Color4 对象(scaled)
  2. result.addInPlace(scaled) 将放大之后的与 result 值相加且替换 result 中的值

    然后我们要的返回值是原对象 current ,而 addInPlace 返回的却是更新之后的原对象(这里是 result),

    继续执行下面的便能达到目的(到目前为止 current 本身还尚未发生变化)

  3. current.addInPlace(result.multiply(new Color(0, 0, 0, 0)) 最后得到值未发生变化的 current 对象。

    但其实实际上 current 的内容是有发生变化的,只不过是做了 val + 0 === val 的还原处理而已。

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const zero = new C4(0, 0, 0, 0)
const current = new C4(0.1, 0.2, 0.3, 0.4)
let target = new C4(0, 0, 0, 0)
let result = current.scaleAndAddToRef(2, target)

console.log('target: ', target, 'color4 - scaleAndAddToRef')
console.log('res = current ?? ', result === current, 'color4 - scaleAndAddToRef')

// 使用各种函数结合起来的方法

const myScaleAndAddToRef = (current, number, target) => current.addInPlace(
(target.addInPlace(current.scale(number))).multiply(zero)
)

target = new C4(0, 0, 0, 0) // reset, 下面的结果和上面一样
result = myScaleAndAddToRef(current, 2, target)

console.log('target: ', target, 'color4 - myScaleAndAddToRef')
console.log('res = current ?? ', result === current, 'color4 - myScaleAndAddToRef')

结果:

img

3.14

scaleToRef(scale: number, result: Color4): Color4

这个函数想较于 scaleAndAddToRef 来说少了一个 add 的步骤,其他基本一致。

如果是自定义实现的话只需要让保存结果的对象乘上零就行了 target.multiply(zero)

1
2
3
const myScaleAndAddToRef = (current, number, target) => current.addInPlace(
target.multiply(zero).addInPlace(current.scale(number))
)

因为这个函数不是将放大之后的结果和 target 的属性值叠加而是直接覆盖,因此将 target 的属性值重置

乘零再和放大之后的结果相加一样也可以模拟叠加的效果。

3.15

set(r: number, g: number, b: number, a: number): Color4

用参数中的值去设置更新当前对象中的属性值,然后返回当前对象。

1
2
3
4
5
6
7

const current = new C4(0, 1, 0, 1)
const res = current.set(0.2, 0.8, 1, 0)

// 最后 current 结果是: { r: 0.2, g: 0.8, b: 1, a: 0 }
// res === current ? true
console.log(current, res === current, 'color4 set')

结果:

{r: 0.2, g: 0.8, b: 1, a: 0} true "color4 set"

3.16

subtract(right: DeepImmutable): Color4

当前得值减去给定的值,作为新对象返回,就是单纯的左减法。

1
2
3
4
5
6
7
8
9

const current = new C4(0, 1, 0, 1)
const target = new C4(1, 0.2, 1, 0.5)
// 当前的值减去给定的值,current - target
const res = current.subtract(target)

console.log('current: ', current, res === current, 'color4 subtract')
console.log('target: ', target, res === current, 'color4 subtract')
console.log('result: ', res, res === current, 'color4 subtract')

结果:

img

3.17

subtractToRef(right: DeepImmutable, result: Color4): Color4

功能和 subtract 一样,不同点在于:

  1. currentright 相减之后的结果保存到 result 中去;
  2. 返回值不同,这个返回的是当前未改变的对象(current),之前的是返回的一个新的对象。

3.18

toArray(array: number[], index?: number): Color4

这个函数作用是将 current 当前的对象中的属性值逐个的替换数组中的元素值,要替换的数组元素起始位置

由后面的 index 参数的值决定。

1
2
3
4
5
6
7
8

const current = new C4(0, 1, 0, 1)
const arr = [2, 3, 4, 5]
// 当前的值减去给定的值,current - target
const res = current.toArray(arr, 2)

console.log('current: ', current, res === current, 'color4 toArray')
console.log('array: ', arr, res === current, 'color4 toArray')

结果:

img

index 改成 20 结果:

img

从结果会很惊讶(原本以为超出数组总长了会默认在数组末尾追加)的发现中间多出了 16 个空元素(hole element)

这个是很不友好的,因此尽量避免这么做吧,不知道为何没有做索引值得限制。

由于 index?: number 是可选的,所以也是可以不传的,不传就默认从数组下标 0 开始替换了。

3.19

toGammaSpace(): Color4

将线性值转换成伽马值,这个过程也叫做 gamma 编码

1
2
3
4
5
6

const current = new C4(0.45, 2.2, 0, 1)
// 当前的值减去给定的值,current - target
const res = current.toGammaSpace()

console.log('result: ', res, 'color4 toGammaSpace')

这篇文章有讲述 gamma spacelinear space 的区别和原理,没怎么看懂

http://www.kinematicsoup.com/news/2016/6/15/gamma-and-linear-space-what-they-are-how-they-differ

根据文中讲述的加上这里测试的结果,这个函数大概的意思就是会根据 gamma space 的原理对颜色进行校准,

校准到适合显示器显示的值。

img

下面链接的这篇文章内有个公式可用来计算得出上表中的大约结果:

链接: https://blog.csdn.net/qq_18229381/article/details/78053018

当中提到一个公式如下:

img

根据上面坐标图中的值,决定了 γ 的值是这样的(以 1.0 为界限):

  1. 大于中线部分的值为绿线部分,需要进行编码,且 γ 的值应约为 0.45
  2. 小于中线部分的值为蓝色部分,需要进行解码,且 γ 的值应为 2.2(即 0.45 的倒数)

那么根据这个结果则可以计算得出编码之后的表:

原值 Gamma 之后的值 公式计算编码得到的值
0.1 0.35111917342151316 Math.pow(0.1, 1 / 2.2) 结果: 0.35111917342151316
0.2 0.4811565050522864 Math.pow(0.2, 1 / 2.2) 结果:0.4811565050522864
2.1 1.4010812326843218 Math.pow(2.1, 1 / 2.2) 结果:1.4010812326843218
12.2 3.1174530605536335 Math.pow(12.2, 1 / 2.2) 结果:3.1174530605536335

如果需要解码只需要将编码之后的值进行(Math.pow(res, 2.2))转换即可。

3.20

toGammaSpaceToRef(convertedColor: Color4): Color4

这个和 toGammaSpace() 作用是一样的,无非就是讲转换之后的结果保存到了 convertedColor 这个对象中。

返回值是原始对象。

3.21

toHexString(): string

将颜色对象转成 16 进制的字符串。

1
2
3
4
5
6

const current = new C4(0, 0, 0, 1)
// 当前的值减去给定的值,current - target
const res = current.toHexString()

console.log('result: ', res, 'color4 toHexString')

结果: result: #000000FF color4 toHexString

这个就比较好理解了。

3.22

toLinearSpace(): Color4

这个和上面的 toGammaSpace() 刚好是相反的,即将 gamma space 的值转成 linear space 的值。

我们就将上面现成的转换表拿下来进行解码得到的值然后和调用 toLinearSpace() 结果值进行比较一下:

原值 toGammaSpace 之后的值 编码值(Math.pow(v, 1/2.2)) toLinearSpace后的值 解码值(Math.pow(v, 2.2))
0.1 0.35111917342151316 0.35111917342151316 0.1 0.1
0.2 0.4811565050522864 0.4811565050522864 0.19999999999999998 0.19999999999999998
2.1 1.4010812326843218 1.4010812326843218 2.1000000000000005 2.1000000000000005
12.2 3.1174530605536335 3.1174530605536335 12.200000000000003 12.200000000000003

其实根据公式的计算结果毫无疑问互相转换的结果肯定是可以对的上的(忽略精确度的问题)。

上表包含了四种对原值进行计算的结果:

  1. toGammaSpace 将原值进行编码(伽马编码)的结果值
  2. Math.pow(v, 1/2.2) 根据伽马编码公式计算原值的结果
  3. toLinearSpace 将伽马编码之后的值进行解码(伽马解码)得结果值
  4. Math.pow(v, 2.2) 根据伽马解码公式将编码之后的值进行计算的结果

2, 4 是通过对应的公式进行编码解码的结果,这里讲表格列出来主要是验证 toGammaSpacetoLinearSpace

两个函数内部计算的公式。

3.23

toLinearSpaceToRef(convertedColor: Color4): Color4

toLinearSpace() 功能一样,不同点:

  1. 结果值覆盖 convertedColor 的值
  2. 返回的是未发生变化的原始对象的值

3.24

toString(): string

返回对象的字符串表达形式:

1
2
3
4
5
6
7

const current = new C4(0.25, 0, 0, 1)
// 当前的值减去给定的值,current - target
const res = current.toString()

console.log('result: ', res, '<<<<< color4 toString')
console.log('result type: ', typeof res, '<<<<< color4 toString')

结果:

result:  {R: 0.25 G:0 B:0 A:1} <<<<< color4 toString
result type:  string <<<<< color4 toString

3.25

[static]CheckColors4

构造器静态函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
console.log(
'C4.CheckColors4([]): ',
C4.CheckColors4([]), '<<<<< color4 CheckColors4')
console.log(
'C4.CheckColors4([], 1): ',
C4.CheckColors4([], 1), '<<<<< color4 CheckColors4')
console.log(
'C4.CheckColors4([1.0, 0.8]): ',
C4.CheckColors4([1.0, 0.8]), '<<<<< color4 CheckColors4')
console.log(
'C4.CheckColors4([1.0, 0.8], 1): ',
C4.CheckColors4([1.0, 0.8], 1), '<<<<< color4 CheckColors4')
console.log(
'C4.CheckColors4([1.0, 0.8, 0.2, 0.3], 10): ',
C4.CheckColors4([1.0, 0.8, 0.2, 0.3], 10), '<<<<< color4 CheckColors4')
console.log(
'C4.CheckColors4([1.0, 0.8, 0.2, 0.3, 0.5, 1, 1], 3): ',
C4.CheckColors4([1.0, 0.8, 0.2, 0.3, 0.5, 1, 1], 3), '<<<<< color4 CheckColors4')

输出结果:

color4.js:5 C4.CheckColors4([]):  [] <<<<< color4 CheckColors4
color4.js:6 C4.CheckColors4([], 1):  [] <<<<< color4 CheckColors4
color4.js:7 C4.CheckColors4([1.0, 0.8]):  (2) [1, 0.8] <<<<< color4 CheckColors4
color4.js:8 C4.CheckColors4([1.0, 0.8], 1):  (2) [1, 0.8] <<<<< color4 CheckColors4
color4.js:9 C4.CheckColors4([1.0, 0.8, 0.2, 0.3], 10):  (4) [1, 0.8, 0.2, 0.3] <<<<< color4 CheckColors4
color4.js:10 C4.CheckColors4([1.0, 0.8, 0.2, 0.3, 0.5, 1, 1], 3):  (7) [1, 0.8, 0.2, 0.3, 0.5, 1, 1] <<<<< color4 CheckColors4

从上面的输出结果看,说实话还真没看出这个函数是干啥的,不管怎么传递参数最终都会讲第一个数组原样返回出来。

然后再看下这个:

1
2
3
4
5
6
7

let arr = [1.0, 0.25], res = null

res = C4.CheckColors4(arr)
console.log(
'C4.CheckColors4(arr): ',
res, res === arr, '<<<<< color4 CheckColors4')

结果竟是:

C4.CheckColors4(arr):  (2) [1, 0.25] true <<<<< color4 CheckColors4

res === arr 结果是 true ???

也就是说 CheckColors4 对数组 arr 没做任何处理原样进行返回了???

最多就是把 1.0 变成整数了。

官方描述:

img

3.26

[static]FromArray(array:DeepImmutable<ArrayLike>, offset?:number): Color4

从一个类数组或数组中提取出出值来组合成 Color4 对象返回。

1
2
3
4
5
6
7

let arr = [1.0, 0.25], res = null

res = C4.FromArray(arr)
console.log(
'C4.CheckColors4(arr): ',
res, res === arr, '<<<<< color4 CheckColors4')

结果:

C4.CheckColors4(arr):  e {r: 1, g: 0.25, b: 0, a: 1} false <<<<< color4 FromArray

结果是不足的使用默认值填充。

3.27

[static]FromColor3(color3: DeepImmutable, alpha?: number): Color4

Color3 对象根据提供的透明度参数组合成 Color4 对象。

相当于将 rgb 加上透明度变成 rgba

alpha 默认值为: 1.0 即不传该参数的时候使用默认值将 Color3 转成 Color3.

1
2
3
4
5

let arr = [1.0, 0.25], res = null

res = C4.FromColor3(new C4(1.0, 0.2, 0.3))
console.log(res, '<<<<< color4 FromColor3')

结果: e {r: 1, g: 0.2, b: 0.3, a: 1} “<<<<< color4 FromColor3”

3.28

[static]FromHexString(hex: string): Color4

将16进制颜色值转成 Color4 对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14

console.log(
'C4.FromHexString("#ffeeddff")',
C4.FromHexString("#ffeeddff"), '<<<<< color4 FromHexString')
console.log( // 没有 #,不支持
'C4.FromHexString("ffeeddff")',
C4.FromHexString("ffeeddff"), '<<<<< color4 FromHexString')
console.log( // 没有第四位透明度,不支持
'C4.FromHexString("#ffeedd")',
C4.FromHexString("#ffeedd"), '<<<<< color4 FromHexString')

console.log( // 简写,不支持
'C4.FromHexString("#fedf")',
C4.FromHexString("#fedf"), '<<<<< color4 FromHexString')

结果:

C4.FromHexString("#ffeeddff") e {r: 1, g: 0.9333333333333333, b: 0.8666666666666667, a: 1} <<<<< color4 FromHexString
C4.FromHexString("ffeeddff") e {r: 0, g: 0, b: 0, a: 0} <<<<< color4 FromHexString
C4.FromHexString("#ffeedd") e {r: 0, g: 0, b: 0, a: 0} <<<<< color4 FromHexString
C4.FromHexString("#fedf") e {r: 0, g: 0, b: 0, a: 0} <<<<< color4 FromHexString

结果告诉我们该函数只支持完整的 16 进制字符串转换,其余的均视为不合法的,但是会返回默认值: {r:0, g:0, b:0, a:0}

3.29

[static]FromInts(r:number, g:number, b:number, a:number): Color4

根据提供的参数数值创建一个 Color4 对象

参数 r/g/b/a 的取值范围均是: 0~255。

1
2
3
4
5
6
7
8
9
10
11
12
13
14

console.log(
'C4.FromInts(100, 100, 100, 100)',
C4.FromInts(100, 100, 100, 100), '<<<<< color4 FromInts')
console.log( // 缺少一个值情况
'C4.FromInts(100, 100, 100)',
C4.FromInts(100, 100, 100), '<<<<< color4 FromInts')
console.log( // 超出范围的值
'C4.FromInts(-100, 100, 100, 100)',
C4.FromInts(-100, 100, 100, 100), '<<<<< color4 FromInts')

console.log( // 超出范围的值
'C4.FromInts(1000, 100, 100, 100)',
C4.FromInts(1000, 100, 100, 100), '<<<<< color4 FromInts')

结果:

img

结果中超出范围的值也得到了相应的转换,但是属于超值,非合法值。

3.30

[static]Lerp

定义: Lerp(left: DeepImmutable<Color4>, right: DeepImmutable<Color4>, amount: number): Color4

差值混合,这个函数的意思是将 left 和 right 作为左右边界,然后两个边界的差值作为一段长度(假设),然后第三个参数为百分比,

根据这个百分比计算出最后的长度值,然后将该长度值加上起始值(left) 即最终得到的差值。

公式: result = left + (right - left) * amount

1
2
3
4
5

const left = new C4(0.1, 0.1, 0.1, 0.1)
const right = new C4(0.8, 0.8, 0.8, 0.8)
const res = C4.Lerp(left, right, 0.2)
console.log(res)

结果:

{r: 0.24000000000000002, g: 0.24000000000000002, b: 0.24000000000000002, a: 0.24000000000000002}

对照表:

起始值 结束值 差量 函数结果值 公式结果值
0.1 0.8 0.2 0.24000000000000002 0.24000000000000002
0.3 0.5 0.6 0.42 0.42

3.31

[static]LerpToRef

定义: LerpToRef(left: DeepImmutable<Color4>, right: DeepImmutable<Color4>, amount: number, result: Color4): Color4

Lerp 功能一样,不同点:

  1. 结果保存到 result
  2. 返回值为 void

3.32

本文标题:Babylon.js Apis – Color4

文章作者:ZhiCheng Lee

发布时间:2019年05月05日 - 16:07:44

最后更新:2019年05月06日 - 23:23:44

原始链接:http://blog.gcl666.com/2019/05/05/babylon_api_colors/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

0%