前言:
WebGL本身不支持光源,不使用three.js,则需使用着色程序来模拟光源。
学习大纲:
Three.js中的光源
特定光源的使用时机
如何调整和配置所有光源的行为
如何创建镜头光晕
光源表
基础光源:THRER.AmbientLight、THERE.PointLight、THERE.SpotLight
特殊光源和效果:THERE.HemisphereLight、THERE.AreaLight和LensFlare
基础光源
THREE.AmbientLight-环境光
特点:1、颜色运用至全局;2、光源无特定来源方向;3、不产生光照阴影 4、将所有物体无论形状渲染成一种颜色(故不能使用为唯一光照)
注意:使用环境光用色需保守些,不然画面颜色会过于饱和。
var ambientLight = new THREE.AmbientLight("#606008");
scene.add(ambientLight);
// 添加控制变量
var controls = new function(){
this.intensity = ambientLight.intensity;
this.ambientColor = ambientLight.color.getStyle();
this.disableSpotlight = false;
}
var gui = new GUI();
// 添加环境光强度控制
gui.add(controls,'intensity').onChange(function(e){
ambientLight.color = new THREE.Color(controls.ambientColor);
ambientLight.intensity = controls.intensity;
});
// 添加环境光颜色控制
gui.addColor(controls,'ambientColor').onChange(function(e){
ambientLight.color = new THREE.Color(controls.ambientColor);
ambientLight.intensity = controls.intensity;
});
// 添加开关控制是否显示聚光灯
gui.add(controls,'disableSpotlight').onChange(function(e){
spotLight.visible = !e;
});
THREE.SpotLight-聚光灯
特点:1、锥型光源 2、具有角度和方向
// 聚光灯
const spotLight = new THREE.SpotLight("#ffffff");
spotLight.position.set(-40, 60, -10);
spotLight.castShadow = true;
spotLight.shadow.camera.near = 1;
spotLight.shadow.camera.far = 100;
spotLight.shadow.camera.fov = 120; // 设置阴影相机的视场角
spotLight.angle = 0.4
spotLight.intensity = 5; // 聚光灯强度
spotLight.target = cube; // 设置聚光灯的目标
spotLight.distance = 0; // 距离
spotLight.decay = 0.06; // 衰减
scene.add(spotLight);
当开启shadow enable时,可以调整其shadow属性
说明:spotLight可以指定某一确定物体,可以为scene中存在的也可以根据目标空间点选取创建;
// 创建空间对象
var target = new THREE.Object3D();
// target.position.set(5, 0, 0);
target.position = new THREE.Vector3(5, 0, 0);
scene.add(target);
可以用其属性angle定义光锥角度,distance定义光锥长度,penumbra设置光强从光锥中心向边缘递减的速度。
THERE.SpotLight对象设置castShadow为true生成阴影;
scene中渲染THERE.Mesh对象要确保投射阴影对象设置castShadow属性,为要显示阴影的对象设置receiveShadow属性。
var helper = new THREE.SpotLightHelper(spotLight);
scene.add(helper);
var debugCamera = new THREE.CameraHelper(spotLight.shadow.camera);
scene.add(debugCamera);
// 创建鼠标控制器
let mouseControls = new OrbitControls(camera, renderer.domElement);
// 监听控制器,每次拖动后重新渲染画面
mouseControls.addEventListener('change', function(){
renderer.render(scene, camera);
});
render();
function render() {
stats.update();
helper.update();
注意:
如果在场景中使用薄对象,在渲染阴影时可能出现奇怪的渲染失真,可用bias属性轻微偏移来修复;
如果想使阴影更加柔和,使用THREE.WebGLRenderer设置为PCFShadowMap
THREE.PointLight-点光源
单点发光照射所有方向
属性:
power和decay属性对于模拟现实世界十分有效。
distance决定了光强度减为0前的距离。
也可使用THREE.CameraHelper 及THREE.PointLightHelper来展示光线
// 平行光
var directionalLight = new THREE.DirectionalLight("#ffffff", 0.1);
directionalLight.castShadow = true;
directionalLight.shadow.camera.near = 2;
directionalLight.shadow.camera.far = 100;
directionalLight.shadow.camera.left = -50;
directionalLight.shadow.camera.right = 50;
directionalLight.shadow.camera.top = 50;
directionalLight.shadow.camera.bottom = -50;
directionalLight.position.set(30, 10, -50);
scene.add(directionalLight);
THERE.DirectionalLight-平行光
特点:所有光线相互平行-eg:太阳光
// 点光源
var pointColor = "#ccffcc";
var pointLight = new THREE.PointLight(pointColor);
pointLight.distance = 100;
scene.add(pointLight);
特殊光源和效果
THREE.HemisphereLight-半球光光源
户外更自然的光照,更多模拟大气散射和地面以及其他物体的反射
const light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 1 ); scene.add( light );
THREE.RectAreaLight-区域光光源
从很大的区域发射光线,而不是单个点
不在标准库而在扩展库中,需要导入RectAreaLightUniformLib.js
const width = 10;
const height = 10;
const intensity = 1;
const rectLight = new THREE.RectAreaLight( 0xffffff, intensity, width, height );
rectLight.position.set( 5, 5, 0 );
rectLight.lookAt( 0, 0, 0 );
scene.add( rectLight )
const rectLightHelper = new RectAreaLightHelper( rectLight );
rectLight.add( rectLightHelper );
LensFlare - 镜头光晕
import { Lensflare } from 'three/addons/objects/Lensflare.js';
blending混合,混合模式决定我们将如何将他们混合在一起,默认混合方式为THREE.AddtiveBlending
color 光晕的颜色。
opacity 不透明度,0完全透明。
如下使用add方法添加,还可以添加color颜色和opacity透明度。
// 光晕
var textureFlare3 = new THREE.ImageUtils.loadTexture('./assets/lensflare0_alpha.png');
lensFare.add(textureFlare3,60,0.6,THREE.AdditiveBlending);
lensFare.add(textureFlare3,70,0.7,THREE.AdditiveBlending);
lensFare.add(textureFlare3,80,0.7,THREE.AdditiveBlending);
转换:
主要讲一下笔者将html的three应用转成vue3,反之亦然。
1、注意自己的导入方法名,html中的new dat.GUI ,但vue3中为
import { GUI } from 'three/examples/jsm/libs/lil-gui.module.min.js';
使用时直接new GUI便可添加图形化调试器
2、注意html可以直接操作dom,vue不可以,所以实例化一个全局变量,来为其原型链上挂载元素
html
// 将渲染器添加到dom
document.getElementById('webgl-output').appendChild(renderer.domElement);
vue
const webglOutput = ref(null);
webglOutput.value.appendChild(renderer.domElement);
3、注意上述的全局变量是否是响应式数据ref,记得添加value,再使用方法appendChildren。