ThreeJS中的灯光
//遍历场景中的所有对象,然后判断当前对象是否是光源对象
function toggleLights( visible ) {
scene.traverse( function ( object ) {
if ( object.isLight ) {
object.visible = visible;
}
} );
render();
}
const shaderMaterial = new THREE.ShaderMaterial({
// 定义顶点着色器,用于处理顶点属性
vertexShader: `
precision lowp float;
// 传递顶点位置信息到片元着色器
varying vec4 vPosition;
// 传递变换后的顶点位置信息到片元着色器
varying vec4 gPosition;
void main(){
// 将顶点坐标从模型空间变换到世界空间
vec4 modelPosition = modelMatrix * vec4( position, 1.0 );
// 将变换后的顶点坐标从世界空间变换到相机空间
// 并传递给 varying vPosition
vPosition = modelPosition;
// 将顶点坐标从模型空间变换到世界空间
// 并传递给 varying gPosition
gPosition = vec4( position, 1.0 );
// 将顶点坐标从模型空间变换到相机空间和投影空间
gl_Position = projectionMatrix * viewMatrix * modelPosition;
}
`,
// 定义片元着色器,用于处理像素颜色
fragmentShader:`
precision lowp float;
// 接收来自顶点着色器的变量
varying vec4 vPosition;
varying vec4 gPosition;
void main(){
// 定义红色和黄色的颜色值
vec4 redColor = vec4(1,0,0,1);
vec4 yellowColor = vec4(1,1,0.5,1);
// 计算需要混合的颜色值,并传递给 gl_FragColor
vec4 mixColor = mix(yellowColor,redColor,gPosition.y/3.0);
if(gl_FrontFacing){
// 对于正面的面,计算并设置像素颜色
gl_FragColor = vec4(mixColor.xyz-(vPosition.y-20.0)/80.0-0.1,1);
}else{
// 对于背面的面,直接设置像素颜色
gl_FragColor = vec4(mixColor.xyz,1);
}
}
`,
// 传递给着色器的变量,这里为空对象
uniforms:{},
// 设置物体的两面都需要渲染
side:THREE.DoubleSide
})
const gltfLoader = new GLTFLoader()
let LightBox = null
gltfLoader.load("/assets/model/flyLight.glb",(gltf) => {
LightBox = gltf.scene.children[1]
LightBox.material = shaderMaterial;
for (let i = 0; i < 150; i++) {
let flyLight = gltf.scene.clone(true);
let x = (Math.random() - 0.5) * 300;
let z = (Math.random() - 0.5) * 300;
let y = Math.random() * 60 + 25;
flyLight.position.set(x, y, z);
gsap.to(flyLight.rotation, {
y: 2 * Math.PI,
duration: 10 + Math.random() * 30,
repeat: -1,
});
gsap.to(flyLight.position, {
x: "+=" + Math.random() * 5,
y: "+=" + Math.random() * 20,
yoyo: true,
duration: 5 + Math.random() * 10,
repeat: -1,
});
scene.add(flyLight);
}
})
function createLight(color) {
// 定义光源强度为2
const intensity = 2;
// 创建一个点光源
const light = new THREE.PointLight(color, intensity, 20);
// 开启阴影
light.castShadow = true;
// 减少双面对象自身阴影
light.shadow.bias = -0.005;
// 创建一个球体作为光源的可视化表示
let geometry = new THREE.SphereGeometry(0.3, 12, 6);
let material = new THREE.MeshBasicMaterial({
color: color
});
// 根据光源强度调整颜色
material.color.multiplyScalar(intensity);
let sphere = new THREE.Mesh(geometry, material);
// 将球体添加到光源上
light.add(sphere);
// 生成纹理
const texture = new THREE.CanvasTexture(generateTexture());
// 设置纹理过滤器和重复方式
texture.magFilter = THREE.NearestFilter;
texture.wrapT = THREE.RepeatWrapping;
texture.wrapS = THREE.RepeatWrapping;
texture.repeat.set(1, 4.5);
// 创建一个球体作为光源的光晕效果
geometry = new THREE.SphereGeometry(2, 32, 8);
material = new THREE.MeshPhongMaterial({
side: THREE.DoubleSide, // 双面显示
alphaMap: texture, // 设置透明度贴图
alphaTest: 0.5 // 设置透明度阈值
});
sphere = new THREE.Mesh(geometry, material);
// 开启球体阴影和接收阴影
sphere.castShadow = true;
sphere.receiveShadow = true;
// 将球体添加到光源上
light.add(sphere);
// 返回创建的光源
return light;
}
/**
* 生成一个 2x2 的纯白色 canvas 纹理
*/
function generateTexture() {
// 创建一个 canvas 元素,并设置它的宽高为 2
const canvas = document.createElement( 'canvas' );
canvas.width = 2;
canvas.height = 2;
// 获取 canvas 的绘制上下文,并将其填充为白色
const context = canvas.getContext( '2d' );
context.fillStyle = 'white';
context.fillRect( 0, 1, 2, 1 );
// 返回生成的纹理
return canvas;
}
Powered by Waline v2.13.0