function
addLightWall() {
const geometry
=
new
THREE.BufferGeometry();
const vertices
=
new
Float32Array([
5, 0, 2
,
3, 0, 5
,
-2, 0, 5
,
-4, 0, 2
,
-4, 5, 2
,
-2, 5, 5
,
3, 5, 5
,
5, 5, 2
const indices
=
new
Uint16Array([
0, 1, 7
,
1, 6, 7
,
1, 2, 6
,
2, 5, 6
,
2, 3, 5
,
3, 4, 5
geometry.setAttribute(
'position',
new
THREE.BufferAttribute(vertices, 3
));
geometry.setIndex(
new
THREE.BufferAttribute(indices, 1
));
geometry.setAttribute(
'aHeight',
new
THREE.BufferAttribute(
new
Float32Array(
new
Array(geometry.getAttribute('position').count).fill(5.0)), 1
));
const uniforms
=
{
uTime: { value:
0.01
},
setShader(geometry, vertex, frag, [
0, 2.5, 0
], uniforms)
function
setShader(geometry, vertexShader, fragmentShader, position = [0, 0, 0], uniforms = {}, isLine =
false
) {
material
=
new
THREE.ShaderMaterial({
vertexShader: vertexShader,
fragmentShader: fragmentShader,
side: THREE.DoubleSide,
uniforms: uniforms,
transparent:
true
,
//
blending: THREE.AdditiveBlending, // 多个元素的颜色相互叠加,颜色可能会变亮,会叠加setClearColor设置的背景色
material.depthTest =
true
;
material.depthWrite
=
false
;
let planeMesh
=
new
THREE.Mesh(geometry, material);
if
(isLine) {
planeMesh
=
new
THREE.Points(geometry, material);
planeMesh.position.x
= position[0
];
planeMesh.position.y
= position[1
];
planeMesh.position.z
= position[2
];
scene.add(planeMesh);
自定义坐标
2. 圆柱体的光影墙
* 添加光影墙
function
addLightWall() {
const geometry
=
new
THREE.CylinderGeometry(3, 3, 5.0, 32, 32,
true
);
geometry.setAttribute(
'aHeight',
new
THREE.BufferAttribute(
new
Float32Array(
new
Array(geometry.getAttribute('position').count).fill(5.0)), 1
));
//
生成一个渐变色的光影墙
const vertex =
`
varying vec3 vPosition;
varying vec2 vUv;
varying
float
vHeight;
attribute
float
aHeight;
void
main() {
vHeight
=
aHeight;
vUv
=
uv;
vPosition
=
position;
gl_Position
= projectionMatrix * modelViewMatrix * vec4(position, 1.0
);
const frag
=
`
varying vec3 vPosition;
varying vec2 vUv;
varying
float
vHeight;
void
main() {
float
d = (vHeight - distance(vPosition, vec3(vPosition.x, -2.5, vPosition.z))) /
vHeight;
gl_FragColor
= vec4(0.0, 1.0, 1.0
, d);
const uniforms
=
{
uTime: { value:
0.01
},
setShader(geometry, vertex, frag, [
0, 2.5, 0
], uniforms)
function
setShader(geometry, vertexShader, fragmentShader, position = [0, 0, 0], uniforms = {}, isLine =
false
) {
material
=
new
THREE.ShaderMaterial({
vertexShader: vertexShader,
fragmentShader: fragmentShader,
side: THREE.DoubleSide,
uniforms: uniforms,
transparent:
true
,
//
blending: THREE.AdditiveBlending, // 多个元素的颜色相互叠加,颜色可能会变亮,会叠加setClearColor设置的背景色
material.depthTest
=
true
;
material.depthWrite
=
false
;
let planeMesh
=
new
THREE.Mesh(geometry, material);
if
(isLine) {
planeMesh
=
new
THREE.Points(geometry, material);
planeMesh.position.x
= position[0
];
planeMesh.position.y
= position[1
];
planeMesh.position.z
= position[2
];
scene.add(planeMesh);
圆柱体光影墙
3. 为圆柱体添加可移动的线圈
* 添加光影墙
function
addLightWall() {
const geometry
=
new
THREE.CylinderGeometry(3, 3, 5.0, 32, 32,
true
);
geometry.setAttribute(
'aHeight',
new
THREE.BufferAttribute(
new
Float32Array(
new
Array(geometry.getAttribute('position').count).fill(5.0)), 1
));
//
生成一个可以向上移动的墙体线
const vertex =
`
varying vec3 vPosition;
varying vec2 vUv;
varying
float
vHeight;
attribute
float
aHeight;
void
main() {
vHeight
=
aHeight;
vUv
=
uv;
vPosition
=
position;
gl_Position
= projectionMatrix * modelViewMatrix * vec4(position, 1.0
);
const frag
=
`
uniform
float
uTime;
varying vec3 vPosition;
varying vec2 vUv;
varying
float
vHeight;
void
main() {
float
dis = distance(vPosition, vec3(vPosition.x, -2.5
, vPosition.z));
float
highlightPos = mod(uTime * 5.0, vHeight) - 2.5
;
float
highlightDis = distance(vec3(vPosition.x, highlightPos, vPosition.z), vec3(vPosition.x, -2.5
, vPosition.z));
float
highlightOpa = (vHeight - highlightDis) /
vHeight;
float
opacity = (vHeight - dis) /
vHeight;
if
(abs(dis - highlightDis) < 0.05
) {
gl_FragColor
= vec4(0.04, 0.95, 0.95, highlightOpa + 0.2
);
}
else
{
gl_FragColor
= vec4(0.0, 1.0, 1.0
, opacity);
const uniforms
=
{
uTime: { value:
0.01
},
setShader(geometry, vertex, frag, [
0, 2.5, 0
], uniforms)
function
setShader(geometry, vertexShader, fragmentShader, position = [0, 0, 0], uniforms = {}, isLine =
false
) {
material
=
new
THREE.ShaderMaterial({
vertexShader: vertexShader,
fragmentShader: fragmentShader,
side: THREE.DoubleSide,
uniforms: uniforms,
transparent:
true
,
//
blending: THREE.AdditiveBlending, // 多个元素的颜色相互叠加,颜色可能会变亮,会叠加setClearColor设置的背景色
material.depthTest
=
true
;
material.depthWrite
=
false
;
let planeMesh
=
new
THREE.Mesh(geometry, material);
if
(isLine) {
planeMesh
=
new
THREE.Points(geometry, material);
planeMesh.position.x
= position[0
];
planeMesh.position.y
= position[1
];
planeMesh.position.z
= position[2
];
scene.add(planeMesh);
移动线圈光影墙
二、实现一个渐变色的波纹圆圈
1. 实现一个固定的渐变色圆圈
1) UV点的范围是[0, 1],所以各个像素点距离圆心的距离范围是0~0.5,如果乘以2刚好是透明度的范围(0~1),这样就可以实现一个简单的渐变圆
2) 假设厚度为t,那么颜色的透明度的范围是[1, 1-t],而我们实际需要的是[1, 0],可以用图二来表示两个线性关系,可以得到两个方程式
方程式1:y = -x + 1;
方程式2:y = -t + 1;
现在我们知道方程式二中的y的值(像素点到中心的距离distance),通过解方程式就可以得到方程式1中所对应的透明度的值为 (distance - 1) / t + 1;
void
main() {
vUv
=
uv;
gl_Position
= projectionMatrix * modelViewMatrix * vec4(position, 1.0
);
const frag
=
`
uniform
float
uTime;
uniform
float
uThickness;
varying vec2 vUv;
void
main() {
//
使用UV坐标计算各个点到中心点的距离,需要减0.5,将圆心移动到(0.5, 0.5)的位置,半径为0.5,透明度范围为0~1,所以需要乘以2
float
distance = length(vUv - 0.5) * 2.0
;
float
opacity = (distance - 1.0) / uThickness + 1.0
;
gl_FragColor
= vec4(0.0, 1.0, 1.0
, opacity);
const uniforms
=
{
uThickness: { value:
0.8, range: [0, 1] },
//
渐变色的厚度
uSpeed: { value: 0.5, range: [0, 5
] },
uTime: { value:
0.01
},
setGui(uniforms);
setShader(geometry, vertex, frag, [
0,0,0
], uniforms);
function
setShader(geometry, vertexShader, fragmentShader, position = [0, 0, 0], uniforms = {}, isLine =
false
) {
material
=
new
THREE.ShaderMaterial({
vertexShader: vertexShader,
fragmentShader: fragmentShader,
side: THREE.DoubleSide,
uniforms: uniforms,
transparent:
true
,
//
blending: THREE.AdditiveBlending, // 多个元素的颜色相互叠加,颜色可能会变亮,会叠加setClearColor设置的背景色
material.depthTest =
true
;
material.depthWrite
=
false
;
let planeMesh
=
new
THREE.Mesh(geometry, material);
if
(isLine) {
planeMesh
=
new
THREE.Points(geometry, material);
planeMesh.position.x
= position[0
];
planeMesh.position.y
= position[1
];
planeMesh.position.z
= position[2
];
planeMesh.rotateX(Math.PI
/ 2
);
scene.add(planeMesh);
厚度可变的渐变圆
2. 半径自动缩放的渐变圆
* 添加一个扩散面
function
addDiffuseCircle() {
const geometry
=
new
THREE.CircleGeometry(3, 48
);
//
创建一个大小可控的渐变圆弧
const vertex =
`
varying vec2 vUv;
void
main() {
vUv
=
uv;
gl_Position
= projectionMatrix * modelViewMatrix * vec4(position, 1.0
);
const frag
=
`
uniform
float
uTime;
uniform
float
uThickness;
uniform
float
uSpeed;
varying vec2 vUv;
void
main() {
//
使用UV坐标计算各个点到中心点的距离,需要减0.5,将圆心移动到(0.5, 0.5)的位置,半径为0.5,透明度范围为0~1,所以需要乘以2
//
假设从内像外开始扩散,距离和时间关系是 最内部: 距离0,时间0;最外部:距离1,时间1,如果用1-时间的话,
//
所以此时1-时间+距离和样例1中的透明度相同
float
timeDis = fract(uTime *
uSpeed);
float
distance = length(vUv - 0.5) * 2.0
;
if
(timeDis <
distance) {
gl_FragColor
= vec4(0.0, 0.0, 1.0, 0.0
);
}
else
{
float
opacity = (1.0 - timeDis + distance - 1.0) / uThickness + 1.0
;
gl_FragColor
= vec4(0.0, 1.0, 1.0
, opacity);
const uniforms
=
{
uThickness: { value:
0.8, range: [0, 1] },
//
渐变色的厚度
uSpeed: { value: 0.5, range: [0, 5
] },
uTime: { value:
0.01
},
setShader(geometry, vertex, frag, [
0,0,0
], uniforms);
function
setShader(geometry, vertexShader, fragmentShader, position = [0, 0, 0], uniforms = {}, isLine =
false
) {
material
=
new
THREE.ShaderMaterial({
vertexShader: vertexShader,
fragmentShader: fragmentShader,
side: THREE.DoubleSide,
uniforms: uniforms,
transparent:
true
,
//
blending: THREE.AdditiveBlending, // 多个元素的颜色相互叠加,颜色可能会变亮,会叠加setClearColor设置的背景色
material.depthTest
=
true
;
material.depthWrite
=
false
;
let planeMesh
=
new
THREE.Mesh(geometry, material);
if
(isLine) {
planeMesh
=
new
THREE.Points(geometry, material);
planeMesh.position.x
= position[0
];
planeMesh.position.y
= position[1
];
planeMesh.position.z
= position[2
];
planeMesh.rotateX(Math.PI
/ 2
);
scene.add(planeMesh);
自动缩放的渐变圆