利用Three.js如何实现阴影效果实例代码


Posted in Javascript onSeptember 26, 2017

前言

众所周知作为webgl的插件,three.js肯定没有原生webgl那样,添加一个阴影这么费劲。所以,经过一小时的研究(笨人不聪明,已经是极限速度了)。终于将阴影效果做了出来,并且还发现一些容易犯错的地方。话不多说了,来一起看看详细的介绍吧。

先上效果图:

利用Three.js如何实现阴影效果实例代码

实现这个效果其实很简单,只需要设置几个属性就可以实现当前的效果。而上面的材质问题我将放到下一节:

(1)首先需要告诉渲染器我需要阴影,你给我生成阴影:

renderer.shadowMap.enabled = true;

(2)然后告诉灯光,我需要阴影:

light.castShadow = true;

(3)告诉模型哪些需要投射阴影:

//告诉球需要投射阴影 
 sphere.castShadow = true; 
//告诉立方体需要投射阴影 
 cube.castShadow = true;

(4)最后告诉最底下的平面长方形你要接受阴影:

plane.receiveShadow = true;

上面四步只要设置好了,就可以实现阴影的效果了。

注意事项:你的模型的材质一定要选择对灯光有反应的材质,要不然不会出现效果,就是因为这个问题导致好长时间没有整出来阴影。

案例全部代码:

<!DOCTYPE html> 
<html lang="en"> 
<head> 
 <meta charset="UTF-8"> 
 <title>Title</title> 
 <style type="text/css"> 
 html, body { 
  margin: 0; 
  height: 100%; 
 } 
 
 canvas { 
  display: block; 
 } 
 
 </style> 
</head> 
<body onload="draw();"> 
 
</body> 
<script src="build/three.js"></script> 
<script src="examples/js/controls/TrackballControls.js"></script> 
<script src="examples/js/libs/stats.min.js"></script> 
<script> 
 var renderer; 
 function initRender() { 
 renderer = new THREE.WebGLRenderer({antialias:true}); 
 renderer.setSize(window.innerWidth, window.innerHeight); 
 //告诉渲染器需要阴影效果 
 renderer.shadowMap.enabled = true; 
 renderer.shadowMap.type = THREE.PCFSoftShadowMap; // 默认的是,没有设置的这个清晰 THREE.PCFShadowMap 
 document.body.appendChild(renderer.domElement); 
 } 
 
 var camera; 
 function initCamera() { 
 camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000); 
 camera.position.set(0, 40, 100); 
 camera.lookAt(new THREE.Vector3(0,0,0)); 
 } 
 
 var scene; 
 function initScene() { 
 scene = new THREE.Scene(); 
 } 
 
 var light; 
 function initLight() { 
 scene.add(new THREE.AmbientLight(0x444444)); 
 
 light = new THREE.SpotLight(0xffffff); 
 light.position.set(60,30,0); 
 
 //告诉平行光需要开启阴影投射 
 light.castShadow = true; 
 
 scene.add(light); 
 } 
 
 function initModel() { 
 //上面的球 
 var sphereGeometry = new THREE.SphereGeometry(5,20,20); 
 var sphereMaterial = new THREE.MeshStandardMaterial({color:0x7777ff}); 
 
 var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial); 
 sphere.position.y = 5; 
 
 //告诉球需要投射阴影 
 sphere.castShadow = true; 
 
 scene.add(sphere); 
 
 //辅助工具 
 var helper = new THREE.AxisHelper(10); 
 scene.add(helper); 
 
 //立方体 
 var cubeGeometry = new THREE.CubeGeometry(10,10,8); 
 var cubeMaterial = new THREE.MeshLambertMaterial({color:0x00ffff}); 
 
 var cube = new THREE.Mesh(cubeGeometry, cubeMaterial); 
 cube.position.x = 25; 
 cube.position.y = 5; 
 cube.position.z = -5; 
 
 //告诉立方体需要投射阴影 
 cube.castShadow = true; 
 
 scene.add(cube); 
 
 //底部平面 
 var planeGeometry = new THREE.PlaneGeometry(100,100); 
 var planeMaterial = new THREE.MeshStandardMaterial({color:0xaaaaaa}); 
 
 var plane = new THREE.Mesh(planeGeometry, planeMaterial); 
 plane.rotation.x = - 0.5 * Math.PI; 
 plane.position.y = -0; 
 
 //告诉底部平面需要接收阴影 
 plane.receiveShadow = true; 
 
 scene.add(plane); 
 
 } 
 
 //初始化性能插件 
 var stats; 
 function initStats() { 
 stats = new Stats(); 
 document.body.appendChild(stats.dom); 
 } 
 
 //用户交互插件 鼠标左键按住旋转,右键按住平移,滚轮缩放 
 var controls; 
 function initControls() { 
 controls = new THREE.TrackballControls( camera ); 
 //旋转速度 
 controls.rotateSpeed = 5; 
 //变焦速度 
 controls.zoomSpeed = 3; 
 //平移速度 
 controls.panSpeed = 0.8; 
 //是否不变焦 
 controls.noZoom = false; 
 //是否不平移 
 controls.noPan = false; 
 //是否开启移动惯性 
 controls.staticMoving = false; 
 //动态阻尼系数 就是灵敏度 
 controls.dynamicDampingFactor = 0.3; 
 //未知,占时先保留 
 //controls.keys = [ 65, 83, 68 ]; 
 controls.addEventListener( 'change', render ); 
 } 
 
 function render() { 
 renderer.render( scene, camera ); 
 } 
 
 //窗口变动触发的函数 
 function onWindowResize() { 
 
 camera.aspect = window.innerWidth / window.innerHeight; 
 camera.updateProjectionMatrix(); 
 controls.handleResize(); 
 render(); 
 renderer.setSize( window.innerWidth, window.innerHeight ); 
 
 } 
 
 function animate() { 
 //更新控制器 
 render(); 
 
 //更新性能插件 
 stats.update(); 
 
 controls.update(); 
 
 requestAnimationFrame(animate); 
 } 
 
 function draw() { 
 initRender(); 
 initScene(); 
 initCamera(); 
 initLight(); 
 initModel(); 
 initControls(); 
 initStats(); 
 
 animate(); 
 window.onresize = onWindowResize; 
 } 
</script> 
</html>

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用Three.js具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
Prototype 工具函数 学习
Jul 23 Javascript
JavaScript Cookie 直接浏览网站分网址
Dec 08 Javascript
js下用层来实现select的title提示属性
Feb 23 Javascript
js控制页面的全屏展示和退出全屏显示的方法
Mar 10 Javascript
在JavaScript应用中实现延迟加载的方法
Jun 25 Javascript
jQuery实现对无序列表的排序功能(附demo源码下载)
Jun 25 Javascript
jQuery.Sumoselect插件实现下拉复选框效果
Nov 09 jQuery
浅谈Vue-cli 命令行工具分析
Nov 22 Javascript
Vue2(三)实现子菜单展开收缩,带动画效果实现方法
Apr 28 Javascript
VUE写一个简单的表格实例
Aug 06 Javascript
vue中注册自定义的全局js方法
Nov 15 Javascript
js实现淘宝首页的banner栏效果
Nov 26 Javascript
使用JavaScript实现在页面中显示距离2017年中秋节的天数
Sep 26 #Javascript
Three.js实现绘制字体模型示例代码
Sep 26 #Javascript
Three.js利用Detector.js插件如何实现兼容性检测详解
Sep 26 #Javascript
JS+jQuery实现注册信息的验证功能
Sep 26 #jQuery
详解vue-cli中的ESlint配置文件eslintrc.js
Sep 25 #Javascript
JavaScript 自定义事件之我见
Sep 25 #Javascript
详解在vue-cli中使用路由
Sep 25 #Javascript
You might like
php反弹shell实现代码
2009/04/22 PHP
ThinkPHP基于PHPExcel导入Excel文件的方法
2014/10/15 PHP
yii2框架中使用下拉菜单的自动搜索yii-widget-select2实例分析
2016/01/09 PHP
微信小程序发送订阅消息的方法(php 为例)
2019/10/30 PHP
JavaScript 实现??打印?理
2007/04/28 Javascript
JScript的条件编译
2007/05/29 Javascript
JavaScript创建命名空间(namespace)的最简实现
2007/12/11 Javascript
jquery的extend和fn.extend的使用说明
2011/01/09 Javascript
extjs tabpanel限制选项卡数量实现思路及代码
2013/04/02 Javascript
JavaScript中按位“异或”运算符使用介绍
2014/03/14 Javascript
js脚本获取webform服务器控件的方法
2014/05/16 Javascript
基于jQuery实现select下拉选择可输入附源码下载
2016/02/03 Javascript
javascript实现查找数组中最大值方法汇总
2016/02/13 Javascript
canvas红包照片实例分享
2017/02/28 Javascript
Node.js使用Express.Router的方法
2017/11/14 Javascript
vuex 的简单使用
2018/03/22 Javascript
webpack的CSS加载器的使用
2018/09/11 Javascript
Vue实现验证码功能
2019/12/03 Javascript
JavaScript检测浏览器是否支持CSS变量代码实例
2020/04/03 Javascript
基于p5.js 2D图像接口的扩展(交互实现)
2020/11/30 Javascript
[02:32]【DOTA2亚洲邀请赛】iceice,梦开始的地方
2017/03/13 DOTA
Python获取Windows或Linux主机名称通用函数分享
2014/11/22 Python
使用FastCGI部署Python的Django应用的教程
2015/07/22 Python
深入理解python中的浅拷贝和深拷贝
2016/05/30 Python
python 实现selenium断言和验证的方法
2019/02/13 Python
python爬虫模拟浏览器的两种方法实例分析
2019/12/09 Python
pytorch GAN生成对抗网络实例
2020/01/10 Python
解决IDEA 的 plugins 搜不到任何的插件问题
2020/05/04 Python
基于html5 canvas做批改作业的小插件
2020/05/20 HTML / CSS
Belle Maison倍美丛官网:日本千趣会旗下邮购网站
2016/07/22 全球购物
体育专业个人的求职信范文
2013/09/21 职场文书
产品质量承诺书
2014/03/27 职场文书
总经理致辞
2015/07/29 职场文书
当你焦虑迷茫时,请读读这6句话
2019/07/24 职场文书
Python字典的基础操作
2021/11/01 Python
Python如何加载模型并查看网络
2022/07/15 Python