【ThreeJS基础教程-初识Threejs】1.4.1 更好的视觉效果-使用材质与灯光

本文主要是介绍【ThreeJS基础教程-初识Threejs】1.4.1 更好的视觉效果-使用材质与灯光,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

更好的视觉效果-使用材质与灯光

  • 学习ThreeJS的捷径
  • 使用灯光与材质
  • 案例解析
    • 使用MeshStandardMaterial给演员换身新衣服
    • 用灯光照亮换了新衣服(新材质)的演员(方块)
    • 控制开关灯
    • 我想知道灯光在哪
    • 我觉得场景太暗了
    • 环境光AmbientLight
    • 使用lil.gui(dat.gui)来控制灯光强度和颜色,以调整到一个比较完美的效果
  • 完整demo代码:

学习ThreeJS的捷径

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

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

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

  1. 没事就把所有的文档翻一遍,哪怕看不懂,也要留个印象,至少要知道Threejs有什么
  2. 没事多看看案例效果,当你记忆的案例效果足够多时,下次再遇到相似问题时,你就有可能第一时间来找对应的案例,能更快解决你自己的问题
  3. 上述案例不只是官网的案例,郭隆邦技术博客,跃焱邵隼,暮志未晚等站点均有不少优质案例,记得一并收藏
    http://www.yanhuangxueyuan.com/ 郭隆邦技术博客
    https://www.wellyyss.cn/ 跃焱邵隼
    http://www.wjceo.com/ 暮志未晚
    这三个站点是我最常逛的站点,推荐各位有事没事逛一下,看看他们的案例和写法思路,绝对没坏处

使用灯光与材质

<!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"><input type="button" value="关灯" id="openLight">
</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";import {GUI} from "../three.js-master/examples/jsm/libs/lil-gui.module.min.js"import Stats from "../three.js-master/examples/jsm/libs/stats.module.js"let scene,renderer,camera,orbitControls;let stats,gui;let light;let mesh;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);light = new THREE.PointLight(0xffffff,1.0);light.position.y += 5;scene.add(light);stats = new Stats({width:500});document.body.appendChild(stats.dom);gui = new GUI();}function addMesh(){let geometry = new THREE.BoxGeometry(1,1,1);let material = new THREE.MeshStandardMaterial({color:"#ff0000"});mesh = new THREE.Mesh(geometry,material);scene.add(mesh);}function addGUI(){}function addEvent(){let btn = document.getElementById("openLight");btn.onclick = ()=>{if(light.intensity === 0){light.intensity = 1;btn.value = "关灯";}else{light.intensity = 0;btn.value = "开灯";}}}function render(){renderer.render(scene,camera);requestAnimationFrame(render);mesh.rotation.x += 0.01;mesh.rotation.y += 0.01;stats.update();}init();addMesh();addGUI();addEvent();render();
</script>
</body>
</html>

关灯效果
开灯效果

本案例中,我们去掉了渲染器设置的背景透明,使用了默认颜色的背景

在关灯状态下,我们只能看到有一个方块在中心旋转,但是我们无法区分它的颜色

在开灯状态下,我们就能看到这个方块,同时,我们也能看清楚它的棱角了,比起之前的纯色方块来说,这个方块的效果要好一些

案例解析

多数代码在我的前面几篇文章已经解析完成,本篇仅针对新出现的代码进行解析

使用MeshStandardMaterial给演员换身新衣服

        let geometry = new THREE.BoxGeometry(1,1,1);let material = new THREE.MeshStandardMaterial({color:"#ff0000"});mesh = new THREE.Mesh(geometry,material);scene.add(mesh);

前一篇的addMesh()函数中,我们使用的是MeshBasicMaterial,MeshBasicMaterial是一种不受光照影响的材质,关于MeshBasicMaterial的使用技巧和应用范围将在后面单独出一篇教程详细介绍

本篇这里使用的材质为:MeshStandaradMaterial(标准网格材质)
以下为官方解释
在这里插入图片描述
https://threejs.org/docs/index.html?q=meshs#api/zh/materials/MeshStandardMaterial

当然,官方的解释不只是这些,这里我们只需要先知道,这种材质会受到光照影响,如果场景中完全没有灯光,或者灯光亮度为0时,我们将什么都看不到,只有一片黑

如果把方块看做演员,MeshBasic材质这种不受光照影响的,可以认为是穿了夜光的衣服,而MeshStandardMaterial是一种更复杂的材料,而初始的状态是需要有光才能看到

现实中亦是如此,在完全黑暗的屋子下,我们什么也看不到

用灯光照亮换了新衣服(新材质)的演员(方块)

既然我们的演员的衣服不带夜光,那么我们就要给它添加一盏灯

这里我们选用点光源来模拟灯泡效果

       light = new THREE.PointLight(0xffffff,1.0);light.position.y += 5;scene.add(light);

这里因为我们需要用按钮控制灯光,且单独用一个addEvent()专门添加dom事件,所以这里将灯光写在全局变量中,正常的开发中,如果不涉及灯光的改变效果,灯光可以不放到全局变量

构造器:new PointLight( color:Integer, intensity:Float ,distance:Number,decay:Float);
color:灯光颜色
intensity:灯光亮度
distance : 灯光的辐射范围,以现实中的灯泡来说,灯泡一般都会有一个照亮范围,距离越近越亮,一直到某个地方光完全消失,distance就是用于控制点光源照亮极限的属性,默认为无限大,根据实际情况使用该值即可
decay: 官方解释为:沿着光照距离的衰退量,本案例中并未使用,暂时可以先不用刻意去理解它,感兴趣的同学可以单独开一个案例自己先研究研究

后续会专门有一篇教程来介绍点光源,本篇仅使用color和intensity,下面的两个属性建议现在了解即可

在这里插入图片描述
点光源官方文档:https://threejs.org/docs/index.html?q=light#api/zh/lights/PointLight

当你的灯光是白色,且亮度为1时,创建灯光时可以直接这样写:

light = new THREE.PointLight(); 

默认值其实就是颜色白色,灯光强度为1

然后就是灯泡要放到演员上方,如果放在(0,0,0)点的话,就放在了方块内部,在内部是不可能照亮外部的(StandardMaterial并不是透光材料)
所以这里我们将灯光移动到了(0,5,0)的位置

	light.position.y += 5;

最后我们把灯光添加到场景中即可

	scene.add(light)

控制开关灯

在这篇教程中,笔者添加了一组用于添加按钮的< div >并添加了对应的css,后续的按钮均会添加到这里,按钮事件的绑定与css的部分在这里不做任何讲解,能看到这里的基本上都是有一定经验的前端了,无需多做解释

    function addEvent(){let btn = document.getElementById("openLight");btn.onclick = ()=>{if(light.intensity === 0){light.intensity = 1;btn.value = "关灯";}else{light.intensity = 0;btn.value = "开灯";}}}

这里我们判断灯光的当前强度,当灯光强度为1时,我们的按钮显示文字为关灯,点击按钮效果设置为让灯光强度设置为0

我想知道灯光在哪

这里我们可以在创建好灯光后,添加这样一个Helper

        let pointLightHelper = new THREE.PointLightHelper( light, 1 );scene.add( pointLightHelper );

pointlightHelper官方文档
https://threejs.org/docs/index.html?q=light#api/zh/helpers/PointLightHelper
在这里插入图片描述

添加helper之后的效果
在这里插入图片描述

我觉得场景太暗了

那么我们可以添加一个环境光,同时降低点光源的亮度,使场景亮度保持在1左右

	let ambientLight = new THREE.AmbientLight( 0xffffff,0.5);scene.add(ambientLight)light = new THREE.PointLight(0xffffff,0.5);light.position.y += 5;scene.add(light);

在这里插入图片描述

这样既保持了方块的明暗效果,同时也让过暗的地方变的稍微能够看到一些

环境光AmbientLight

构造器:new AmbientLight( color, intensity)
color:灯光颜色
intensity:灯光强度
环境光会影响整个场景的亮度,但不包括设置了不受光照影响材质的物体,如MeshBasicMaterial的物体均不会受环境光影响

官方文档
https://threejs.org/docs/index.html?q=light#api/zh/lights/AmbientLight
在这里插入图片描述

使用lil.gui(dat.gui)来控制灯光强度和颜色,以调整到一个比较完美的效果

    function addGUI(){let params = {pointLightIntensity:light.intensity,pointLightColor:"#ffffff",ambientIntensity:ambientLight.intensity,ambientColor:"#ffffff"};gui.add(params,"pointLightIntensity",0,2).step(0.01).name("点光源亮度").onChange((value)=>{light.intensity = value;});gui.add(params,"ambientIntensity",0,2).step(0.01).name("环境光亮度").onChange((value)=>{ambientLight.intensity = value;});gui.addColor(params,'pointLightColor').listen().name('点光源颜色').onChange(function (value){light.color = new THREE.Color(value);});gui.addColor(params,'ambientColor').listen().name('环境光颜色').onChange(function (value){ambientLight.color = new THREE.Color(value);});}

同时,我们把创建Mesh的MeshStandardMaterial修改为白色,使得默认创建一个白色方块

        let material = new THREE.MeshStandardMaterial({color:"#ffffff"});

在这里插入图片描述
接下来就可以享受一下设计们的工作了,调整光源颜色和光照强度
就请各位亲自操作一下,感受一下光,点光源和环境光对物体的影响

函数: gui.addColor(对象,属性名)
这里我们创建了一个单独的params,用于方便处理颜色
函数:gui.addColor().listen() 用于监听事件动态改变颜色

其他用法均与之前介绍的dat.gui的用法一致

我们这里修改颜色使用color = new THREE.Color(),主要目的是语义明确

当我们在调试方块的时候,发现了一个问题,就是,我们的开灯和关灯,设置了灯光强度,但是右上角的LIL.GUI没有跟着变化,此时只需要手动修改一下它的值即可

但是这个功能并不常用,一般情况下,lil.gui是不会应用到实际项目中,这个gui实在太low了,还是老老实实用于调试程序比较好

function addEvent(){let btn = document.getElementById("openLight");btn.onclick = ()=>{if(light.intensity === 0){light.intensity = 1;btn.value = "关灯";gui.children[0].setValue(1);}else{light.intensity = 0;btn.value = "开灯";gui.children[0].setValue(0);}}}

函数:gui.children[0].setValue() 用于手动更新lil.gui的值

完整demo代码:

<!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"><input type="button" value="关灯" id="openLight">
</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";import {GUI} from "../three.js-master/examples/jsm/libs/lil-gui.module.min.js"import Stats from "../three.js-master/examples/jsm/libs/stats.module.js"let scene,renderer,camera,orbitControls;let stats,gui;let light,ambientLight;let mesh;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);ambientLight = new THREE.AmbientLight( 0xffffff,0.3);scene.add(ambientLight)light = new THREE.PointLight(0xffffff,0.7);light.position.y += 5;scene.add(light);let pointLightHelper = new THREE.PointLightHelper( light, 1 );scene.add( pointLightHelper );stats = new Stats({width:500});document.body.appendChild(stats.dom);gui = new GUI();}function addMesh(){let geometry = new THREE.BoxGeometry(1,1,1);let material = new THREE.MeshStandardMaterial({color:"#ffffff"});mesh = new THREE.Mesh(geometry,material);scene.add(mesh);}function addGUI(){let params = {pointLightIntensity:light.intensity,pointLightColor:"#ffffff",ambientIntensity:ambientLight.intensity,ambientColor:"#ffffff"};gui.add(params,"pointLightIntensity",0,2).step(0.01).name("点光源亮度").onChange((value)=>{light.intensity = value;});gui.add(params,"ambientIntensity",0,2).step(0.01).name("环境光亮度").onChange((value)=>{ambientLight.intensity = value;});gui.addColor(params,'pointLightColor').listen().name('点光源颜色').onChange(function (value){light.color = new THREE.Color(value);});gui.addColor(params,'ambientColor').listen().name('环境光颜色').onChange(function (value){ambientLight.color = new THREE.Color(value);});}function addEvent(){let btn = document.getElementById("openLight");btn.onclick = ()=>{if(light.intensity === 0){light.intensity = 1;btn.value = "关灯";gui.children[0].setValue(1);}else{light.intensity = 0;btn.value = "开灯";gui.children[0].setValue(0);}}}function render(){renderer.render(scene,camera);requestAnimationFrame(render);mesh.rotation.x += 0.01;mesh.rotation.y += 0.01;stats.update();}init();addMesh();addGUI();addEvent();render();
</script>
</body>
</html>

这篇关于【ThreeJS基础教程-初识Threejs】1.4.1 更好的视觉效果-使用材质与灯光的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/176435

相关文章

中文分词jieba库的使用与实景应用(一)

知识星球:https://articles.zsxq.com/id_fxvgc803qmr2.html 目录 一.定义: 精确模式(默认模式): 全模式: 搜索引擎模式: paddle 模式(基于深度学习的分词模式): 二 自定义词典 三.文本解析   调整词出现的频率 四. 关键词提取 A. 基于TF-IDF算法的关键词提取 B. 基于TextRank算法的关键词提取

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

Hadoop数据压缩使用介绍

一、压缩原则 (1)运算密集型的Job,少用压缩 (2)IO密集型的Job,多用压缩 二、压缩算法比较 三、压缩位置选择 四、压缩参数配置 1)为了支持多种压缩/解压缩算法,Hadoop引入了编码/解码器 2)要在Hadoop中启用压缩,可以配置如下参数

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]

git使用的说明总结

Git使用说明 下载安装(下载地址) macOS: Git - Downloading macOS Windows: Git - Downloading Windows Linux/Unix: Git (git-scm.com) 创建新仓库 本地创建新仓库:创建新文件夹,进入文件夹目录,执行指令 git init ,用以创建新的git 克隆仓库 执行指令用以创建一个本地仓库的

【北交大信息所AI-Max2】使用方法

BJTU信息所集群AI_MAX2使用方法 使用的前提是预约到相应的算力卡,拥有登录权限的账号密码,一般为导师组共用一个。 有浏览器、ssh工具就可以。 1.新建集群Terminal 浏览器登陆10.126.62.75 (如果是1集群把75改成66) 交互式开发 执行器选Terminal 密码随便设一个(需记住) 工作空间:私有数据、全部文件 加速器选GeForce_RTX_2080_Ti

【Linux 从基础到进阶】Ansible自动化运维工具使用

Ansible自动化运维工具使用 Ansible 是一款开源的自动化运维工具,采用无代理架构(agentless),基于 SSH 连接进行管理,具有简单易用、灵活强大、可扩展性高等特点。它广泛用于服务器管理、应用部署、配置管理等任务。本文将介绍 Ansible 的安装、基本使用方法及一些实际运维场景中的应用,旨在帮助运维人员快速上手并熟练运用 Ansible。 1. Ansible的核心概念