利用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 相关文章推荐
javascript web页面刷新的方法收集
Jul 02 Javascript
javascript 面向对象全新理练之数据的封装
Dec 03 Javascript
ExtJS 下拉多选框lovcombo
May 19 Javascript
js模仿html5 placeholder适应于不支持的浏览器
Jan 13 Javascript
js鼠标点击事件在各个浏览器中的写法及Event对象属性介绍
Jan 24 Javascript
如何获取select下拉框的值(option没有及有value属性)
Nov 08 Javascript
JavaScript实现下拉列表框数据增加、删除、上下排序的方法
Aug 11 Javascript
js实现Tab选项卡切换效果
Jul 17 Javascript
vue-cli3项目升级到vue-cli4 的方法总结
Mar 19 Javascript
javascript用defineProperty实现简单的双向绑定方法
Apr 03 Javascript
Element Card 卡片的具体使用
Jul 26 Javascript
vue+element获取el-table某行的下标,根据下标操作数组对象方式
Aug 07 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的ob_start() 控制您的浏览器cache
2009/08/03 PHP
深入PHP数据缓存的使用说明
2013/05/10 PHP
深入mysql_fetch_row()与mysql_fetch_array()的区别详解
2013/06/05 PHP
PHP实现的折半查找算法示例
2017/12/19 PHP
使用jquery插件实现图片延迟加载技术详细说明
2011/03/12 Javascript
ajax上传时参数提交不更新等相关问题
2012/12/11 Javascript
js返回上一页并刷新代码整理
2012/12/21 Javascript
JS的参数传递示例介绍
2014/02/08 Javascript
js实现兼容IE和FF的上下层的移动
2015/05/04 Javascript
理解Javascript图片预加载
2016/02/23 Javascript
JS组件Bootstrap dropdown组件扩展hover事件
2016/04/17 Javascript
AngularJs篇:使用AngularJs打造一个简易权限系统的实现代码
2016/12/26 Javascript
Jquery EasyUI $.Parser
2017/06/02 jQuery
Vue.js组件通信的几种姿势
2017/10/23 Javascript
bootstrap轮播模板使用方法详解
2017/11/17 Javascript
js和jQuery以及easyui实现对下拉框的指定赋值方法
2018/01/23 jQuery
深入浅析Node环境和浏览器的区别
2018/08/14 Javascript
微信小程序实现图片上传
2019/05/23 Javascript
JS实现利用闭包判断Dom元素和滚动条的方向示例
2019/08/26 Javascript
Vue实现手机扫描二维码预览页面效果
2020/05/28 Javascript
vue 动态组件(component :is) 和 dom元素限制(is)用法说明
2020/09/04 Javascript
[01:52]DOTA2完美大师赛Vega战队趣味视频——kpii老师小课堂
2017/11/25 DOTA
python连接mongodb操作数据示例(mongodb数据库配置类)
2013/12/31 Python
利用Python如何生成随机密码
2016/04/20 Python
Python数据类型详解(二)列表
2016/05/08 Python
Python基础篇之初识Python必看攻略
2016/06/23 Python
python matplotlib 注释文本箭头简单代码示例
2018/01/08 Python
python爬取m3u8连接的视频
2018/02/28 Python
基于python SMTP实现自动发送邮件教程解析
2020/06/02 Python
如何通过命令行进入python
2020/07/06 Python
Python如何对齐字符串
2020/07/30 Python
如何查看浏览器对html5的支持情况
2020/12/15 HTML / CSS
德国宠物用品、宠物食品及水族馆网上商店:ZooRoyal
2017/07/09 全球购物
VC++笔试题
2014/10/13 面试题
什么是makefile? 如何编写makefile?
2013/01/02 面试题
元旦联欢会主持词
2014/03/26 职场文书