ThreeJS-3D教学五-材质

我们在ThreeJS-3D教学二:基础形状展示中有简单介绍过一些常用的材质,这次我们举例来具体看下效果:
在这里插入图片描述
代码是这样的:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>body {width: 100%;height: 100%;}* {margin: 0;padding: 0;}.label {font-size: 20px;color: #000;font-weight: 700;}</style>
</head>
<body>
<div id="container"></div>
<script type="importmap">{"imports": {"three": "../three-155/build/three.module.js","three/addons/": "../three-155/examples/jsm/"}}
</script>
<script type="module">
import * as THREE from 'three';
import Stats from 'three/addons/libs/stats.module.js';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { GPUStatsPanel } from 'three/addons/utils/GPUStatsPanel.js';
import { CSS2DRenderer, CSS2DObject } from 'three/addons/renderers/CSS2DRenderer.js';
let stats, labelRenderer, gpuPanel, spotLight;
let camera, scene, renderer, controls, earth;
const group = new THREE.Group();
let widthImg = 200;
let heightImg = 200;
let time = 0;
init();
initHelp();
initLight();
axesHelperWord();
animate();
// 添加平面
addPlane();
addBox();function addBox() {/*** 凹凸贴图可以使纹理也有厚度,看起来更立体。凹凸贴图一般使用一张灰度图,设置成材料的bumpMap属性* */const loader = new THREE.TextureLoader();loader.load("../materials/line_images/stone.jpg", texture => {loader.load("../materials/line_images/stone-bump.jpg",bumpTexture => {const boxGeo = new THREE.BoxGeometry(60, 60, 2);const material = new THREE.MeshStandardMaterial({map: texture,bumpMap: bumpTexture,bumpScale: 1});const box = new THREE.Mesh(boxGeo,material);box.position.set(-45, 10, 0);box.castShadow = true;scene.add(box);});});/*** 法向贴图使用一张法向图来表示纹理图片某个点的法向量。即用一张图片保存另一张图片的法向量信息,* 然后再在threejs中将这两个图片的信息合在一起,就形成了一个细节丰富的立体纹理* 设置材质的 normalMap 属性* */loader.load("../materials/line_images/normal2.jpg", texture => {loader.load("../materials/line_images/normal1.jpg", bumpTexture => {const boxGeo = new THREE.BoxGeometry(60, 60, 2);const material = new THREE.MeshStandardMaterial({map: texture,normalMap: bumpTexture});// material.normalScale.set(1, 1)const box = new THREE.Mesh(boxGeo,material);box.position.set(45, 10, 0);box.castShadow = true;scene.add(box);});});// 高光贴图loader.load("../materials/line_images/earth.jpg",textureNormal => {loader.load("../materials/line_images/earthSpec.png", textureSpec => {const meterial = new THREE.MeshPhongMaterial({shininess: 5, //高光部分的亮度,默认30map: textureNormal, // 普通纹理贴图specularMap: textureSpec, // 高光贴图specular: '#fff' // 高光部分的颜色});/**SphereGeometry(radius:浮点,widthSegments:整数,heightSegments:整数)radius——球体半径。默认值为1。widthSegments—水平线段的数量。最小值为3,默认值为32。heightSegments—垂直线段的数量。最小值为2,默认值为16。*/const earthGeo = new THREE.SphereGeometry(15, 50, 50);earth = new THREE.Mesh(earthGeo, meterial);earth.position.set(0, 15, 70);earth.castShadow = true;scene.add(earth);});});
}function addPlane() {// 创建一个平面 PlaneGeometry(width, height, widthSegments, heightSegments)const planeGeometry = new THREE.PlaneGeometry(widthImg, heightImg, 1, 1);// 创建 Lambert 材质:会对场景中的光源作出反应,但表现为暗淡,而不光亮。const planeMaterial = new THREE.MeshPhongMaterial({color: 0xb2d3e6,side: THREE.DoubleSide});const plane = new THREE.Mesh(planeGeometry, planeMaterial);// 以自身中心为旋转轴,绕 x 轴顺时针旋转 45 度plane.rotation.x = -0.5 * Math.PI;plane.position.set(0, -4, 0);plane.castShadow = true;plane.receiveShadow = true;scene.add(plane);
}function init() {camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 10, 1000 );camera.up.set(0, 1, 0);camera.position.set(60, 40, 60);camera.lookAt(0, 0, 0);scene = new THREE.Scene();scene.background = new THREE.Color( '#ccc' );renderer = new THREE.WebGLRenderer( { antialias: true } );renderer.setPixelRatio( window.devicePixelRatio );renderer.setSize( window.innerWidth, window.innerHeight );renderer.shadowMap.enabled = true;renderer.shadowMap.type = THREE.PCFSoftShadowMap;renderer.toneMapping = THREE.ACESFilmicToneMapping;// 色调映射的曝光级别renderer.toneMappingExposure = 1;document.body.appendChild( renderer.domElement );labelRenderer = new CSS2DRenderer();labelRenderer.setSize( window.innerWidth, window.innerHeight );labelRenderer.domElement.style.position = 'absolute';labelRenderer.domElement.style.top = '0px';labelRenderer.domElement.style.pointerEvents = 'none';document.getElementById( 'container' ).appendChild( labelRenderer.domElement );controls = new OrbitControls( camera, renderer.domElement );// 设置最大最小视距controls.minDistance = 20;controls.maxDistance = 1000;window.addEventListener( 'resize', onWindowResize );stats = new Stats();stats.setMode(1); // 0: fps, 1: msdocument.body.appendChild( stats.dom );gpuPanel = new GPUStatsPanel( renderer.getContext() );stats.addPanel( gpuPanel );stats.showPanel( 0 );scene.add( group );
}function initLight() {const targetObject = new THREE.Object3D();targetObject.position.set(0, 0, 0);scene.add(targetObject);spotLight = new THREE.SpotLight(0xffffff);spotLight.position.set(0, 80, 150);spotLight.target = targetObject;spotLight.angle = Math.PI / 4;spotLight.intensity = 500;spotLight.penumbra = 1;spotLight.decay = 1;spotLight.distance = 300;// spotLight.map = textures['uv_grid_opengl.jpg'];spotLight.castShadow = true;spotLight.shadow.mapSize.width = 1024;spotLight.shadow.mapSize.height = 1024;spotLight.shadow.camera.near = 1;spotLight.shadow.camera.far = 200;spotLight.shadow.focus = 1;scene.add(spotLight);const lightHelper = new THREE.SpotLightHelper(spotLight);scene.add(lightHelper);const AmbientLight = new THREE.AmbientLight(new THREE.Color('rgb(255, 255, 255)'));scene.add( AmbientLight );
}function initHelp() {// const size = 100;// const divisions = 5;// const gridHelper = new THREE.GridHelper( size, divisions );// scene.add( gridHelper );// The X axis is red. The Y axis is green. The Z axis is blue.const axesHelper = new THREE.AxesHelper( 100 );scene.add( axesHelper );
}function axesHelperWord() {let xP = addWord('X轴');let yP = addWord('Y轴');let zP = addWord('Z轴');xP.position.set(50, 0, 0);yP.position.set(0, 50, 0);zP.position.set(0, 0, 50);
}function addWord(word) {let name = `<span>${word}</span>`;let moonDiv = document.createElement( 'div' );moonDiv.className = 'label';// moonDiv.textContent = 'Moon';// moonDiv.style.marginTop = '-1em';moonDiv.innerHTML = name;const label = new CSS2DObject( moonDiv );group.add( label );return label;
}function onWindowResize() {camera.aspect = window.innerWidth / window.innerHeight;camera.updateProjectionMatrix();renderer.setSize( window.innerWidth, window.innerHeight );
}function animate() {requestAnimationFrame( animate );if (earth) {time += 0.00005;earth.rotateY(time);}stats.update();controls.update();labelRenderer.render( scene, camera );renderer.render( scene, camera );
}
</script>
</body>
</html>

图片我依次放进来,方便大家本地看效果

stone.jpg

在这里插入图片描述

stone-bump.jpg

在这里插入图片描述

normal2.jpg

在这里插入图片描述

normal1.jpg

在这里插入图片描述

earth.jpg

在这里插入图片描述

earthSpec.png

在这里插入图片描述
具体的注释也都放代码里了!感觉不错的点个赞,光白嫖可还行!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/154056.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Qt】三种方式实现抽奖小游戏

简介 本文章是基本Qt与C实现一个抽奖小游戏&#xff0c;用到的知识点在此前发布的几篇文章。 下面是跳转链接&#xff1a; 【Qt控件之QLabel】用法及技巧链接&#xff1a; https://blog.csdn.net/MrHHHHHH/article/details/133691441?spm1001.2014.3001.5501 【Qt控件之QPus…

CRMEB 标准版商城系统新增主题风格颜色【超级完整教程】

一、后台 1.新增主题图片 assets/images/brown.jpg和assets/images/brownsign.png 2.修改admin/src/pages/setting/themeStyle/index.vue 3.修改admin/src/pages/marketing/sign/index.vue 4.修改admin/src/pages/system/group/visualization.vue &#xff08;第三步和第四步…

嵌入式养成计划-33--数据库-sqlite3

七十一、 数据库 71.1 数据库基本概念 数据&#xff08;Data&#xff09; 能够输入计算机并能被计算机程序识别和处理的信息集合数据库 &#xff08;Database&#xff09;数据库是在数据库管理系统管理和控制之下&#xff0c;存放在存储介质上的数据集合 常用的数据库 大型数…

MapReduce(林子雨慕课课程)

文章目录 7. MapReduce7.1 MapReduce简介7.1.1 分布式并行编程7.1.2 MapReduce模型简介 7.2 MapReduce体系结构7.3 MapReduce工作流程概述7.4 Shuffle过程原理7.5 MapReduce应用程序的执行过程7.6 WordCount实例分析7.7 MapReduce的具体应用7.8 MaReduce编程实践 7. MapReduce …

Prometheus和grafana安装配置手册

1.简介 本文档为prometheus和grafana安装配置手册&#xff0c;prometheus和grafana的内容、和操作过程&#xff0c;详细介绍了服务监控配置、dashboard配置、告警配置等操作。 2.部署说明 Prometheus基于Golang编写&#xff08;需要安装&#xff09;&#xff0c;编译后的软件…

PyTorch 深度学习实战

文章目录 前言1. 环境安装1.Anaconda2.pytorch cuda 环境3.测试 前言 官网 https://pytorch.org/hub/pytorch_vision_vgg/ 1. 环境安装 1.Anaconda 可以参考这里&#xff1a;Anaconda学习 2.pytorch cuda 环境 我是按照下面的博客一步步完成&#xff0c;亲测有效 Pytorc…

移动应用-Android-开发指南

Android-UI开发指南 Android Studio调试UI设计UI框架布局Layout文本框 android的活动Activity基本概念Activity的生命周期Activity栈创建Activity管理ActivityActivity间传递数据 FragmentAdapterRecyclerViewRecyclerView Adapter&#xff08;适配器&#xff09;事件setOnItem…

基于BES平台音乐信号处理之DRC算法实现

基于BES平台音乐信号处理之DRC算法实现 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)&#xff1f;加我微信hezkz17, 本群提供音频技术答疑服务 1 DRC实现 drc.h 2 调用 audio_process.c 3 DRC动态范围控制算法在音乐信号处理中的位置 4 DRC具体细节源码 可参考…

Lumos-az/MiniSQL阅读笔记

文章目录 处理SQL创建创建表RecordManager部分CatalogManager部分 创建索引IndexManager::createIndex部分API::createNewIndex部分CatalogManager::createIndex部分 插入删除删除表删除记录? 查询B树gif演示B树增删&#xff1a;插入&#xff1a;删除&#xff1a; 项目源码&am…

ArcGIS Pro地图可视化—双变量关系映射

原址链接ArcGIS Pro地图可视化—双变量关系映射https://mp.weixin.qq.com/s/g-pPBHPXMOEF5NHm06JcrA 这个方法很早很早以前就有了&#xff0c;可能大家早就知道了&#xff0c;可我昨天刚看到这个东西 https://en.wikipedia.org/wiki/Multivariate_map 像是上图&#xff0c;美国…

MyBatisPlus(十)判空查询

说明 判空查询&#xff0c;对应SQL语句中的 IS NULL语句&#xff0c;查询对应字段为 NULL 的数据。 isNull /*** 查询用户列表&#xff0c; 查询条件&#xff1a;电子邮箱为 null 。*/Testvoid isNull() {LambdaQueryWrapper<User> wrapper new LambdaQueryWrapper<…

ctfshow-web9(奇妙的ffifdyop绕过)

尝试万能密码登录&#xff0c;没有任何回显 尝试扫描目录&#xff0c;这里不知道为啥御剑什么都扫不到&#xff0c;使用dirsearch可以扫到robots.txt 查看robots协议 访问下载index.phps 查看index.phps 简单审计一下php代码&#xff1a; $password$_POST[password]; if(strl…

js 之让人迷惑的闭包

文章目录 一、闭包是什么&#xff1f; &#x1f926;‍♂️二、闭包 &#x1f60e;三、使用场景 &#x1f601;四、使用场景&#xff08;2&#xff09; &#x1f601;五、闭包的原理六、思考总结一、 更深层次了解闭包&#xff0c;分析以下代码执行过程二、闭包三、闭包定义四、…

GNN+RA 文献阅读

[1] X. Wang et al., ‘Scalable Resource Management for Dynamic MEC: An Unsupervised Link-Output Graph Neural Network Approach’. paper code&#xff1a;GitHub - UNIC-Lab/LOGNN: This is the code for paper "Scalable Resource Management for Dynamic MEC:…

吃透底层:从路由到前缀树

前言 今天学到关于路由相关文章&#xff0c;发现动态路由中有一个很常见的实现方式是前缀树&#xff0c;很感兴趣这个算法&#xff0c;故进行记录。 前缀树 Trie&#xff08;又被叫做字典树&#xff09;可以看作是一个确定有限状态自动机&#xff0c;尽管边上的符号一般是隐含…

kaggle新赛:写作质量预测大赛【数据挖掘】

赛题名称&#xff1a;Linking Writing Processes to Writing Quality 赛题链接&#xff1a;https://www.kaggle.com/competitions/linking-writing-processes-to-writing-quality 赛题背景 写作过程中存在复杂的行为动作和认知活动&#xff0c;不同作者可能采用不同的计划修…

Godot 添加信号

前言 Godot 里面C#和GDScirpt 的用法完全不一样&#xff0c;网上相关资料太少了。 什么是信号 信号分为信号源&#xff0c;触发&#xff0c;目的节点。信号源在某些条件下触发信号&#xff0c;比如按钮点击&#xff0c;鼠标悬停等事件 #mermaid-svg-wyr9ARVcBFmUUu8y {font-…

JVM面试题:(二)内存结构和内存溢出、方法区的两种实现

内存结构&#xff1a; 方法区和对是所有线程共享的内存区域&#xff1b;而java栈、本地方法栈和程序员计数器是运行是线程私有 的内存区域。 Java堆&#xff08;Heap&#xff09;,是Java虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块内 存区域&#xff0c;在…

2023年山东省安全员C证证考试题库及山东省安全员C证试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年山东省安全员C证证考试题库及山东省安全员C证试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人员上岗证考试大…

C# 图解教程 第5版 —— 第1章 C# 和 .NET 框架

文章目录 1.1 在 .NET 之前1.2 .NET 时代1.2.1 .NET 框架的组成1.2.2 大大改进的编程环境 1.3 编译成 CIL1.4 编译成本机代码并执行1.5 CLR1.6 CLI1.7 各种缩写1.8 C# 的演化1.9 C# 和 Windows 的演化&#xff08;*&#xff09; 1.1 在 .NET 之前 MFC&#xff08;Microsoft Fou…