当前位置: 首页 > news >正文

《Learning Three.js》学习(1)使用Three.js创建三维场景

前言:

WebGL可以直接使用显卡资源从JS创建三维场景;可用Three.js优化该复杂过程。

"构建骨架"

理论知识:

我们分别需要Three.js和TrackballControls.js两个文件作为支持库。

THREE中需要场景、相机和渲染器来构建三维元素。

scene - 场景是一个容器,用于保存、跟踪所要渲染的物体和使用的光源。

scene是渲染物体的基础。

对于物体对象的基本操作个人概括为:1、创建物体的尺寸  2、添加样式-颜色/透明度/材质  3、将尺寸和样式融合并“覆盖原物体”  4、设置物体的“外方位元素” 5、添加到场景中

camera - 相机将决定哪些东西会被渲染(可视)

renderer - 渲染场景和相机视角,        renderer.render(scene, camera);

最后将渲染挂载到div标签上,告诉渲染器使用指定摄像机渲染场景

接下来我们实现下表中的对象

sphereGeometry方法 

效果:

由于设置了旋转角,默认z轴垂直平面向外。 

代码:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>/* 确保容器填满整个视口 */#webgl-output {width: 100%;height: 100%;display: block;}</style><script type="text/javascript" charset="UTF-8" src="./libs/three.js"></script><script type="text/javascript" charset="UTF-8" src="./libs/TrackballControls.js"></script>
</head>
<body><!-- 添加一个容器元素 --><div id="webgl-output"></div><script> const init = () =>{var scene = new THREE.Scene();var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);var renderer = new THREE.WebGLRenderer();// 设置背景颜色renderer.setClearColor(new THREE.Color(0xEEEEEE));// 设置渲染区域的大小renderer.setSize(window.innerWidth, window.innerHeight);// 创建坐标轴var axes = new THREE.AxisHelper(20);scene.add(axes);// 创建平面var planeGeometry = new THREE.PlaneGeometry(60, 20);// 创建材质var planeMaterial = new THREE.MeshBasicMaterial({color: 0xcccccc});// 组装var plane = new THREE.Mesh(planeGeometry, planeMaterial);// 平面旋转plane.rotation.x = -0.5 * Math.PI;// 平面位置plane.position.x = 15;// plane.position.set(15, 0, 0);// 添加到场景scene.add(plane);// 创建立方体var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);var cubeMaterial = new THREE.MeshBasicMaterial({color: 0xff0000, wireframe: true});var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);  cube.position.set(-4, 3, 0);scene.add(cube)// 创建球体var sphereGeometry = new THREE.SphereGeometry(4,20,20)var sphereMaterial = new THREE.MeshBasicMaterial({color: 0x7777ff, wireframe: true});var sphereMesh = new THREE.Mesh(sphereGeometry, sphereMaterial);sphereMesh.position.set(20, 4, 2);scene.add(sphereMesh);// 设置相机位置camera.position.set(-30, 40, 30);camera.lookAt(scene.position);// 将渲染器添加到domdocument.getElementById('webgl-output').appendChild(renderer.domElement);// 渲染renderer.render(scene, camera);}init();</script>
</body>
</html>

"添加羽毛"

添加材质、光源、阴影效果。

理论知识:

通过castShadow属性设置,THREE.js阴影效果被开启,并使用shadow.mapSize,shadow.camera.far,shadow.camera.near来控制阴影精细化程度。

注意光源的显示必须要合适的材料,效果才能显示,eg:MeshBasicMaterial材料无效果

可以改为MeshLambertMaterial、MeshPhysicalMaterial、MeshStandardMaterial、MeshPhongMaterail(已废弃)

阴影贴图大小仅为512x512,阴影贴图必须是2的幂

告诉渲染器需要阴影效果 renderer.shadowMap.enabled = true;

此时仍然无光影效果,需要明确指定谁投射阴影,谁接受阴影。

注意需要对光源的强度和随距离衰减情况进行修改,否则材质显示为黑色。

plane.recieveShadow = true
cube.castShadow = true
sphere.castShadow = true

定义产生阴影的光源,并不是所有的光源可以产生阴影,通过Three.SpotLight定义的光源能够产生阴影。下述代码渲染阴影。

spotLight.castShadow = true
效果:

代码: 
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>/* 确保容器填满整个视口 */#webgl-output {width: 100%;height: 100%;display: block;overflow: hidden;}</style><script type="module">import * as THREE from '../build/three.module.js';window.THREE = THREE;</script>
</head>
<body><!-- 添加一个容器元素 --><div id="Stats-output"><div id="webgl-output"></div></div><script type="module"> const init = () => {var scene = new THREE.Scene();var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000);var renderer = new THREE.WebGLRenderer();// 设置背景颜色renderer.setClearColor(new THREE.Color(0x000000));// 设置渲染区域的大小renderer.setSize(window.innerWidth, window.innerHeight);// 创建坐标轴var axes = new THREE.AxesHelper(20);scene.add(axes);// 创建平面var planeGeometry = new THREE.PlaneGeometry(60, 20);// 创建材质var planeMaterial = new THREE.MeshBasicMaterial({color: 0xecb514, side: THREE.DoubleSide});// 组装-创建格网var plane = new THREE.Mesh(planeGeometry, planeMaterial);// 平面旋转plane.rotation.x = -0.5 * Math.PI;// 平面位置plane.position.set(15, 0, 0);plane.receiveShadow = true;// 添加到场景scene.add(plane);// 创建立方体var cubeGeometry = new THREE.BoxGeometry(4, 4, 4);var cubeMaterial = new THREE.MeshLambertMaterial({color: 0xff0000, emissive: 0x000000, side: THREE.DoubleSide});var cube = new THREE.Mesh(cubeGeometry, cubeMaterial);cube.position.set(-4, 3, 0);cube.castShadow = true;scene.add(cube);// 创建球体var sphereGeometry = new THREE.SphereGeometry(4, 20, 20);var sphereMaterial = new THREE.MeshLambertMaterial({color: 0x7777ff, emissive: 0x000000, side: THREE.DoubleSide});var sphereMesh = new THREE.Mesh(sphereGeometry, sphereMaterial);sphereMesh.position.set(20, 4, 2);sphereMesh.castShadow = true;scene.add(sphereMesh);// 设置相机位置camera.position.set(-30, 40, 30);camera.lookAt(cube.position); // 改为看向立方体// 光照// 聚光灯const spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(-40, 60, -10);spotLight.shadow.mapSize.width = 1024;spotLight.shadow.mapSize.height = 1024;spotLight.shadow.camera.visible = false; // 不显示阴影相机spotLight.castShadow = true;spotLight.shadow.camera.far = 130;spotLight.shadow.camera.near = 40;spotLight.shadow.camera.fov = 50; // 设置阴影相机的视场角spotLight.intensity = 5; // 聚光灯强度spotLight.target = cube; // 设置聚光灯的目标spotLight.decay = 0.06; // 衰减scene.add(spotLight);// 添加阴影效果renderer.setClearColor(new THREE.Color(0x000000));renderer.setSize(window.innerWidth, window.innerHeight);renderer.shadowMap.type = THREE.PCFSoftShadowMap;// 设置更高的阴影贴图分辨率renderer.shadowMap.width = 2048; // 减少锯齿效果renderer.shadowMap.height = 2048;renderer.shadowMap.enabled = true;// 将渲染器添加到domdocument.getElementById('webgl-output').appendChild(renderer.domElement);}window.onload = init;</script>
</body>
</html>

"初试羽翼"

让场景中的物体动起来。

requestAnimationFrame()

稳定而连续的渲染场景

        // 将渲染器添加到domdocument.getElementById('webgl-output').appendChild(renderer.domElement);// 渲染循环function renderScene() {requestAnimationFrame(renderScene);renderer.render(scene, camera);}renderScene()

添加帧数显示

代码:

    // 添加帧数显示function initStates(type){var panelType = (typeof type !== 'undefined' && type) && (!isNaN(parseInt(type))) ? parseInt(type) : 0;var stats = new Stats();stats.showPanel(panelType);document.getElementById('Stats-output').appendChild(stats.dom);return stats;}
旋转立方体

效果:

代码:

// 立方体旋转
cube.rotation.x += 0.02;
cube.rotation.y += 0.02;
cube.rotation.z += 0.02;
弹跳球

效果:

代码:

            const step = 0// 小球运动step += 0.04;sphereMesh.position.x = 20 + (10 * (Math.cos(step)));sphereMesh.position.y = 2 + (10 * Math.abs(Math.sin(step)));

GUI简化调试流程

代码:

	// 创建待GUI控制的对象var controls = new function(){this.rotationSpeed = 0.02;this.bouncingSpeed = 0.03;}// 创建控制器var gui = new dat.GUI();gui.add(controls, 'rotationSpeed', 0, 0.5);gui.add(controls, 'bouncingSpeed', 0, 0.5);


http://www.mrgr.cn/news/78345.html

相关文章:

  • 三维地形图计算软件(三)-原基于PYQT5+pyqtgraph旧代码
  • 移除链表元素(203)
  • Windows修复SSL/TLS协议信息泄露漏洞(CVE-2016-2183)
  • 探寻嵌入式系统的发展之路与趋势展望
  • java脚手架系列16-AI大模型集成
  • 0基础学前端系列 -- 前端的存储方式
  • ABAP OOALV模板
  • 蓝桥杯备赛笔记(一)
  • transformer学习笔记-神经网络原理
  • mini-spring源码分析
  • Leetcode(快慢指针习题思路总结,持续更新。。。)
  • 【halcon】Metrology工具系列之 get_metrology_object_model_contour
  • Leetcode 51 N Queens Leetcode N Queens II
  • Qt程序发布及打包成exe安装包
  • Windows Server 2019 虚拟机 安装Oracle19c,图文详情(超详细)
  • Chrome和edge浏览器如何为任何网站强制暗模式
  • git 学习笔记
  • VTK中对于相机camera的设置
  • 机载视频流回传+编解码方案
  • 分布式调用 - 服务间的远程调用RPC
  • Linux系统硬件老化测试脚本:自动化负载与监控
  • Github 基本使用学习笔记
  • 老旧前端项目如何升级工程化的项目
  • 【大模型】从零样本到少样本学习:一文读懂 Zero-shot、One-shot 和 Few-shot 的核心原理与应用!
  • 【Zookeeper】四,Zookeeper节点类型、通知、仲裁、会话
  • 去哪儿大数据面试题及参考答案