WebGL three.js学习笔记之阴影与实现物体的动画效果


Posted in Javascript onApril 25, 2019

实现物体的旋转、跳动以及场景阴影的开启与优化

本程序将创建一个场景,并实现物体的动画效果

 运行的结果如图:

WebGL three.js学习笔记之阴影与实现物体的动画效果

运行结果

 完整代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Three.js</title>
 <script src="../../../Import/three.js"></script>
 <script src="../../../Import/stats.js"></script>
 <script src="../../../Import/Setting.js"></script>
 <script src="../../../Import/OrbitControls.js"></script>
 <script src="../../../Import/dat.gui.min.js"></script>
 <style type="text/css">
 div#canvas-frame {
 border: none;
 cursor: pointer;
 width: 100%;
 height: 850px;
 background-color: #333333;
 }
 </style>
</head>
<body onload="threeStart()">
<div id="canvas-frame"></div>
<script>
 //控制面板中需要的两个数据
 let control = new function () {
 this.rotationSpeed = 0.01;
 this.jumpSpeed = 0.03;
 };
 let renderer, camera, scene;
 let controller;
 let width,height;

 //初始化渲染器
 function initThree() {
 width = document.getElementById('canvas-frame').clientWidth;
 height = document.getElementById('canvas-frame').clientHeight;
 renderer = new THREE.WebGLRenderer({
 antialias: true
 });//定义渲染器
 renderer.setSize(width, height);//设置渲染的宽度和高度
 document.getElementById("canvas-frame").appendChild(renderer.domElement);//将渲染器加在html中的div里面
 renderer.setClearColor(0x333333, 1.0);//渲染的颜色设置
 renderer.shadowMapEnabled = true;//开启阴影,默认是关闭的,太影响性能
 renderer.shadowMapType = THREE.PCFSoftShadowMap;//阴影的一个类型,可以不设置对比看效果
 }
 //初始化摄像机
 function initCamera() {
 camera = new THREE.PerspectiveCamera(45, width / height, 1, 10000);//perspective是透视摄像机,这种摄像机看上去画面有3D效果

 //摄像机的位置
 camera.position.x = 50;
 camera.position.y = 50;
 camera.position.z = 50;
 camera.up.x = 0;
 camera.up.y = 1;//摄像机的上方向是Y轴
 camera.up.z = 0;
 camera.lookAt(0, 0, 0);//摄像机对焦的位置
 //这三个参数共同作用才能决定画面
 }
 //初始化场景
 function initScene() {
 scene = new THREE.Scene();
 }
 //摄像机的控制,可以采用鼠标拖动来控制视野
 function cameraControl() {
 controller = new THREE.OrbitControls(camera, renderer.domElement);
 controller.target = new THREE.Vector3(0, 0, 0);
 }
 //一个很方便的控制面板,方便更改程序的参数
 function datGUI() {
 let gui = new dat.GUI();
 //可以设置可以调动的范围
 gui.add(control, "rotationSpeed", 0, 0.05);
 gui.add(control, "jumpSpeed", 0, 0.08);
 }
 //初始化灯光
 function initLight() {
 let light = new THREE.SpotLight(0xffffff, 1.0, 0);//点光源
 light.position.set(-40, 60, -10);
 light.castShadow = true;//开启阴影
 light.shadowMapWidth = 8192;//阴影的分辨率
 light.shadowMapHeight = 8192;
 scene.add(light);
 light = new THREE.AmbientLight(0xffffff, 0.2);//环境光,如果不加,点光源照不到的地方就完全是黑色的
 scene.add(light);
 }

 let cube;
 let sphere;

 //初始化物体
 function initObject() {
 //定义了一个地面
 let planeGeometry = new THREE.PlaneGeometry(100, 100, 1, 1);
 let planeMaterial = new THREE.MeshLambertMaterial({
 color: 0xcccccc,
 });
 let plane = new THREE.Mesh(planeGeometry, planeMaterial);
 plane.rotation.x = -0.5 * Math.PI;
 plane.position.x = 15;
 plane.receiveShadow = true;//开启地面的接收阴影
 scene.add(plane);//添加到场景中

 //定义了一个方块
 let cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
 let cubeMaterial = new THREE.MeshLambertMaterial({
 color: 0xff1111,
 });
 cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
 cube.position.x = -4;
 cube.position.y = 3;
 cube.position.z = 0;
 cube.castShadow = true;//开启阴影
 scene.add(cube);

 //定义了一个球体
 let sphereGeometry = new THREE.SphereGeometry(4, 100, 100);
 let sphereMaterial = new THREE.MeshLambertMaterial({
 color: 0xba7890,
 });
 sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
 sphere.position.x = 20;
 sphere.position.y = 4;
 sphere.position.z = 2;
 sphere.castShadow = true;//开启阴影
 scene.add(sphere);
 }
 //方块的自动旋转
 function cubeRotation() {
 cube.rotation.x += control.rotationSpeed;
 cube.rotation.y += control.rotationSpeed;
 cube.rotation.z += control.rotationSpeed;
 }

 let step = 0;
 //球体的抛物线运动轨迹
 function boxJump() {
 step += control.jumpSpeed;
 sphere.position.x = 20 + 10 * (Math.cos(step));
 sphere.position.y = 4 + 10 * (Math.abs(Math.sin(step)));
 }
 //定义的一个功能文件
 function initSetting() {
 loadAutoScreen(camera,renderer);
 loadFullScreen();
 loadStats();
 }
 //主函数
 function threeStart() {
 initThree();
 initCamera();
 initScene();
 initLight();
 initObject();
 cameraControl();
 datGUI();
 initSetting();
 animation();
 }
 //动画
 function animation() {
 cubeRotation();//方块旋转函数
 boxJump();//球体运动函数
 stats.update();//更新性能检测器

 renderer.clear();
 renderer.render(scene, camera);//开始渲染

 requestAnimationFrame(animation);//重复执行此函数,不停的渲染,达到动画的效果
 }
</script>
</body>
</html>

其中OrbitControls.jsdat.gui.min.js这两个文件都是Three.js自带的两个很好用的工具,第一个是可以让摄像机有轨道地进行移动,而不用再自己写函数去实现,第二个是一个轻量级的图形用户界面库(GUI 组件),使用这个库可以很容易地创建出能够改变代码变量的界面组件,方便我们测试程序。

另外如果想要在程序中开启阴影的话首先需要把renderer.shadowMapEnabled设置为true,默认是关闭的,因为实现阴影的效果是比较消耗性能的。同时要把light的投掷阴影开启light.castShadow = true,但是并不是所有的灯光都可以开启,比如环境光就不可以。每一个需要产生阴影的物体也要开启阴影,我们需要用地面来接收阴影,所以也需要开启地面的接收

WebGL three.js学习笔记之阴影与实现物体的动画效果

plane.receiveShadow = true;
cube.castShadow = true;
 sphere.castShadow = true;

现在的效果是这样的:

WebGL three.js学习笔记之阴影与实现物体的动画效果

 可以看到,阴影是比较难看的,所以设置一些阴影的类型,PCFSoftShadowMap能让边缘柔和,但只是基于像素颗粒的边缘柔和。我们可以先使用此类型,然后再提高阴影的分辨率

light.shadowMapWidth = 8192;
 light.shadowMapHeight = 8192;

默认的值应该是1024。

 此时的阴影效果是这样的

优化后阴影

 至此,我们的场景还有物体的动画效果就已经实现。

总结

以上所述是小编给大家介绍的WebGL three.js学习笔记之阴影与实现物体的动画效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
基于jQuery实现网页进度显示插件
Mar 04 Javascript
cocos2dx骨骼动画Armature源码剖析(三)
Sep 08 Javascript
Javascript数组Array方法解读
Mar 13 Javascript
JavaScript的模块化开发框架Sea.js上手指南
May 12 Javascript
浅谈js中对象的使用
Aug 11 Javascript
用AngularJS的指令实现tabs切换效果
Aug 31 Javascript
jquery手机触屏滑动拼音字母城市选择器的实例代码
Dec 11 jQuery
详解vue-cli 接口代理配置
Dec 13 Javascript
VUE路由动态加载实例代码讲解
Aug 26 Javascript
ES6中let、const的区别及变量的解构赋值操作方法实例分析
Oct 15 Javascript
javascript读取本地文件和目录方法详解
Aug 06 Javascript
解决vue动态下拉菜单 有数据未反应的问题
Aug 06 Javascript
WebGL学习教程之Three.js学习笔记(第一篇)
Apr 25 #Javascript
Angular封装搜索框组件操作示例
Apr 25 #Javascript
Vue使用zTree插件封装树组件操作示例
Apr 25 #Javascript
详解javascript中的Error对象
Apr 25 #Javascript
Vue开发之封装上传文件组件与用法示例
Apr 25 #Javascript
vue2.0自定义指令示例代码详解
Apr 25 #Javascript
Vue开发之封装分页组件与使用示例
Apr 25 #Javascript
You might like
PHP 5.3.0 安装分析心得
2009/08/07 PHP
php 数据库字段复用的基本原理与示例
2011/07/22 PHP
php查看网页源代码的方法
2015/03/13 PHP
详解Yii实现分页的两种方法
2017/01/14 PHP
PHP实现的简单AES加密解密算法实例
2017/05/29 PHP
利用Homestead快速运行一个Laravel项目的方法详解
2017/11/14 PHP
使用JavaScript获取地址栏参数的方法
2014/12/19 Javascript
解决jquery实现的radio重新选中的问题
2015/07/03 Javascript
浅谈JavaScript变量的自动转换和语句
2016/06/12 Javascript
jQuery实现导航滚动到指定内容效果完整实例【附demo源码下载】
2016/09/20 Javascript
js判断文件格式及大小的简单实例(必看)
2016/10/11 Javascript
微信小程序 详解页面跳转与返回并回传数据
2017/02/13 Javascript
Node.js操作redis实现添加查询功能
2017/05/25 Javascript
基于vue-cli 打包时抽离项目相关配置文件详解
2018/03/07 Javascript
JS实现访问DOM对象指定节点的方法示例
2018/04/04 Javascript
微信小程序的tab选项卡的实现效果
2019/05/15 Javascript
vue实现自定义H5视频播放器的方法步骤
2019/07/01 Javascript
微信小程序实现下拉框功能
2019/07/16 Javascript
jquery validate 实现动态增加/删除验证规则操作示例
2019/10/28 jQuery
vue路由缓存的几种实现方式小结
2020/02/02 Javascript
[02:17]TI4西雅图DOTA2前线报道 啸天mik夫妻档解说
2014/07/08 DOTA
python清除指定目录内所有文件中script的方法
2015/06/30 Python
Python的面向对象编程方式学习笔记
2016/07/12 Python
python使用opencv读取图片的实例
2017/08/17 Python
Django 模型类(models.py)的定义详解
2019/07/19 Python
Python+OpenCv制作证件图片生成器的操作方法
2019/08/21 Python
深入了解canvas在移动端绘制模糊的问题解决
2019/04/30 HTML / CSS
汤米巴哈马官方网站:Tommy Bahama
2017/05/13 全球购物
Sneaker Studio捷克:购买运动鞋
2018/07/08 全球购物
Booking.com亚太地区:Booking.com APAC
2020/02/07 全球购物
电气工程及其自动化学生实习自我鉴定
2013/09/19 职场文书
《我的伯父鲁迅先生》教学反思
2014/02/12 职场文书
年终总结会主持词
2014/03/25 职场文书
2014年干部作风建设总结
2014/10/23 职场文书
2015年民主评议党员工作总结
2015/05/19 职场文书
PHP实现rar解压读取扩展包小结
2021/06/03 PHP