利用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 相关文章推荐
showModalDialog 和 showModelessDialog
Jan 22 Javascript
JavaScript获取GridView中用户点击控件的行号,列号
Apr 14 Javascript
Google Map API更新实现用户自定义标注坐标
Jul 29 Javascript
探讨在JQuery和Js中,如何让ajax执行完后再继续往下执行
Jul 09 Javascript
jquery使用jxl插件导出excel示例
Apr 14 Javascript
AngularJS向后端ASP.NET API控制器上传文件
Feb 03 Javascript
Vue.js 递归组件实现树形菜单(实例分享)
Dec 21 Javascript
兼容浏览器的js事件绑定函数(详解)
May 09 Javascript
JS中利用swiper实现3d翻转幻灯片实例代码
Aug 25 Javascript
Vue.js通用应用框架-Nuxt.js的上手教程
Dec 25 Javascript
Vue+Java+Base64实现条码解析的示例
Sep 23 Javascript
原生js实现表格循环滚动
Nov 24 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 文章调用类代码
2011/08/11 PHP
php array_filter除去数组中的空字符元素
2020/06/21 PHP
PHP中header和session_start前不能有输出原因分析
2013/01/11 PHP
表单提交验证类
2006/07/14 Javascript
javascript之学会吝啬 精简代码
2010/04/25 Javascript
基于jQuery实现的水平和垂直居中的div窗口
2011/08/08 Javascript
js同比例缩放图片的小例子
2013/10/30 Javascript
jquery实现多行文字图片滚动效果示例代码
2014/10/10 Javascript
无刷新上传文件并返回自定义值
2015/06/11 Javascript
jquery实现网站列表切换效果的2种方法
2016/08/12 Javascript
JS实现页面中所有img对象添加onclick事件及新窗口查看图片的方法
2016/12/27 Javascript
JS对象创建的几种方式整理
2017/02/28 Javascript
AngularJs导出数据到Excel的示例代码
2017/08/11 Javascript
seajs模块压缩问题与解决方法实例分析
2017/10/10 Javascript
jQuery动态移除与增加onclick属性的方法详解
2018/06/07 jQuery
vue 自定义组件的写法与用法详解
2020/03/04 Javascript
js编写简易的计算器
2020/07/29 Javascript
详解Python判定IP地址合法性的三种方法
2018/03/06 Python
Python实现的计算器功能示例
2018/04/26 Python
Python实现查看系统启动项功能示例
2018/05/10 Python
python实现二维插值的三维显示
2018/12/17 Python
Django实现学员管理系统
2019/02/26 Python
基于python if 判断选择结构的实例详解
2019/05/06 Python
python实现微信自动回复及批量添加好友功能
2019/07/03 Python
在Tensorflow中实现leakyRelu操作详解(高效)
2020/06/30 Python
Pycharm学生免费专业版安装教程的方法步骤
2020/09/24 Python
HTML5印章绘制电子签章图片(中文英文椭圆章、中文英文椭圆印章)
2019/06/03 HTML / CSS
POP文化和音乐灵感的时尚:Hot Topic
2019/06/19 全球购物
SK-II神仙水美国官网:SK-II美国
2020/02/25 全球购物
J2ee常用的设计模式?说明工厂模式
2015/05/21 面试题
区域销售主管岗位职责
2014/06/15 职场文书
中层干部培训方案
2014/06/16 职场文书
交通安全宣传标语(100条)
2019/08/22 职场文书
Python如何配置环境变量详解
2021/05/18 Python
Python趣味挑战之教你用pygame画进度条
2021/05/31 Python
使用JS前端技术实现静态图片局部流动效果
2022/08/05 Javascript