前言
上一节实现了添加建筑物线框,模型外墙和道路地面材质添加。这一节准备通过简单的shader
实现上升线效果。
思路
简单的说一下思路,通过获取模型顶点坐标所在的高度Z来进行筛选,高度再某一区间内设置成上升线的颜色,其余高度颜色正常,把高度不断上升来让这根上升线不断上升,到一定高度后重置。
ShaderMaterial的组成
实现主要通关Three
内自定义材质(ShaderMaterial
)来实现,首先来实现一个最简单的ShaderMaterial
来看一下这个材质的组成。
const shader = new THREE.ShaderMaterial({
//从程序穿到着色器里面的值,这里先不传值
uniforms: {
},
//顶点着色器
vertexShader: `
void main()
{
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`,
//片段着色器
fragmentShader: `
void main()
{
gl_FragColor = vec4(1.0);
}`,
});
- 顶点着色器(
vertexShader
):首先来介绍一下顶点着色器,顶点着色器是用来处理顶点数据的,本例子中的顶点着色器主要代码就一句:
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
先来说一下每个变量的意思
-
position:模型点位数据。
-
modelViewMatrix:视图矩阵,等于camera.matrixWorldInverse * object.matrixWorld,就是模型矩阵和相机矩阵(视图矩阵)的乘积。
-
projectionMatrix:投影矩阵,等于camera.projectionMatrix。
-
gl_Position:矩阵变换后模型点位投影到屏幕上的位置,该值与position的关系如下图。
经过上述的矩阵变化,模型就会投影到裁剪坐标系然后经过一系列计算,显示到屏幕上。
- 片段着色器 (
fragmentShader
):片段着色器是片元的颜色,本例子中的顶点着色器如下:
gl_FragColor = vec4(1.0,1.0,1.0,1.0);
gl_FragColor是每个片段的颜色,这里统一设置成白色 vec4(1.0,1.0,1.0,1.0)
。
然后把这个材质赋给模型
//object.geometry是模型的geometry属性,shader是上面定义的材质
const city = new THREE.Mesh(object.geometry, shader);
//把重新生成的模型对象添加到场景里面
scene.add(city);
这里的显示效果:
所有的建筑模型显示白色。
上升线效果实现
- 这个效果的实现需要四个值:线上升到的高度
height
、上升线的颜色uFlowColor
、建筑模型的颜色uCityColor
、模型点位的高度值z(这个顶点着色器里面有,需要从顶点着色器传到片段着色器中),然后把这些值通过uniforms
传入到着色器里面去。着色器代码如下:
const shader = new THREE.ShaderMaterial({
uniforms: {
height: this.height,
uFlowColor: {
value: new THREE.Color("#5588aa"),
},
uCityColor: {
value: new THREE.Color("#FFFFDC"),
},
},
vertexShader: `
varying vec3 vPosition;
void main()
{
vPosition = position;
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
}`,
fragmentShader: `
varying vec3 vPosition;
uniform float height;
uniform float uStartTime;
uniform vec3 uSize;
uniform vec3 uFlow;
uniform vec3 uFlowColor;
uniform vec3 uCityColor;
void main()
{
//模型的基础颜色
vec3 distColor=uCityColor;
// 流动范围当前点z的高度加上流动线的高度
float topY = vPosition.z +5.0;
if (height > vPosition.z && height < topY) {
// 颜色渐变
distColor = uFlowColor;
}
gl_FragColor = vec4(distColor, 0.6);
}`,
transparent: true,
});
render添加如下代码
this.height.value += 0.03;
if(this.height.value>100)
{
this.height.value=0.0
}
首先说一下render中的代码,render是在每一次渲染中都会执行,在每一帧渲染时把height值逐渐增加,当height大于100的时候重置。
接下来是shader材质的定义,这里我们在uniforms中把需要的上升线的高度height
,上升线的颜色uFlowColor
,建筑模型的颜色uCityColor
进行了传入,然后在vertexShader
中把fragmentShader
需要的点位属vPosition
性通过varying
变量实现了两个着色器直接的共用,这样上升效果需要的变量就都齐全了。
在片段着色器中首先定义模型的基本颜色distColor
,然后定义流动颜色的位置float topY = vPosition.z +5.0
;vPosition.z
是当前点位的z值加上一个宽度就是模型需要着色的部位。下一步进行筛选,筛选点位高度在 vPosition.z-height
和 vPosition.z+0.5-height
之间的值进行着色。把这一块的颜色设置成上升片段的颜色(uFlowColor
).显示效果如下图:
项目地址: github.com/lixiaochjaj…