【ThreeJS基础教程-高级几何体篇】2.1更好的视觉效果-综合案例(2)
2.1更好的视觉效果-综合案例(2
- 学习ThreeJS的捷径
- 初识纹理Texture
- 如何生成一片草地
- Texture与TextureLoader
- 做一个简单的地球出来
- 下一篇预告:加载模型
学习ThreeJS的捷径
本段内容会写在0篇以外所有的,本人所编写的Threejs教程中
对,学习ThreeJS有捷径
当你有哪个函数不懂的时候,第一时间去翻一翻文档
当你有哪个效果不会做的时候,第一时间去翻一翻所有的案例,也许就能找到你想要的效果
最重要的一点,就是,绝对不要怕问问题,越怕找找别人问题,你的问题就会被拖的越久
如果你确定要走WebGL/ThreeJS的开发者路线的话,以下行为可以让你更快的学习ThreeJS
- 没事就把所有的文档翻一遍,哪怕看不懂,也要留个印象,至少要知道Threejs有什么
- 没事多看看案例效果,当你记忆的案例效果足够多时,下次再遇到相似问题时,你就有可能第一时间来找对应的案例,能更快解决你自己的问题
- 上述案例不只是官网的案例,郭隆邦技术博客,跃焱邵隼,暮志未晚等站点均有不少优质案例,记得一并收藏
http://www.yanhuangxueyuan.com/ 郭隆邦技术博客
https://www.wellyyss.cn/ 跃焱邵隼
http://www.wjceo.com/ 暮志未晚
这三个站点是我最常逛的站点,推荐各位有事没事逛一下,看看他们的案例和写法思路,绝对没坏处
初识纹理Texture
先提前纠正一下纹理(Texture)和贴图(Map)不是一个东西
纹理一般是指贴图贴在模型表面之后,显示出来的样子,称为纹理,通常会由贴图来生成纹理
贴图的本质就是一张图片资源
如何生成一片草地
let geometry = new THREE.PlaneGeometry(10,10,10).rotateX(-Math.PI/2);let material = new THREE.MeshBasicMaterial({color:"#00ff00"});let mesh = new THREE.Mesh(geometry,material);scene.add(mesh);
上述方式虽然可以制作一块绿色的平面,但是这很难让人联想到这里是一块草地
这时候我们就需要借助纹理来生成草地了
function addMesh(){let texture = new THREE.TextureLoader().load("./grass.jpg");let geometry = new THREE.PlaneGeometry(10,10,10).rotateX(-Math.PI/2);let material = new THREE.MeshBasicMaterial({map:texture});let mesh = new THREE.Mesh(geometry,material);scene.add(mesh);}
这样的草地是否显得更逼真一些呢?
Texture与TextureLoader
先在这里说明一下,官方的写法这里存在问题
上面的案例也是按照官方写法而写的,但是这种写法会存在一个问题,就是TextureLoader.load()是一个异步函数,当你的图片加载速度低于你使用纹理的速度时,就有可能会出现错误,尤其是当你要一次加载多个纹理时,或者你加载的贴图过于巨大时(极高分辨率的大型巨型图片),此时受网速影响加载纹理太慢时,就会出现这样的问题
这种错误一般是线上更容易发生,而在本地开发过程中几乎不会遇到
因此笔者建议从一开始接触纹理时,就使用下面的写法
function addMesh(){//创建纹理加载器let textureLoader = new THREE.TextureLoader();//加载器读取grass.jpg,加载完成时执行下面的函数textureLoader.load("./grass.jpg",(texture)=>{let geometry = new THREE.PlaneGeometry(10,10,10).rotateX(-Math.PI/2);let material = new THREE.MeshBasicMaterial({map:texture});let mesh = new THREE.Mesh(geometry,material);scene.add(mesh);});}
官方文档中的wrapS和warpT等暂时不在本篇讨论,后续将有一篇文章单独对纹理详细讲解
Texture官方文档
TextureLoader官方文档
关于Loader会在后续专门写一篇文章来详细讲解,本篇仅对纹理做基本介绍
函数:textureLoader.load(url : String, onLoad : Function, onProgress : Function, onError : Function );
url:图片路径
onLoad:资源全部加载完成时的回调函数
onProgress:在加载过程中调用,用于监控加载进度
onError:加载错误时回调
在前期的学习和开发中,笔者建议始终添加onError参数来监控加载情况,后续讲到模型加载时会再提这方面事宜
let textureLoader = new THREE.TextureLoader();textureLoader.load("./gr2ass.jpg",(texture)=>{let geometry = new THREE.PlaneGeometry(10,10,10).rotateX(-Math.PI/2);let material = new THREE.MeshBasicMaterial({map:texture});let mesh = new THREE.Mesh(geometry,material);scene.add(mesh);},null,(error)=>{console.log(error);});
如果仅对一个文件做加载时,onProgress函数可以先写为null
在onLoad函数中,我们可以获取到加载完成的资源,textureLoader中,已经将生成好的纹理,以对象的方式返回给我们了,所以这里我们直接访问它即可
官方写法中,并没有使用()=>{}这样的箭头函数,这种写法容易造成this指向错误,所以这里笔者建议,从这里开始,每一个Load函数,都使用箭头函数,以免出现一些奇奇怪怪的问题
箭头函数为ES6的语法,不熟悉ES6的同学这时还可以去了解一下
当我们拿到了加载完成后的纹理后,将它作为值,传给Material的map属性
let material = new THREE.MeshBasicMaterial({map:texture});
如果这里再添加Color属性的话,Color会覆盖当前加载出来的纹理颜色
这样我们的草地就被创建出来了
案例完整源码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>canvas{display: block;}body {margin: 0;overscroll-behavior: none;}#btns{position: absolute;top:10%;width: 500px;height: 100px;left: 50%;transform:translateX(-50%);}</style>
</head>
<body>
<div id="btns"></div><!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script><script type="importmap">{"imports": {"three": "../../three.js-master/build/three.module.js"}}</script>
<script type="module">import * as THREE from '../../three.js-master/build/three.module.js';import {OrbitControls} from "../../three.js-master/examples/jsm/controls/OrbitControls.js";let scene,renderer,camera,orbitControls;function init(){scene = new THREE.Scene();renderer = new THREE.WebGLRenderer({alpha:true,antialias:true});renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(renderer.domElement);camera = new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,1,1000);camera.position.set(10,10,10);orbitControls = new OrbitControls(camera,renderer.domElement);scene.add(new THREE.AmbientLight(0xffffff,1));let helper = new THREE.AxesHelper(5);scene.add(helper);}function addMesh(){let textureLoader = new THREE.TextureLoader();textureLoader.load("./grass.jpg",(texture)=>{let geometry = new THREE.PlaneGeometry(10,10,10).rotateX(-Math.PI/2);let material = new THREE.MeshBasicMaterial({map:texture});let mesh = new THREE.Mesh(geometry,material);scene.add(mesh);},null,(error)=>{console.log(error);});}function render(){renderer.render(scene,camera);requestAnimationFrame(render);}init();addMesh();render();
</script>
</body>
</html>
案例使用的图片文件,图片来源:three.js-master\examples\textures\terrain下的草地贴图
做一个简单的地球出来
上面我们学会了怎么使用纹理,那么,这次我们不再将纹理贴到plane上,贴到我们的球体Sphere上
地球的贴图素材three.js-master\examples\textures\planets,这里我们选用的素材是earth_atmos_2048.jpg
完整代码
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>canvas{display: block;}body {margin: 0;overscroll-behavior: none;}#btns{position: absolute;top:10%;width: 500px;height: 100px;left: 50%;transform:translateX(-50%);}</style>
</head>
<body>
<div id="btns"></div><!-- Import maps polyfill -->
<!-- Remove this when import maps will be widely supported -->
<script async src="https://unpkg.com/es-module-shims@1.3.6/dist/es-module-shims.js"></script><script type="importmap">{"imports": {"three": "../../three.js-master/build/three.module.js"}}</script>
<script type="module">import * as THREE from '../../three.js-master/build/three.module.js';import {OrbitControls} from "../../three.js-master/examples/jsm/controls/OrbitControls.js";let scene,renderer,camera,orbitControls;function init(){scene = new THREE.Scene();renderer = new THREE.WebGLRenderer({antialias:true});renderer.setSize(window.innerWidth,window.innerHeight);document.body.appendChild(renderer.domElement);camera = new THREE.PerspectiveCamera(60,window.innerWidth/window.innerHeight,1,1000);camera.position.set(10,10,10);orbitControls = new OrbitControls(camera,renderer.domElement);let helper = new THREE.AxesHelper(5);scene.add(helper);let light = new THREE.PointLight();camera.add(light);scene.add(camera);}function addMesh(){let textureLoader = new THREE.TextureLoader();textureLoader.load("./earth_atmos_2048.jpg",(texture)=>{let geometry = new THREE.SphereGeometry(5,32,32);let material = new THREE.MeshStandardMaterial({map:texture});let mesh = new THREE.Mesh(geometry,material);scene.add(mesh);},null,(error)=>{console.log(error);});}function render(){renderer.render(scene,camera);requestAnimationFrame(render);}init();addMesh();render();
</script>
</body>
</html>
完整效果:
大多数知识点在前面已经解析完成,笔者在这里就不多做解释了
下一篇预告:加载模型
下一篇主要讲解主流的几种模型格式与Loader,以及加载管理器LoadingManager
【ThreeJS基础教程-高级几何体篇】2.1更好的视觉效果-综合案例(2)相关推荐
- 【ThreeJS基础教程-高级几何体篇】2.6.1 BufferGeometry应用1-物体居中与包围盒的应用
BufferGeometry应用1-物体居中与包围盒的应用 学习ThreeJS的捷径 问题案例:为什么会围绕Y轴旋转 问题代码 案例效果 模型中心的概念 包围盒简介 修正Mesh中心到包围盒中心 关于 ...
- 【ThreeJS基础教程-材质纹理篇】3.2 初识基础网格材质MeshStandardMaterial
初识标准网格材质 学习ThreeJS的捷径 了解材质的基本知识 材质继承关系 常用的通用材质属性 alphaTest的验证和应用 depthTest和depthWrite应用 渲染哪一面Side 常用 ...
- 【ThreeJS基础教程-材质纹理篇】3.1 纹理知识进阶
纹理知识进阶 学习ThreeJS的捷径 如何用一张地板砖贴图制作出地板砖效果 旋转纹理 移动纹理 纹理旋转与移动的应用 简单的光圈效果 简单的流水效果 WebGL项目优化技巧:没必要的细节可以用纹理直 ...
- 【ThreeJS基础教程】0.在学习使用ThreeJS之前
[ThreeJS基础教程]0.在学习使用ThreeJS之前 什么人适合学习ThreeJS 什么人不建议学习ThreeJS或学起来比较累 了解ThreeJS ThreeJS文档在哪 关于<Thre ...
- 人工智能python自学教程-人工智能基础教程:Python篇(青少版)
人工智能基础教程:Python篇(青少版) 编辑推荐 源代码及PPT下载:https://pan.baidu.com/s/1mWa2fy457fhUXKxT-FgyPw 哈工智诚在线编程云平台:htt ...
- EGE基础:高级绘图篇
EGE专栏:EGE专栏 目录 一. EGE中的高级绘图函数 1. 高级绘图函数相比普通绘图函数的优势 1.1 图形边缘更为光滑 1.2 图形具有透明度 二. 高级函数的使用设置 1. 高级绘图函数设置 ...
- python人工智能编程教程-清华大学出版社-图书详情-《人工智能基础教程:Python篇(青少版)》...
2017 年国务院印发了<关于印发新一代人工智能发展规划的通知>,提出要围绕教育. 医疗.养老等迫切民生需求,加快人工智能创新应用.要发展智能教育,利用智能技术加 快推动人才培养模式.教学 ...
- 【ThreeJS基础教程-初识Threejs】1.2掌控我们的物体和模型
掌控我们的物体和模型 学习ThreeJS的捷径 引入帧数监控与调试时使用的GUI 案例解析 引入刷新率检测器stats和lil-gui Stats LIL.GUI (Dat.GUI) 学习ThreeJ ...
- DirectX12(D3D12)基础教程(外篇一)——编译Assimp
目录 1.前言 2.Assimp库简介 3.编译Assimp库的准备工作 4.下载Assimp源码并编译 1.前言 D3D12系列教程因为我转移精力学习Nodejs.VueJs等技能,暂时中断了一 ...
最新文章
- laravel博客中文章删除遇到问题
- 教你编写Node.js中间件,实现服务端缓存
- 手动用hibernate-validator校验入参
- 多元时代个人信息更需强有力保护
- TEDxChengdu 演讲(瞬雨)
- Mysql 创建表、存储过程、触发器 -Angelo 分享
- 那些让程序员提升30-80%的快捷键大全整理
- J2EE 第二阶段项目之JUnit4进行单元测试(五)
- 大连理工大学计算机组织与结构实验,大连理工大学计算机系统结构实验-实验四.doc...
- HTML代码页面无法跳转为什么,html超链接不跳转 html为什么超链接不跳转页面
- Springboot集成Quartz定时任务,项目启动执行任务
- RGMII信号是什么样子的----大揭秘
- 参加2022 年第四届齐鲁工业大学(山东省科学院)与山东师范大学ICPC 大学生程序设计竞赛的总结
- VARCHART XGantt v5.2用户手册:甘特图如何Drag Drop
- python爬取下厨房每周最受欢迎菜谱
- CentOS 7.9 安装NVIDIA 显卡驱动
- JAVA商城 B2B2C商城系统 多用户商城系统 直播带货 新零售商城 o2o商城 电子商务 拼团商城 分销商城 直播商城 短视频商城 springcloud商城 spring cloud商城
- Ghost XP SP2下如何安装IIS的解决方案
- 关于U盘存储大量小容量文件速度慢的解释(摘抄)
- 【CAN通信】CAN协议详解