认识光源.

,光源基类

在Threejs中,光源用Light表示,它是所有光源的基类。它的构造函数是:
THREE.Light (color)
它有一个参数color,接受一个16进制的颜色值。例如要定义一种红色的光源,我们可以这样来定义:
Var light = new THREE.Light(0xFF0000);


由基类派生出来的其他种类光源

THREE.Light只是其他所有光源的基类,要让光源除了具有颜色的特性之外,我们需要其他光源。看看,下面的类图,是目前光源的继承结构。

环境光

经过多次反射而来的光称为环境光(或者也可以这么说:无法确定光最初的方向的光就叫环境光。比如阴天的时候没有太阳,你无法确定光是从哪里照射出来的。)

环境光的颜色会影响整个场景,并且其光线没有特定的来源,所以你无须指定它的位置。在使用其它光源的同时使用环境光,目的是弱化阴影或添加一些颜色。


环境光用THREE.AmbientLight来表示,它的构造函数如下所示:
AmbientLight( color,intensity )
color: 光的颜色
intensity  : 光的强度,默认是1.0,就是说是100%强度的灯光

例子 :

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        body{padding: 0; margin: 0; overflow: hidden;}
    </style>
    <title>环境光</title> 
</head>
<body>  
	<div id="WebGL-output"></div> 
</body>
<script src='three.js'></script>
<script src='dat.gui.js'></script>
<script>
		
	var scene = new THREE.Scene();   
	var axes = new THREE.AxisHelper(100);  
	scene.add(axes);  
	var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);    
	camera.position.set(-8,8,20);  
	camera.lookAt(scene.position);  
	var renderer = new THREE.WebGLRenderer();   
	renderer.setSize(window.innerWidth, window.innerHeight);  
	renderer.setClearColor('#fff');
	document.body.appendChild(renderer.domElement);  

	//矩形
	var mshFloor = new THREE.Mesh( new THREE.CubeGeometry( 2000, 1, 2000 ), new THREE.MeshPhongMaterial());
	mshFloor.position.set( 0, -1, 0 );
	scene.add(mshFloor)

	//立方体   
	var cube = new THREE.Mesh(new THREE.CubeGeometry(1,2,3), new THREE.MeshLambertMaterial({  
	    color : 0x7777ff 
	})); 
	cube.position.set(0,0.5,0); 
	scene.add(cube); 

	//环境光
	var light = new THREE.AmbientLight(0xffffff);
	light.position.set( 0, 5, 0 );
    scene.add(light);

    //小球,它的位置就是光源的位置
	var sphereLight = new THREE.SphereGeometry(0.2);
    var sphereLightMaterial = new THREE.MeshBasicMaterial({color: 0xac6c25});
    var sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial);
    sphereLightMesh.position.set(light.position.x, light.position.y, light.position.z);
    scene.add(sphereLightMesh);

    //GUI
    var controls = new function(){
    	this.color = light.color.getHex();
    	this.intensity = light.intensity;
    	this.light_x = light.position.x;
    	this.light_y = light.position.y;
    	this.light_z = light.position.z;
    }
    var gui = new dat.GUI();
	gui.addColor(controls, 'color').onChange(function (e) {
	    light.color = new THREE.Color(e);
	});
	gui.add(controls, 'intensity', 0,1).onChange(function (e) {
	    light.intensity = e;
	});
	gui.add(controls, 'light_x', -50,50).onChange(function (e) {
	    light.position.x = e;
	    sphereLightMesh.position.x = e;
	});
	gui.add(controls, 'light_y', -50,50).onChange(function (e) {
	    light.position.y = e;
	    sphereLightMesh.position.y = e;
	});
	gui.add(controls, 'light_z', -50,50).onChange(function (e) {
	    light.position.z = e;
	    sphereLightMesh.position.z = e;
	});

	//更新函数
	function updata(){ 
	    cube.rotation.y +=0.01;  
	    axes.rotation.y +=0.01; 
	    mshFloor.rotation.y +=0.01; 
	    renderer.render(scene, camera);  
	    requestAnimationFrame(updata);  
	}  
	updata();  

	//窗口事件
	window.onresize = function(){
		renderer.setSize(window.innerWidth, window.innerHeight);  
	}

</script>
</html>

效果图:


从上面的例子可以看出,光的位置对环境光是没有影响的。



点光源

点光源是一种单点发光并照射所有方向的光源。比如夜空中的照明灯。

点光源用PointLight来表示,它的构造函数如下所示:

PointLight( color, intensity, distance,decay)
color:光的颜色
intensity:光的强度,默认是1.0,就是说是100%强度的灯光
distance:光能照射到的最远的距离。
decay : 值为0~1. 此值越大,光的衰减程度越多。

例子 :

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        body{padding: 0; margin: 0; overflow: hidden;}
    </style>
    <title>点光源</title> 
</head>
<body>  
	<div id="WebGL-output"></div> 
</body>
<script src='three.js'></script>
<script src='dat.gui.js'></script>
<script>
		
	var scene = new THREE.Scene();   
	var axes = new THREE.AxisHelper(100);  
	scene.add(axes);  
	var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);    
	camera.position.set(-8,8,20);  
	camera.lookAt(scene.position);  
	var renderer = new THREE.WebGLRenderer();   
	renderer.setSize(window.innerWidth, window.innerHeight);  
	renderer.setClearColor('#fff');
	document.body.appendChild(renderer.domElement);  

	//矩形
	var mshFloor = new THREE.Mesh( new THREE.CubeGeometry( 2000, 1, 2000 ), new THREE.MeshPhongMaterial());
	mshFloor.position.set( 0, -1, 0 );
	scene.add(mshFloor)

	//立方体   
	var cube = new THREE.Mesh(new THREE.CubeGeometry(1,2,3), new THREE.MeshLambertMaterial({  
	    color : 0x7777ff 
	})); 
	cube.position.set(0,0.5,0); 
	scene.add(cube); 

	//点光源
	var light = new THREE.PointLight(0xffffff, 1, 1000);
	light.position.set( 0, 5, 0 );
    scene.add(light);

    //小球,它的位置就是光源的位置
	var sphereLight = new THREE.SphereGeometry(0.2);
    var sphereLightMaterial = new THREE.MeshBasicMaterial({color: 0xac6c25});
    var sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial);
    sphereLightMesh.position.set(light.position.x, light.position.y, light.position.z);
    scene.add(sphereLightMesh);

    //GUI
    var controls = new function(){
    	this.color = light.color.getHex();
    	this.intensity = light.intensity;
    	this.distance = light.distance;	
    	this.light_x = light.position.x;
    	this.light_y = light.position.y;
    	this.light_z = light.position.z;
    }
    var gui = new dat.GUI();
	gui.addColor(controls, 'color').onChange(function (e) {
	    light.color = new THREE.Color(e);
	});
	gui.add(controls, 'intensity', 0,1).onChange(function (e) {
	    light.intensity = e;
	});
	gui.add(controls, 'distance', 0,1000).onChange(function (e) {
	    light.distance = e;
	});
	gui.add(controls, 'light_x', -50,50).onChange(function (e) {
	    light.position.x = e;
	    sphereLightMesh.position.x = e;
	});
	gui.add(controls, 'light_y', -50,50).onChange(function (e) {
	    light.position.y = e;
	    sphereLightMesh.position.y = e;
	});
	gui.add(controls, 'light_z', -50,50).onChange(function (e) {
	    light.position.z = e;
	    sphereLightMesh.position.z = e;
	});

	//更新函数
	function updata(){ 
	    cube.rotation.y +=0.01;  
	    axes.rotation.y +=0.01; 
	    mshFloor.rotation.y +=0.01; 
	    renderer.render(scene, camera);  
	    requestAnimationFrame(updata);  
	}  
	updata();  

	//窗口事件
	window.onresize = function(){
		renderer.setSize(window.innerWidth, window.innerHeight);  
	}

</script>
</html>


效果图:



聚光灯

聚光灯有一种锥形的效果。比如手电筒发射出来的光。


聚光灯用SpotLight来表示,它的构造函数如下所示:
SpotLight( color, intensity, distance, angle, penumbra, decay)
color:光的颜色
intensity:光的强度,默认是1.0,就是说是100%强度的灯光
distance:光能照射到的最远的距离。
angle : 椎体的角度
penumbra : 羽化程度
decay : 值为0~1. 此值越大,光的衰减程度越多。

例子:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        body{padding: 0; margin: 0; overflow: hidden;}
    </style>
    <title>聚光灯</title> 
</head>
<body>  
	<div id="WebGL-output"></div> 
</body>
<script src='three.js'></script>
<script src='dat.gui.js'></script>
<script>
		
	var scene = new THREE.Scene();   
	var axes = new THREE.AxisHelper(100);  
	scene.add(axes);  
	var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);    
	camera.position.set(-8,8,20);  
	camera.lookAt(scene.position);  
	var renderer = new THREE.WebGLRenderer();   
	renderer.setSize(window.innerWidth, window.innerHeight);  
	renderer.setClearColor('#fff');
	renderer.shadowMapEnabled = true;
	document.body.appendChild(renderer.domElement);  

	//矩形
	var mshFloor = new THREE.Mesh( new THREE.CubeGeometry( 2000, 1, 2000 ), new THREE.MeshPhongMaterial());
	mshFloor.receiveShadow = true;
	mshFloor.position.set( 0, -1, 0 );
	scene.add(mshFloor)

	//立方体   
	var cube = new THREE.Mesh(new THREE.CubeGeometry(1,2,3), new THREE.MeshLambertMaterial({  
	    color : 0x7777ff 
	})); 
	cube.position.set(0,0.5,0); 
	cube.castShadow = true;
	scene.add(cube); 

	//聚光灯
	var light = new THREE.SpotLight(0xffffff, 1, 1000, 1);
	light.position.set( 0, 5, 0 );
	light.castShadow = true;
	light.shadowMapWidth = 2048;	//阴影的宽度用多少像素绘制
	light.shadowMapHeight = 2048;	//阴影的高度用多少像素绘制
    scene.add(light);

    //小球,它的位置就是光源的位置
	var sphereLight = new THREE.SphereGeometry(0.2);
    var sphereLightMaterial = new THREE.MeshBasicMaterial({color: 0xac6c25});
    var sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial);
    sphereLightMesh.position.set(light.position.x, light.position.y, light.position.z);
    scene.add(sphereLightMesh);

    //辅助线,帮助我们看到聚光灯angle的变化
    var lightHelper = new THREE.SpotLightHelper( light );
    scene.add( lightHelper );

    //GUI
    var controls = new function(){
    	this.color = light.color.getHex();
    	this.intensity = light.intensity;
    	this.distance = light.distance;
    	this.angle = light.angle;	
    	this.penumbra = 1;  //聚光灯的模糊度
    	this.light_x = light.position.x;
    	this.light_y = light.position.y;
    	this.light_z = light.position.z;
    }
    var gui = new dat.GUI();
	gui.addColor(controls, 'color').onChange(function (e) {
	    light.color = new THREE.Color(e);
	});
	gui.add(controls, 'intensity', 0,1).onChange(function (e) {
	    light.intensity = e;
	});
	gui.add(controls, 'distance', 0,1000).onChange(function (e) {
	    light.distance = e;
	});
    gui.add(controls, 'angle', 0,1).onChange(function (e) {
	    light.angle = e; 
	    lightHelper.update();
	});
	gui.add(controls, 'penumbra', 0,1).onChange(function (e) {
	    light.penumbra = e;
	});
	gui.add(controls, 'light_x', -50,50).onChange(function (e) {
	    light.position.x = e;
	    sphereLightMesh.position.x = e;
	    lightHelper.update();
	});
	gui.add(controls, 'light_y', -50,50).onChange(function (e) {
	    light.position.y = e;
	    sphereLightMesh.position.y = e;
	    lightHelper.update();
	});
	gui.add(controls, 'light_z', -50,50).onChange(function (e) {
	    light.position.z = e;
	    sphereLightMesh.position.z = e;
	    lightHelper.update();
	});

	//更新函数
	function updata(){ 
	    cube.rotation.y +=0.01;  
	    axes.rotation.y +=0.01; 
	    mshFloor.rotation.y +=0.01; 
	    renderer.render(scene, camera);  
	    requestAnimationFrame(updata);  
	}  
	updata();  

	//窗口事件
	window.onresize = function(){
		renderer.setSize(window.innerWidth, window.innerHeight);  
	}

</script>
</html>


效果图:



方向光

方向光可以看作是距离很远的光源,比如太阳光。被方向光照亮的整个区域接收到的光的强度是一样的。你可以用方向光来模拟晚上到早上的过渡效果。

方向光用DirectionalLight来表示,它的构造函数如下所示:

DirectionalLight(color, intensity)
color :颜色
intensity :光的强度,默认是1.0,就是说是100%强度的灯光

例子:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        body{padding: 0; margin: 0; overflow: hidden;}
    </style>
    <title>方向光</title> 
</head>
<body>  
	<div id="WebGL-output"></div> 
</body>
<script src='three.js'></script>
<script src='dat.gui.js'></script>
<script>
		
	var scene = new THREE.Scene();   
	var axes = new THREE.AxisHelper(100);  
	scene.add(axes);  
	var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);    
	camera.position.set(-8,8,20);  
	camera.lookAt(scene.position);  
	var renderer = new THREE.WebGLRenderer();   
	renderer.setSize(window.innerWidth, window.innerHeight);  
	renderer.setClearColor('#fff');
	renderer.shadowMapEnabled = true;
	document.body.appendChild(renderer.domElement);  

	//矩形
	var mshFloor = new THREE.Mesh( new THREE.CubeGeometry( 2000, 1, 2000 ), new THREE.MeshPhongMaterial());
	mshFloor.position.set( 0, -1, 0 );
	mshFloor.receiveShadow = true;
	scene.add(mshFloor)

	//立方体   
	var cube = new THREE.Mesh(new THREE.CubeGeometry(1,2,3), new THREE.MeshLambertMaterial({  
	    color : 0x7777ff 
	})); 
	cube.position.set(0,0.5,0);
	cube.castShadow = true; 
	scene.add(cube); 

	//方向光
	var light = new THREE.DirectionalLight (0xffffff, 0.5);
	light.castShadow = true;
	light.position.set( 0, 5, 0 );
    scene.add(light);

    //小球,它的位置就是光源的位置
	var sphereLight = new THREE.SphereGeometry(0.2);
    var sphereLightMaterial = new THREE.MeshBasicMaterial({color: 0xac6c25});
    var sphereLightMesh = new THREE.Mesh(sphereLight, sphereLightMaterial);
    sphereLightMesh.position.set(light.position.x, light.position.y, light.position.z);
    scene.add(sphereLightMesh);

    //GUI
    var controls = new function(){
    	this.color = light.color.getHex();
    	this.intensity = light.intensity;
    	this.light_x = light.position.x;
    	this.light_y = light.position.y;
    	this.light_z = light.position.z;
    }
    var gui = new dat.GUI();
	gui.addColor(controls, 'color').onChange(function (e) {
	    light.color = new THREE.Color(e);
	});
	gui.add(controls, 'intensity', 0,1).onChange(function (e) {
	    light.intensity = e;
	});
	gui.add(controls, 'light_x', -50,50).onChange(function (e) {
	    light.position.x = e;
	    sphereLightMesh.position.x = e;
	});
	gui.add(controls, 'light_y', -50,50).onChange(function (e) {
	    light.position.y = e;
	    sphereLightMesh.position.y = e;
	});
	gui.add(controls, 'light_z', -50,50).onChange(function (e) {
	    light.position.z = e;
	    sphereLightMesh.position.z = e;
	});

	//更新函数
	function updata(){ 
	    cube.rotation.y +=0.01;  
	    axes.rotation.y +=0.01; 
	    mshFloor.rotation.y +=0.01; 
	    renderer.render(scene, camera);  
	    requestAnimationFrame(updata);  
	}  
	updata();  

	//窗口事件
	window.onresize = function(){
		renderer.setSize(window.innerWidth, window.innerHeight);  
	}

</script>
</html>


效果图:



区域光

区域光也叫平面光,使用平面光你可以定义一个发光的矩形。该光源不在标准的three.js库中,而是在扩展库中,所以使用之前需要导入几个额外的js文件。
另外该光源是一种非常复杂的光源,它会对WebglRenderer对象造成非常严重的性能损失。所以使用该光源时要使用WebGLDeferredRenderer来代替WebglRenderer。

平面光用AreaLight来表示,它的构造函数如下所示:
AreaLight(color, intensity)
color :颜色
intensity :光的强度,默认是1.0,就是说是100%强度的灯光

例子 :

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <style>
        body{padding: 0; margin: 0; overflow: hidden;}
    </style>
    <title>平面光</title> 
</head>
<body>  
	<div id="WebGL-output"></div> 
</body>
<script src='three_AreaLight.js'></script>
<script src='dat.gui.js'></script>
<!--平面光需要导入的js库-->
<script type="text/javascript" src="WebGLDeferredRenderer.js"></script>
<script type="text/javascript" src="ShaderDeferred.js"></script>
<script type="text/javascript" src="RenderPass.js"></script>
<script type="text/javascript" src="EffectComposer.js"></script>
<script type="text/javascript" src="CopyShader.js"></script>
<script type="text/javascript" src="ShaderPass.js"></script>
<script type="text/javascript" src="FXAAShader.js"></script>
<script type="text/javascript" src="MaskPass.js"></script>
<script>
		
	var scene = new THREE.Scene();   
	var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);    
	camera.position.set(0,30,30);  
	camera.lookAt(scene.position);

	//WebGLDeferredRenderer
	var renderer = new THREE.WebGLDeferredRenderer({
	    width: window.innerWidth,
	    height: window.innerHeight,
	    scale: 1, antialias: true,
	    tonemapping: THREE.FilmicOperator, brightness: 2.5 
	});
	document.body.appendChild(renderer.domElement);

	//平面
    var mshFloor = new THREE.Mesh(
    	new THREE.PlaneGeometry(70, 70, 1, 1), 
    	new THREE.MeshPhongMaterial({ color: 0xffffff, specular: 0xffffff, shininess: 200 })
    );
    mshFloor.rotation.x = -0.5 * Math.PI;
    scene.add(mshFloor);

	//平面光
	var light = new THREE.AreaLight(0xffffff, 1.5);
	light.position.set(0, 5, -10);
    light.rotation.set(-Math.PI / 2, 0, 0);
    light.width = 2;
    light.height = 4;
    scene.add(light);

    //伪发光的立方块
    var geom = new THREE.CubeGeometry(2, 4, 0);
    var mesh = new THREE.MeshBasicMaterial({color: 0xffffff})
    var cube = new THREE.Mesh(geom, mesh);
    cube.position = light.position;
    scene.add(cube);

    //GUI
    var controls = new function(){
    	this.color = light.color.getHex();
    	this.intensity = light.intensity;
    	this.light_x = light.position.x;
    	this.light_y = light.position.y;
    	this.light_z = light.position.z;
    }

    var gui = new dat.GUI();
	gui.addColor(controls, 'color').onChange(function (e) {
	    light.color = new THREE.Color(e);

	    //重新设置材质的颜色
        mesh.color = new THREE.Color(e);
        scene.remove(cube);
        cube = new THREE.Mesh(geom, mesh);
        cube.position = light.position;
        scene.add(cube);
	});
	gui.add(controls, 'intensity', 0,3).onChange(function (e) {
	    light.intensity = e;
	});
	gui.add(controls, 'light_x', -50,50).onChange(function (e) {
	    light.position.x = e;
	    cube.position.x = e;
	});
	gui.add(controls, 'light_y', -50,50).onChange(function (e) {
	    light.position.y = e;
	    cube.position.y = e;
	});
	gui.add(controls, 'light_z', -50,50).onChange(function (e) {
	    light.position.z = e;
	    cube.position.z = e;
	});

	//更新函数
	function updata(){ 
	    renderer.render(scene, camera);  
	    requestAnimationFrame(updata); 
	}  
	updata();  

	//窗口事件
	window.onresize = function(){
		renderer.setSize(window.innerWidth, window.innerHeight);  
	}

</script>
</html>


效果图 :


生成阴影

上面的例子中,有一些光源能生成阴影,而有一些光源不能。因为在three.js中,能形成阴影的光源只有 方向光 和 聚光灯;而相对的能表现阴影效果的材质只有 LambertMaterial 和 PhongMaterial。因此在设置光源和材质的时候,一定要注意这一点。
给物体生成阴影需要4个步骤 :
1、renderer.shadowMapEnabled = true; 
告诉渲染器我们需要阴影。为此可以将shadowMapEnabled (允许阴影映射)属性设为true
2、plane.receiveShadow = true;
接受阴影的物体需要把receiveShadow 设为true
3、cube.castShadow = true;
投射阴影的物体需要啊castShadow 设为true
4、light.castShadow = true;
把光源的castShadow 也设为true (需要注意改光源是否能产生阴影)

 

设置阴影的像素

设置光源的 shadowMapWidth 和shadowMapHeight 可以调整阴影的真实程度。如下图 : 

设置之前


设置之后

例子 :

light.shadowMapWidth = 2048; //阴影的宽度用多少像素绘制
light.shadowMapHeight = 2048; //阴影的高度用多少像素绘制

本章代码下载地址 :three.js光源-Web开发代码类资源-CSDN下载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值