跳到主要内容

材质颜色

每个物体都有自己的颜色,颜色可以数字化地由红色、绿色和蓝色三个分量组成,通常被缩写为RGB。例如,要获取一个alice蓝的话,我们可以这样定义:

  // 用rgba值定义颜色
const color = clr3(0.941, 0.973, 1.000, 1.0);
  import { NamedColor } from 'ore.color';
// 直接采用color库中定义好的颜色接口
const color1 = NamedColor.aliceblue;

我们在现实生活中看到某一物体的颜色并不是这个物体真正拥有的颜色,而是它所反射的颜色。换句话说,那些不能被物体所吸收的颜色就是我们能够感知到的物体的颜色。上面定义的材质颜色是它在白色光源下能被我们感知到的颜色,但如果光源是其他颜色,那么最终的颜色向量就是:

  const lightColor = clr3(0.0, 1.0, 1.0);
const resultColor = color * lightColor;

在引擎中有以下几种方式直接定义几何的颜色属性:

  • 通过材质的Uniform参数定义
  • 通过顶点缓冲定义
提示

由于这些定义过程比较繁琐,我们在材料库中将这些方法封装为简单的材质接口,您可以参考:使用材质库

颜色作为Uniform参数

可以在创建材质时,直接为它定义颜色属性。这个颜色属性是包含在material的parameter参数中,下面的例子中,材质中的颜色属性名称为color,然后在fragment shader也声明一个uniform变量:color,参与计算从而得到最终的颜色输出fragColor。

    const vs = `#version 300 es
#version 330 core

in vec2 positions;

void main()
{
gl_Position = vec4(positions, 0.0, 1.0);
}
`;

const fs = `#version 300 es
#version 330 core

out vec4 fragColor;
uniform vec3 color;

void main()
{
fragColor = vec4(color, 1.0);
}
`;
const material: JMaterial = {
program: {
// 指定了该材质的顶点着色器和面元着色器
vertex: vert(vs),
fragment: frag(fs)
},
parameters: {
// 指定了该材质的颜色
color: clr3(0.4, 0.6, 0.2)
},
states: {
// 打开了深度测试
depth: Depth({ enabled: true })
}
};

运行程序,可以看到下面这样的效果:

texture

颜色作为VBO

上面介绍的uniform color是程序与着色器之间进行数据交互的一类工具,但如果我们需要为每个顶点设置不同颜色,从而形成渐变效果的时候,就需要采用下面的方法了。

我们从之前的几何教程中,已经了解了如何利用VBO定义几何顶点位置,这里我们也利用VBO定义顶点颜色,比如下面这个例子中所做的。


const geometry: JGeometry = {
vertices: {
positions: Vertices({-0.5, -0.5, 0.5, -0.5, 0.0, 0.5}),
// 三个顶点分别是红、绿、蓝色
color: Vertices({1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0}),
},
indices: Triangles([0, 1, 2]),
boundingBox: bbox(-0.5, 0.5, -0.5, 0.5, 0.0, 0.0)
};

然后我们将顶点颜色数据发送到顶点着色器中,只要将它作为做一个顶点属性输入就行。

const vs = `#version 300 es
#version 330 core

in vec2 positions;
// Use the color VBO as an input variable
in vec3 colors;
// Define an output variable to pass to the fragment shader
out vec3 v_Color;

void main() {
gl_Position = vec4(positions, 0.0, 1.0);
v_Color = colors;
}`;

const fs = `#version 300 es
precision mediump float;

// Use the v_Color passed from the vertex shader instead of a uniform
in vec3 v_Color;
out vec4 fragColor;

void main() {
fragColor = vec4(v_Color, 1.0);
}`;

运行程序,我们可以看到下面的效果:

texture