2.1更好的视觉效果-综合案例(2

  • 学习ThreeJS的捷径
  • 初识纹理Texture
    • 如何生成一片草地
    • Texture与TextureLoader
  • 做一个简单的地球出来
  • 下一篇预告:加载模型

学习ThreeJS的捷径

本段内容会写在0篇以外所有的,本人所编写的Threejs教程中

对,学习ThreeJS有捷径
当你有哪个函数不懂的时候,第一时间去翻一翻文档
当你有哪个效果不会做的时候,第一时间去翻一翻所有的案例,也许就能找到你想要的效果
最重要的一点,就是,绝对不要怕问问题,越怕找找别人问题,你的问题就会被拖的越久

如果你确定要走WebGL/ThreeJS的开发者路线的话,以下行为可以让你更快的学习ThreeJS

  1. 没事就把所有的文档翻一遍,哪怕看不懂,也要留个印象,至少要知道Threejs有什么
  2. 没事多看看案例效果,当你记忆的案例效果足够多时,下次再遇到相似问题时,你就有可能第一时间来找对应的案例,能更快解决你自己的问题
  3. 上述案例不只是官网的案例,郭隆邦技术博客,跃焱邵隼,暮志未晚等站点均有不少优质案例,记得一并收藏
    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)相关推荐

  1. 【ThreeJS基础教程-高级几何体篇】2.6.1 BufferGeometry应用1-物体居中与包围盒的应用

    BufferGeometry应用1-物体居中与包围盒的应用 学习ThreeJS的捷径 问题案例:为什么会围绕Y轴旋转 问题代码 案例效果 模型中心的概念 包围盒简介 修正Mesh中心到包围盒中心 关于 ...

  2. 【ThreeJS基础教程-材质纹理篇】3.2 初识基础网格材质MeshStandardMaterial

    初识标准网格材质 学习ThreeJS的捷径 了解材质的基本知识 材质继承关系 常用的通用材质属性 alphaTest的验证和应用 depthTest和depthWrite应用 渲染哪一面Side 常用 ...

  3. 【ThreeJS基础教程-材质纹理篇】3.1 纹理知识进阶

    纹理知识进阶 学习ThreeJS的捷径 如何用一张地板砖贴图制作出地板砖效果 旋转纹理 移动纹理 纹理旋转与移动的应用 简单的光圈效果 简单的流水效果 WebGL项目优化技巧:没必要的细节可以用纹理直 ...

  4. 【ThreeJS基础教程】0.在学习使用ThreeJS之前

    [ThreeJS基础教程]0.在学习使用ThreeJS之前 什么人适合学习ThreeJS 什么人不建议学习ThreeJS或学起来比较累 了解ThreeJS ThreeJS文档在哪 关于<Thre ...

  5. 人工智能python自学教程-人工智能基础教程:Python篇(青少版)

    人工智能基础教程:Python篇(青少版) 编辑推荐 源代码及PPT下载:https://pan.baidu.com/s/1mWa2fy457fhUXKxT-FgyPw 哈工智诚在线编程云平台:htt ...

  6. EGE基础:高级绘图篇

    EGE专栏:EGE专栏 目录 一. EGE中的高级绘图函数 1. 高级绘图函数相比普通绘图函数的优势 1.1 图形边缘更为光滑 1.2 图形具有透明度 二. 高级函数的使用设置 1. 高级绘图函数设置 ...

  7. python人工智能编程教程-清华大学出版社-图书详情-《人工智能基础教程:Python篇(青少版)》...

    2017 年国务院印发了<关于印发新一代人工智能发展规划的通知>,提出要围绕教育. 医疗.养老等迫切民生需求,加快人工智能创新应用.要发展智能教育,利用智能技术加 快推动人才培养模式.教学 ...

  8. 【ThreeJS基础教程-初识Threejs】1.2掌控我们的物体和模型

    掌控我们的物体和模型 学习ThreeJS的捷径 引入帧数监控与调试时使用的GUI 案例解析 引入刷新率检测器stats和lil-gui Stats LIL.GUI (Dat.GUI) 学习ThreeJ ...

  9. DirectX12(D3D12)基础教程(外篇一)——编译Assimp

    目录 1.前言 2.Assimp库简介 3.编译Assimp库的准备工作 4.下载Assimp源码并编译 1.前言   D3D12系列教程因为我转移精力学习Nodejs.VueJs等技能,暂时中断了一 ...

最新文章

  1. laravel博客中文章删除遇到问题
  2. 教你编写Node.js中间件,实现服务端缓存
  3. 手动用hibernate-validator校验入参
  4. 多元时代个人信息更需强有力保护
  5. TEDxChengdu 演讲(瞬雨)
  6. Mysql 创建表、存储过程、触发器 -Angelo 分享
  7. 那些让程序员提升30-80%的快捷键大全整理
  8. J2EE 第二阶段项目之JUnit4进行单元测试(五)
  9. 大连理工大学计算机组织与结构实验,大连理工大学计算机系统结构实验-实验四.doc...
  10. HTML代码页面无法跳转为什么,html超链接不跳转 html为什么超链接不跳转页面
  11. Springboot集成Quartz定时任务,项目启动执行任务
  12. RGMII信号是什么样子的----大揭秘
  13. 参加2022 年第四届齐鲁工业大学(山东省科学院)与山东师范大学ICPC 大学生程序设计竞赛的总结
  14. VARCHART XGantt v5.2用户手册:甘特图如何Drag Drop
  15. python爬取下厨房每周最受欢迎菜谱
  16. CentOS 7.9 安装NVIDIA 显卡驱动
  17. JAVA商城 B2B2C商城系统 多用户商城系统 直播带货 新零售商城 o2o商城 电子商务 拼团商城 分销商城 直播商城 短视频商城 springcloud商城 spring cloud商城
  18. Ghost XP SP2下如何安装IIS的解决方案
  19. 关于U盘存储大量小容量文件速度慢的解释(摘抄)
  20. 【CAN通信】CAN协议详解

热门文章

  1. python面试大全 萧井陌_Python就该这么学?!
  2. 电脑管家独立版 v3.1 官方版
  3. Spring核心容器
  4. MQ消息队列数据丢失问题
  5. 转载的HTTP长连接短连接和无状态的理解
  6. Android 在线预览ppt、doc、xls、txt等文件
  7. 形式语言与自动机——第二章 自动机
  8. freetype使用文泉驿显示及保存图片
  9. oracle table()函数
  10. 项目经理应具备的关键能力