hiccLoghicc log by wccHipo日志

Three.js中光源

toc

Intro

Three.js中光源

光源
THREE.AmbientLight基本光源,该光源的颜色会叠加到场景现有物体的颜色上
THREE.PointLight点光源,从空间上的一点向所有方向发射光线。点光源不能用来创建阴影(新版本支持了)
THREE.SpotLight这种光源有聚光的效果,类似台灯、吊灯或者手电筒。这种光源可以投射阴影
THREE.DirectionalLight无限光,从这种光源发出的光可以看作是平行的,就像太光,这种光源可以创建阴影
THREE.HemisphereLight一种特殊的光源,可以通过模拟反光面和光线微弱的太空来创建更加自然的室外光线。此光源不提供任何与阴影相关的功能
THREE.AreaLight使用这种光源可以指定散发光线的平面,而不是一个点。不投射任何阴影
THREE.LensFlare这不是一种光源,但是通过THREE.LensFlare为场景中的光源添加镜头光晕的效果

上述都是基于THREE.Light对象扩展.

基础光源

THREE.AmbientLight

创建AmbientLight很简单,一般和其他光源配合使用来产生阴影。

var ambientLight = new THREE.AmbientLight("#606008", 1); scene.add(ambientLight);
function init() { // use the defaults var stats = initStats(); var renderer = initRenderer(); var camera = initCamera(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); // add ambient lighting var ambientLight = new THREE.AmbientLight("#606008", 1); scene.add(ambientLight); // add spotlight for the shadows var spotLight = new THREE.SpotLight(0xffffff, 1, 180, Math.PI / 4); spotLight.shadow.mapSize.set(2048, 2048); spotLight.position.set(-30, 40, -10); spotLight.castShadow = true; scene.add(spotLight); // add a simple scene addHouseAndTree(scene) // add controls var controls = setupControls(); // call the render function render(); function render() { stats.update(); requestAnimationFrame(render); renderer.render(scene, camera); } function setupControls() { var controls = new function () { this.intensity = ambientLight.intensity; this.ambientColor = ambientLight.color.getStyle(); this.disableSpotlight = false; }; var gui = new dat.GUI(); gui.add(controls, 'intensity', 0, 3, 0.1).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; }); return controls; } }

THREE.SpotLight聚光灯

创建聚光灯SpotLight的经典步骤

var 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.target = plane; spotLight.distance = 0; spotLight.angle = 0.4; spotLight.shadow.camera.fov = 120;
function init() { // use the defaults var stats = initStats(); var renderer = initRenderer(); var camera = initCamera(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); var cubeAndSphere = addDefaultCubeAndSphere(scene); var cube = cubeAndSphere.cube; var sphere = cubeAndSphere.sphere; var plane = addGroundPlane(scene); // add subtle ambient lighting var ambiColor = "#1c1c1c"; var ambientLight = new THREE.AmbientLight(ambiColor); scene.add(ambientLight); // add spotlight for a bit of light var spotLight0 = new THREE.SpotLight(0xcccccc); spotLight0.position.set(-40, 30, -10); spotLight0.lookAt(plane); scene.add(spotLight0); // add target and light var target = new THREE.Object3D(); target.position = new THREE.Vector3(5, 0, 0); var 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.target = plane; spotLight.distance = 0; spotLight.angle = 0.4; spotLight.shadow.camera.fov = 120; scene.add(spotLight); var debugCamera = new THREE.CameraHelper(spotLight.shadow.camera); var pp = new THREE.SpotLightHelper(spotLight) scene.add(pp) // add a small sphere simulating the pointlight var sphereLight = new THREE.SphereGeometry(0.2); var sphereLightMaterial = new THREE.MeshBasicMaterial({ color: 0xac6c25 }); var sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial); sphereLightMesh.castShadow = true; sphereLightMesh.position = new THREE.Vector3(3, 20, 3); scene.add(sphereLightMesh); // for controlling the rendering var step = 0; var invert = 1; var phase = 0; var controls = setupControls(); render(); function render() { stats.update(); // rotate the cube around its axes cube.rotation.x += controls.rotationSpeed; cube.rotation.y += controls.rotationSpeed; cube.rotation.z += controls.rotationSpeed; // bounce the sphere up and down step += controls.bouncingSpeed; sphere.position.x = 20 + (10 * (Math.cos(step))); sphere.position.y = 2 + (10 * Math.abs(Math.sin(step))); // move the light simulation if (!controls.stopMovingLight) { if (phase > 2 * Math.PI) { invert = invert * -1; phase -= 2 * Math.PI; } else { phase += controls.rotationSpeed; } sphereLightMesh.position.z = +(7 * (Math.sin(phase))); sphereLightMesh.position.x = +(14 * (Math.cos(phase))); sphereLightMesh.position.y = 15; if (invert < 0) { var pivot = 14; sphereLightMesh.position.x = (invert * (sphereLightMesh.position.x - pivot)) + pivot; } spotLight.position.copy(sphereLightMesh.position); } pp.update(); // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } function setupControls() { var controls = new function () { this.rotationSpeed = 0.03; this.bouncingSpeed = 0.03; this.ambientColor = ambiColor; this.pointColor = spotLight.color.getStyle(); this.intensity = 1; this.distance = 0; this.angle = 0.1; this.shadowDebug = false; this.castShadow = true; this.target = "Plane"; this.stopMovingLight = false; this.penumbra = 0; }; var gui = new dat.GUI(); gui.addColor(controls, 'ambientColor').onChange(function (e) { ambientLight.color = new THREE.Color(e); }); gui.addColor(controls, 'pointColor').onChange(function (e) { spotLight.color = new THREE.Color(e); }); gui.add(controls, 'angle', 0, Math.PI * 2).onChange(function (e) { spotLight.angle = e; }); gui.add(controls, 'intensity', 0, 5).onChange(function (e) { spotLight.intensity = e; }); gui.add(controls, 'penumbra', 0, 1).onChange(function (e) { spotLight.penumbra = e; }); gui.add(controls, 'distance', 0, 200).onChange(function (e) { spotLight.distance = e; }); gui.add(controls, 'shadowDebug').onChange(function (e) { if (e) { scene.add(debugCamera); } else { scene.remove(debugCamera); } }); gui.add(controls, 'castShadow').onChange(function (e) { spotLight.castShadow = e; }); gui.add(controls, 'target', ['Plane', 'Sphere', 'Cube']).onChange(function (e) { switch (e) { case "Plane": spotLight.target = plane; break; case "Sphere": spotLight.target = sphere; break; case "Cube": spotLight.target = cube; break; } }); gui.add(controls, 'stopMovingLight').onChange(function (e) { stopMovingLight = e; }); return controls; } }

官方文档:https://threejs.org/docs/index.html#api/zh/lights/SpotLight

THREE.SpotLight 属性描述默认值
angle (角度)光源发射出的光束的宽度,单位是弧度Math.PI/3
catShadow (投影)如果设为true,光源会产生阴影
color (颜色)光源颜色
decay (衰减)光源强度随着离开光源的激励而衰减的速度。该值为2时更接近现实中的效果。只有当WebGLRenderer的属性physicallyCorrectLights(物理正确光源)被设置为启用时,才生效1
distance (距离)光源照射距离0 (意味着光线强度不会随着距离增加而减弱)
intensity (强度)光源照射的强度1
penumbra (半影区)设置聚光灯的锥形照明区域在其区域边缘附近的平滑衰减速度0
position (位置)光源在场景中的位置
power (功率)WebGLRenderer的属性physicallyCorrectLights(物理正确光源)被设置为启用时,可设置光源的功率,单位为流明4*Math.PI
target (目标)THREE.SpotLight 的指向很重要。指向场景中特定的对象或位置。需要一个THREE.Object3D对象(THREE.mesh)。
visible (是否可见)true时光源就会打开;false光源关闭

THREE.SpotLightshadowendable时:

THREE.SpotLight.shadow属性描述默认值
shadow.bias (阴影偏移)用来偏移阴影的位置。当你使用非常薄的对象时,可以用来解决奇怪的效果(将奇设置为更小的值,例如0.01)0
shadow.camera.far (投影远点)到距离光源的那一个位置可以产生阴影。 你可以设置所有提供给THREE.PerspectiveCamera的其他属性5000
shadow.camera.fov (投影视场)用于生成阴影的视场大小50
shadow.camera.near (投影近点)从距离光源的那一个位置可以产生阴影50
shadow.mapSize.widthshadow.mapSize.height (阴影映射宽高)决定了有多少像素用来生成阴影。当阴影有锯齿边缘,或者看起来不光滑的时候,可以增加这个值。在场景渲染之后无法更改512
shadow.radius (半径)当值大于1时,阴影的边缘将有平滑的效果。该属性在THREE.WebGIRenderershadowMap.type属性为Three.BasicShadowMap时无效

添加摄像机或者光源辅助线

如上述demo所示,开发3D时候,添加辅助线通常会很方便,也很有用

添加摄像机辅助线

var debugCamera = new THREE.CameraHelper(spotLight.shadow.camera); scene.add(debugCamera)

类似聚光灯也能添加辅助线,可以用来观察形状和朝向

var helper = new THREE.SpotLightHelper(spotLight) scene.add(helper) function render() { ... helper.update() ... }

THREE.PointLight点光源

function init() { // use the defaults var stats = initStats(); var renderer = initRenderer(); var camera = initCamera(); var trackballControls = initTrackballControls(camera, renderer); var clock = new THREE.Clock(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); // add a simple scene addHouseAndTree(scene) // add subtle ambient lighting var ambientLight = new THREE.AmbientLight("#0c0c0c"); scene.add(ambientLight); // the point light where working with var pointColor = "#ccffcc"; var pointLight = new THREE.PointLight(pointColor); pointLight.decay = 0.1 pointLight.castShadow = true; scene.add(pointLight); var helper = new THREE.PointLightHelper(pointLight); // scene.add(helper); var shadowHelper = new THREE.CameraHelper(pointLight.shadow.camera) // scene.add(shadowHelper) // add a small sphere simulating the pointlight var sphereLight = new THREE.SphereGeometry(0.2); var sphereLightMaterial = new THREE.MeshBasicMaterial({ color: 0xac6c25 }); var sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial); sphereLightMesh.position = new THREE.Vector3(3, 0, 5); scene.add(sphereLightMesh); // call the render function var step = 0; // used to determine the switch point for the light animation var invert = 1; var phase = 0; var controls = setupControls(); render(); function render() { helper.update(); shadowHelper.update(); stats.update(); pointLight.position.copy(sphereLightMesh.position); trackballControls.update(clock.getDelta()); // move the light simulation if (phase > 2 * Math.PI) { invert = invert * -1; phase -= 2 * Math.PI; } else { phase += controls.rotationSpeed; } sphereLightMesh.position.z = +(25 * (Math.sin(phase))); sphereLightMesh.position.x = +(14 * (Math.cos(phase))); sphereLightMesh.position.y = 5; if (invert < 0) { var pivot = 14; sphereLightMesh.position.x = (invert * (sphereLightMesh.position.x - pivot)) + pivot; } // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } function setupControls() { var controls = new function () { this.rotationSpeed = 0.01; this.bouncingSpeed = 0.03; this.ambientColor = ambientLight.color.getStyle();; this.pointColor = pointLight.color.getStyle();; this.intensity = 1; this.distance = pointLight.distance; }; var gui = new dat.GUI(); gui.addColor(controls, 'ambientColor').onChange(function (e) { ambientLight.color = new THREE.Color(e); }); gui.addColor(controls, 'pointColor').onChange(function (e) { pointLight.color = new THREE.Color(e); }); gui.add(controls, 'distance', 0, 100).onChange(function (e) { pointLight.distance = e; }); gui.add(controls, 'intensity', 0, 3).onChange(function (e) { pointLight.intensity = e; }); return controls; } }

官方文档:https://threejs.org/docs/index.html#api/zh/lights/PointLight

THREE.PointLight属性描述默认值
color光源颜色
distance (距离)光源着色的距离0(意味着光的强度不会随着距离增加而减少)
intensity (强度)光源照射的强度1
position (位置)光源在场景的位置
visible (是否可见)truefalse
decay (衰减)光源强度随着离开距离而衰减的速度。 2时接近现实世界中效果。当WebGLRenderer的属性physicallyCorrectLights(物理正确光源)被设置为启用时decay才有效。1
power (功率)WebGLRenderer的属性physicallyCorrectLights(物理正确光源)被设置为启用时,可设置光源的功率,单位为流明。该属性与intensity属性为简单的线性关系(power = instensity * 4 Math.PI)4*Math.PI

创建 THREE.PointLight点光源:

var pointColor = "#ccffcc"; var pointLight = new THREE.PointLight(pointColor); pointLight.decay = 0.1 pointLight.castShadow = true; scene.add(pointLight);

THREE.DirectionalLight平行光

function init() { // use the defaults var stats = initStats(); var renderer = initRenderer(); var camera = initCamera(); camera.position.set(-80, 80, 80); var trackballControls = initTrackballControls(camera, renderer); var clock = new THREE.Clock(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); // create the ground plane var planeGeometry = new THREE.PlaneGeometry(600, 200, 20, 20); var planeMaterial = new THREE.MeshLambertMaterial({ color: 0xffffff }); var plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.receiveShadow = true; // rotate and position the plane plane.rotation.x = -0.5 * Math.PI; plane.position.x = 15; plane.position.y = -5; plane.position.z = 0; // add the plane to the scene scene.add(plane); // create a cube var cubeGeometry = new THREE.BoxGeometry(4, 4, 4); var cubeMaterial = new THREE.MeshLambertMaterial({ color: 0xff3333 }); var cube = new THREE.Mesh(cubeGeometry, cubeMaterial); cube.castShadow = true; // position the cube cube.position.x = -4; cube.position.y = 3; cube.position.z = 0; // add the cube to the scene scene.add(cube); var sphereGeometry = new THREE.SphereGeometry(4, 20, 20); var sphereMaterial = new THREE.MeshLambertMaterial({ color: 0x7777ff }); var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); // position the sphere sphere.position.x = 20; sphere.position.y = 0; sphere.position.z = 2; sphere.castShadow = true; // add the sphere to the scene scene.add(sphere); // add subtle ambient lighting var ambiColor = "#1c1c1c"; var ambientLight = new THREE.AmbientLight(ambiColor); scene.add(ambientLight); var target = new THREE.Object3D(); target.position = new THREE.Vector3(5, 0, 0); var pointColor = "#ff5808"; var directionalLight = new THREE.DirectionalLight(pointColor); directionalLight.position.set(-40, 60, -10); directionalLight.castShadow = true; directionalLight.shadow.camera.near = 2; directionalLight.shadow.camera.far = 80; directionalLight.shadow.camera.left = -30; directionalLight.shadow.camera.right = 30; directionalLight.shadow.camera.top = 30; directionalLight.shadow.camera.bottom = -30; directionalLight.intensity = 0.5; directionalLight.shadow.mapSize.width = 1024; directionalLight.shadow.mapSize.height = 1024; scene.add(directionalLight); var shadowCamera = new THREE.CameraHelper(directionalLight.shadow.camera) // add a small sphere simulating the pointlight var sphereLight = new THREE.SphereGeometry(0.2); var sphereLightMaterial = new THREE.MeshBasicMaterial({ color: 0xac6c25 }); var sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial); sphereLightMesh.castShadow = true; sphereLightMesh.position = new THREE.Vector3(3, 20, 3); scene.add(sphereLightMesh); // call the render function var step = 0; var invert = 1; var phase = 0; var controls = new function () { this.rotationSpeed = 0.03; this.bouncingSpeed = 0.03; this.ambientColor = ambiColor; this.pointColor = pointColor; this.intensity = 0.5; this.debug = false; this.castShadow = true; this.onlyShadow = false; this.target = "Plane"; }; var gui = new dat.GUI(); gui.addColor(controls, 'ambientColor').onChange(function (e) { ambientLight.color = new THREE.Color(e); }); gui.addColor(controls, 'pointColor').onChange(function (e) { directionalLight.color = new THREE.Color(e); }); gui.add(controls, 'intensity', 0, 5).onChange(function (e) { directionalLight.intensity = e; }); gui.add(controls, 'debug').onChange(function (e) { e ? scene.add(shadowCamera) : scene.remove(shadowCamera); }); gui.add(controls, 'castShadow').onChange(function (e) { directionalLight.castShadow = e; }); gui.add(controls, 'onlyShadow').onChange(function (e) { directionalLight.onlyShadow = e; }); gui.add(controls, 'target', ['Plane', 'Sphere', 'Cube']).onChange(function (e) { console.log(e); switch (e) { case "Plane": directionalLight.target = plane; break; case "Sphere": directionalLight.target = sphere; break; case "Cube": directionalLight.target = cube; break; } }); render(); function render() { stats.update(); trackballControls.update(clock.getDelta()); // rotate the cube around its axes cube.rotation.x += controls.rotationSpeed; cube.rotation.y += controls.rotationSpeed; cube.rotation.z += controls.rotationSpeed; // bounce the sphere up and down step += controls.bouncingSpeed; sphere.position.x = 20 + (10 * (Math.cos(step))); sphere.position.y = 2 + (10 * Math.abs(Math.sin(step))); sphereLightMesh.position.z = -8; sphereLightMesh.position.y = +(27 * (Math.sin(step / 3))); sphereLightMesh.position.x = 10 + (26 * (Math.cos(step / 3))); directionalLight.position.copy(sphereLightMesh.position); // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } }

官网文档:https://threejs.org/docs/index.html#api/zh/lights/DirectionalLight

THREE.DirectionalLight平行光就类似太阳对于地球而言,光线是“平行”的。和THREE.SpotLight聚光灯等最大的区别是:平行光不会离目标越远越暗。

平行光形成的阴影不是光锥,而是立方体。和THREE.SpotLight一样,包围对象的空间定义越紧密,投影的效果约好。

可以这样调整阴影下效果:

directionalLight.castShadow = true; directionalLight.shadow.camera.near = 2; directionalLight.shadow.camera.far = 80; directionalLight.shadow.camera.left = -30; directionalLight.shadow.camera.right = 30; directionalLight.shadow.camera.top = 30; directionalLight.shadow.camera.bottom = -30;

特殊光源

THREE.HemisphereLight半球光光源

要模拟户外的效果可以通过设置THREE.DirectionalLight平行光模拟太阳配合THREE.AmbientLight给场景提供基础色。但是这样不太自然。因为大自然中光不只有上方的太阳光,更多的是大气的散射和地面以及其他物体的反射。THREE.HemisphereLight半球光光源就是来解决这个问题的。

官方文档:https://threejs.org/docs/index.html#api/zh/lights/HemisphereLight

function init() { var stats = initStats(); var renderer = initRenderer(); var camera = initCamera(); var trackballControls = initTrackballControls(camera, renderer); var clock = new THREE.Clock(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); // create the ground plane var textureGrass = new THREE.TextureLoader().load("/assets/threejs/assets/textures/ground/grasslight-big.jpg"); textureGrass.wrapS = THREE.RepeatWrapping; textureGrass.wrapT = THREE.RepeatWrapping; textureGrass.repeat.set(10, 10); var planeGeometry = new THREE.PlaneGeometry(1000, 1000, 20, 20); var planeMaterial = new THREE.MeshLambertMaterial({ map: textureGrass }); // var planeMaterial = new THREE.MeshLambertMaterial(); var plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.receiveShadow = true; // rotate and position the plane plane.rotation.x = -0.5 * Math.PI; plane.position.x = 15; plane.position.y = 0; plane.position.z = 0; // add the plane to the scene scene.add(plane); // create a cube var cubeGeometry = new THREE.BoxGeometry(4, 4, 4); var cubeMaterial = new THREE.MeshLambertMaterial({ color: 0xff3333 }); var cube = new THREE.Mesh(cubeGeometry, cubeMaterial); cube.castShadow = true; // position the cube cube.position.x = -4; cube.position.y = 3; cube.position.z = 0; // add the cube to the scene scene.add(cube); var sphereGeometry = new THREE.SphereGeometry(4, 25, 25); var sphereMaterial = new THREE.MeshPhongMaterial({ color: 0x7777ff }); var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); // position the sphere sphere.position.x = 10; sphere.position.y = 5; sphere.position.z = 10; sphere.castShadow = true; // add the sphere to the scene scene.add(sphere); // add spotlight for a bit of light var spotLight0 = new THREE.SpotLight(0xcccccc); spotLight0.position.set(-40, 60, -10); spotLight0.lookAt(plane); scene.add(spotLight0); var target = new THREE.Object3D(); target.position = new THREE.Vector3(5, 0, 0); var hemiLight = new THREE.HemisphereLight(0x0000ff, 0x00ff00, 0.6); hemiLight.position.set(0, 500, 0); scene.add(hemiLight); var pointColor = "#ffffff"; var dirLight = new THREE.DirectionalLight(pointColor); dirLight.position.set(30, 10, -50); dirLight.castShadow = true; dirLight.target = plane; dirLight.shadow.camera.near = 0.1; dirLight.shadow.camera.far = 200; dirLight.shadow.camera.left = -50; dirLight.shadow.camera.right = 50; dirLight.shadow.camera.top = 50; dirLight.shadow.camera.bottom = -50; dirLight.shadow.mapSize.width = 2048; dirLight.shadow.mapSize.height = 2048; scene.add(dirLight); // call the render function var step = 0; // used to determine the switch point for the light animation var invert = 1; var phase = 0; var controls = addControls(); render(); function render() { stats.update(); trackballControls.update(clock.getDelta()); // rotate the cube around its axes cube.rotation.x += controls.rotationSpeed; cube.rotation.y += controls.rotationSpeed; cube.rotation.z += controls.rotationSpeed; // bounce the sphere up and down step += controls.bouncingSpeed; sphere.position.x = 20 + (10 * (Math.cos(step))); sphere.position.y = 2 + (10 * Math.abs(Math.sin(step))); requestAnimationFrame(render); renderer.render(scene, camera); } function addControls() { var controls = new function () { this.rotationSpeed = 0.03; this.bouncingSpeed = 0.03; this.hemisphere = true; this.color = 0x0000ff; this.groundColor = 0x00ff00; this.intensity = 0.6; }; var gui = new dat.GUI(); gui.add(controls, 'hemisphere').onChange(function (e) { if (!e) { hemiLight.intensity = 0; } else { hemiLight.intensity = controls.intensity; } }); gui.addColor(controls, 'groundColor').onChange(function (e) { hemiLight.groundColor = new THREE.Color(e); }); gui.addColor(controls, 'color').onChange(function (e) { hemiLight.color = new THREE.Color(e); }); gui.add(controls, 'intensity', 0, 5).onChange(function (e) { hemiLight.intensity = e; }); return controls; } }

仔细观察,上述场景中球体表面底部有接近草地的绿色,而顶部有接近天空的蓝色(设置color).

创建THREE.HemisphereLight半球光光源:

var hemiLight = new THREE.HemisphereLight(0x0000ff, 0x00ff00, 0.6); hemiLight.position.set(0, 500, 0); scene.add(hemiLight);
THREE.HemisphereLight属性Column 2
groundColor从地面发出光线的颜色
color从天空发出的光线的颜色
intensity光线照射的强度

THREE.AreaLight区域光

function init() { var stats = initStats(); var renderer = initRenderer({ antialias: true }); var camera = initCamera(); camera.position.set(-50, 30, 50) // camera.lookAt(new THREE.Vector3(0, 0, -35)); var trackballControls = initTrackballControls(camera, renderer); var clock = new THREE.Clock(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); // create the ground plane var planeGeometry = new THREE.PlaneGeometry(70, 70, 1, 1); var planeMaterial = new THREE.MeshStandardMaterial({ roughness: 0.044676705160855, // calculated from shininess = 1000 metalness: 0.0 }); var plane = new THREE.Mesh(planeGeometry, planeMaterial); // plane.receiveShadow = true; // rotate and position the plane plane.rotation.x = -0.5 * Math.PI; plane.position.x = 0; plane.position.y = 0; plane.position.z = 0; // add the plane to the scene scene.add(plane); // call the render function var step = 0; var spotLight0 = new THREE.SpotLight(0xcccccc); spotLight0.position.set(-40, 60, -10); spotLight0.intensity = 0.1; spotLight0.lookAt(plane); scene.add(spotLight0); var areaLight1 = new THREE.RectAreaLight(0xff0000, 500, 4, 10); areaLight1.position.set(-10, 10, -35); scene.add(areaLight1); var areaLight2 = new THREE.RectAreaLight(0x00ff00, 500, 4, 10); areaLight2.position.set(0, 10, -35); scene.add(areaLight2); var areaLight3 = new THREE.RectAreaLight(0x0000ff, 500, 4, 10); areaLight3.position.set(10, 10, -35); scene.add(areaLight3); var planeGeometry1 = new THREE.BoxGeometry(4, 10, 0); var planeGeometry1Mat = new THREE.MeshBasicMaterial({ color: 0xff0000 }); var plane1 = new THREE.Mesh(planeGeometry1, planeGeometry1Mat); plane1.position.copy(areaLight1.position); scene.add(plane1); var planeGeometry2 = new THREE.BoxGeometry(4, 10, 0); var planeGeometry2Mat = new THREE.MeshBasicMaterial({ color: 0x00ff00, }); var plane2 = new THREE.Mesh(planeGeometry2, planeGeometry2Mat); plane2.position.copy(areaLight2.position); scene.add(plane2); var planeGeometry3 = new THREE.BoxGeometry(4, 10, 0); var planeGeometry3Mat = new THREE.MeshBasicMaterial({ color: 0x0000ff }); var plane3 = new THREE.Mesh(planeGeometry3, planeGeometry3Mat); plane3.position.copy(areaLight3.position); scene.add(plane3); var controls = new function () { this.rotationSpeed = 0.02; this.color1 = 0xff0000; this.intensity1 = 500; this.color2 = 0x00ff00; this.intensity2 = 500; this.color3 = 0x0000ff; this.intensity3 = 500; }; var gui = new dat.GUI(); gui.addColor(controls, 'color1').onChange(function (e) { areaLight1.color = new THREE.Color(e); planeGeometry1Mat.color = new THREE.Color(e); scene.remove(plane1); plane1 = new THREE.Mesh(planeGeometry1, planeGeometry1Mat); plane1.position.copy(areaLight1.position); scene.add(plane1); }); gui.add(controls, 'intensity1', 0, 1000).onChange(function (e) { areaLight1.intensity = e; }); gui.addColor(controls, 'color2').onChange(function (e) { areaLight2.color = new THREE.Color(e); planeGeometry2Mat.color = new THREE.Color(e); scene.remove(plane2); plane2 = new THREE.Mesh(planeGeometry2, planeGeometry2Mat); plane2.position.copy(areaLight2.position); scene.add(plane2); }); gui.add(controls, 'intensity2', 0, 1000).onChange(function (e) { areaLight2.intensity = e; }); gui.addColor(controls, 'color3').onChange(function (e) { areaLight3.color = new THREE.Color(e); planeGeometry3Mat.color = new THREE.Color(e); scene.remove(plane3); plane3 = new THREE.Mesh(planeGeometry1, planeGeometry3Mat); plane3.position.copy(areaLight3.position); scene.add(plane3); }); gui.add(controls, 'intensity3', 0, 1000).onChange(function (e) { areaLight3.intensity = e; }); render(); function render() { stats.update(); trackballControls.update(clock.getDelta()); // render using requestAnimationFrame requestAnimationFrame(render); renderer.render(scene, camera); } }

新版貌似改为THREE.RectAreaLighthttps://threejs.org/docs/index.html#api/zh/lights/RectAreaLight

Lensflare镜头光晕

创建镜头光晕效果。

官方文档:https://threejs.org/docs/index.html?q=lens#examples/zh/objects/Lensflare

function init() { var stats = initStats(); var renderer = initRenderer({ alpha: true }); var camera = initCamera(); camera.position.x = -20; camera.position.y = 10; camera.position.z = 45; camera.lookAt(new THREE.Vector3(10, 0, 0)); var trackballControls = initTrackballControls(camera, renderer); var clock = new THREE.Clock(); // create a scene, that will hold all our elements such as objects, cameras and lights. var scene = new THREE.Scene(); // create the ground plane var textureGrass = new THREE.TextureLoader().load("/assets/threejs/assets/textures/ground/grasslight-big.jpg"); textureGrass.wrapS = THREE.RepeatWrapping; textureGrass.wrapT = THREE.RepeatWrapping; textureGrass.repeat.set(10, 10); var planeGeometry = new THREE.PlaneGeometry(1000, 1000, 20, 20); var planeMaterial = new THREE.MeshLambertMaterial({ map: textureGrass }); var plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.receiveShadow = true; // rotate and position the plane plane.rotation.x = -0.5 * Math.PI; plane.position.x = 15; plane.position.y = 0; plane.position.z = 0; // add the plane to the scene scene.add(plane); // create a cube var cubeGeometry = new THREE.BoxGeometry(4, 4, 4); var cubeMaterial = new THREE.MeshLambertMaterial({ color: 0xff3333 }); var cube = new THREE.Mesh(cubeGeometry, cubeMaterial); cube.castShadow = true; // position the cube cube.position.x = -4; cube.position.y = 3; cube.position.z = 0; // add the cube to the scene scene.add(cube); var sphereGeometry = new THREE.SphereGeometry(4, 25, 25); var sphereMaterial = new THREE.MeshLambertMaterial({ color: 0x7777ff }); var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); // position the sphere sphere.position.x = 10; sphere.position.y = 5; sphere.position.z = 10; sphere.castShadow = true; // add the sphere to the scene scene.add(sphere); // add subtle ambient lighting var ambiColor = "#1c1c1c"; var ambientLight = new THREE.AmbientLight(ambiColor); scene.add(ambientLight); // add spotlight for a bit of light var spotLight0 = new THREE.SpotLight(0xcccccc); spotLight0.position.set(-40, 60, -10); spotLight0.lookAt(plane); scene.add(spotLight0); var target = new THREE.Object3D(); target.position = new THREE.Vector3(5, 0, 0); var pointColor = "#ffffff"; // var spotLight = new THREE.SpotLight( pointColor); var spotLight = new THREE.DirectionalLight(pointColor); spotLight.position.set(30, 10, -50); spotLight.castShadow = true; spotLight.shadowCameraNear = 0.1; spotLight.shadowCameraFar = 100; spotLight.shadowCameraFov = 50; spotLight.target = plane; spotLight.distance = 0; spotLight.shadowCameraNear = 2; spotLight.shadowCameraFar = 200; spotLight.shadowCameraLeft = -100; spotLight.shadowCameraRight = 100; spotLight.shadowCameraTop = 100; spotLight.shadowCameraBottom = -100; spotLight.shadowMapWidth = 2048; spotLight.shadowMapHeight = 2048; scene.add(spotLight); // call the render function var step = 0; // used to determine the switch point for the light animation var invert = 1; var phase = 0; var controls = new function () { this.rotationSpeed = 0.03; this.bouncingSpeed = 0.03; this.ambientColor = ambiColor; this.pointColor = pointColor; this.intensity = 0.1; this.distance = 0; this.exponent = 30; this.angle = 0.1; this.debug = false; this.castShadow = true; this.onlyShadow = false; this.target = "Plane"; }; var gui = new dat.GUI(); gui.addColor(controls, 'ambientColor').onChange(function (e) { ambientLight.color = new THREE.Color(e); }); gui.addColor(controls, 'pointColor').onChange(function (e) { spotLight.color = new THREE.Color(e); }); gui.add(controls, 'intensity', 0, 5).onChange(function (e) { spotLight.intensity = e; }); var textureFlare0 = THREE.ImageUtils.loadTexture("/assets/threejs/assets/textures/flares/lensflare0.png"); var textureFlare3 = THREE.ImageUtils.loadTexture("/assets/threejs/assets/textures/flares/lensflare3.png"); var flareColor = new THREE.Color(0xffaacc); var lensFlare = new THREE.Lensflare(); lensFlare.addElement(new THREE.LensflareElement(textureFlare0, 350, 0.0, flareColor)); lensFlare.addElement(new THREE.LensflareElement(textureFlare3, 60, 0.6, flareColor)); lensFlare.addElement(new THREE.LensflareElement(textureFlare3, 70, 0.7, flareColor)); lensFlare.addElement(new THREE.LensflareElement(textureFlare3, 120, 0.9, flareColor)); lensFlare.addElement(new THREE.LensflareElement(textureFlare3, 70, 1.0, flareColor)); spotLight.add(lensFlare); render(); function render() { stats.update(); trackballControls.update(clock.getDelta()); // rotate the cube around its axes cube.rotation.x += controls.rotationSpeed; cube.rotation.y += controls.rotationSpeed; cube.rotation.z += controls.rotationSpeed; // bounce the sphere up and down step += controls.bouncingSpeed; sphere.position.x = 20 + (10 * (Math.cos(step))); sphere.position.y = 2 + (10 * Math.abs(Math.sin(step))); requestAnimationFrame(render); renderer.render(scene, camera); } };

创建镜头光晕:

var lensFlare = new THREE.Lensflare(texture, size, distance, blending, color, opacity);
THREE.Lensflare参数描述
texture(纹理)纹理就是一个图片,决定光晕的形状
size指定光晕的尺寸,单位像素。如果-1,将使用纹理本身的尺寸
distance(距离)从光源(0)到摄像机(1)的距离。 使用这个属性,设置镜头光晕在正确的位置
blending(混合)可以为镜头光晕设置多个材质。混合模式决定混合方式。默认THREE.AdditiveBlending
color光晕的颜色
opacity光晕的透明度。 0完全透明,1完全不透明