光源 | |
---|---|
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);
show code
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;
show code
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.SpotLight
的shadow
为endable
时:
THREE.SpotLight.shadow属性 | 描述 | 默认值 |
---|---|---|
shadow.bias (阴影偏移) | 用来偏移阴影的位置。当你使用非常薄的对象时,可以用来解决奇怪的效果(将奇设置为更小的值,例如0.01) | 0 |
shadow.camera.far (投影远点) | 到距离光源的那一个位置可以产生阴影。 你可以设置所有提供给THREE.PerspectiveCamera的其他属性 | 5000 |
shadow.camera.fov (投影视场) | 用于生成阴影的视场大小 | 50 |
shadow.camera.near (投影近点) | 从距离光源的那一个位置可以产生阴影 | 50 |
shadow.mapSize.width 和shadow.mapSize.height (阴影映射宽高) | 决定了有多少像素用来生成阴影。当阴影有锯齿边缘,或者看起来不光滑的时候,可以增加这个值。在场景渲染之后无法更改 | 512 |
shadow.radius (半径) | 当值大于1时,阴影的边缘将有平滑的效果。该属性在THREE.WebGIRenderer的shadowMap.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
点光源show code
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 (是否可见) | true | false | |
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
平行光show code
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
show code
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
区域光show code
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.RectAreaLight
。https://threejs.org/docs/index.html#api/zh/lights/RectAreaLight
Lensflare
镜头光晕创建镜头光晕效果。
官方文档:https://threejs.org/docs/index.html?q=lens#examples/zh/objects/Lensflare
show code
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完全不透明 |