用ThreeJS写了一个圣诞树

使用什么技术写

一开始我准备用html+css去写,后来感觉使用html和css写就太low了,没有一点点心意。就打算用three.js写一个3d版本的。

简单介绍一下threejs

Three.js是一个基于原生WebGL封装运行的三维引擎,是最著名的3D WebGL JavaScriptThree.js是一个基于原生WebGL封装运行的三维引擎,是最著名的3D WebGL JavaScript库之一。它是一个让用户通过JavaScript入手进入搭建WebGL项目的类库。Three.js提供了许多简单易用的API,使得开发者能够更加方便地创建复杂的3D场景。

WebGL是一个只能画点、线和三角形的非常底层的系统。而Three.js则在此基础之上进行了封装,提供了一系列的图形处理功能,如渲染器、相机、灯光、材质等,以及各种几何体、粒子系统等,极大地简化了3D图形编程的难度。这使得学习WebGL需要图形学知识的要求得以降低,因为开发者可以直接通过使用Three.js提供的JS和GLSL两种语言来构建和呈现3D图形。

实现具体步骤

首先,我们需要在HTML文件中引入Three.js库。你可以在Three.js官方网站下载最新版本的库,或者直接从CDN获取。将以下代码添加到你的HTML文件的<head>部分:

<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>

接下来,我们将开始编写JavaScript代码来创建场景、相机、渲染器以及圣诞树的各个部分。首先,我们创建一个场景对象,并设置其背景颜色为深绿色:

let scene = new THREE.Scene();
scene.background = new THREE.Color(0x002633);

然后,我们创建一个透视相机,并将其位置设置为距离场景中心一定距离的位置。我们还设置了相机的视野范围和纵横比:

let camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;

接下来,我们创建一个WebGL渲染器,并将其大小设置为浏览器窗口的大小。然后,我们将渲染器的DOM元素添加到页面中:

let renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

现在,我们可以开始创建圣诞树的各个部分了。首先,我们创建一个树干,它是一个圆柱体:

let trunkGeometry = new THREE.CylinderGeometry(0.2, 0.4, 1.6, 8);
let trunk = new THREE.Mesh(trunkGeometry, brownMaterial);
scene.add(trunk);

接着,我们创建一个树叶,它是一个圆锥体:

let leavesGeometry = new THREE.ConeGeometry(1.2, 2.4, 8);
let leaves = new THREE.Mesh(leavesGeometry, greenMaterial);
leaves.position.y = 1.6;
scene.add(leaves);

然后,我们创建彩灯,它们是一些旋转的球体:

let lightGeometry = new THREE.SphereGeometry(0.1, 4, 4);
let lights = [];
let colors = [redMaterial, yellowMaterial, new THREE.MeshBasicMaterial({ color: 0x0000ff }), new THREE.MeshBasicMaterial({ color: 0x00ff00 })];
let angles = [0, Math.PI / 3, 2 * Math.PI / 3, Math.PI, 4 * Math.PI / 3, 5 * Math.PI / 3];
for (let i = 0; i < angles.length; i++) {let light = new THREE.Mesh(lightGeometry, colors[i % 4]);light.position.set(Math.cos(angles[i]) * 0.9, 2.2, Math.sin(angles[i]) * 0.9);scene.add(light);lights.push(light);
}

接下来,我们创建一个星星,它是一些旋转的点:

let starGeometry = new THREE.SphereGeometry(0.2, 4, 4);
let star = new THREE.Mesh(starGeometry, yellowMaterial);
star.position.y = 2.7;
scene.add(star);

最后,我们创建一个礼物盒,它是一个立方体:

let giftGeometry = new THREE.BoxGeometry(0.5, 0.5, 0.5);
let giftMaterials = [new THREE.MeshBasicMaterial({ color: 0xff0000 }),new THREE.MeshBasicMaterial({ color: 0x00ff00 }),new THREE.MeshBasicMaterial({ color: 0x0000ff }),new THREE.MeshBasicMaterial({ color: 0xffff00 }),new THREE.MeshBasicMaterial({ color: 0xff00ff }),new THREE.MeshBasicMaterial({ color: 0x00ffff })
];
let giftMesh = new THREE.Mesh(giftGeometry, giftMaterials);
giftMesh.position.set(0, -1.3, 0);
scene.add(giftMesh);

为了给圣诞树增添一些雪花效果,我们还需要创建一个雪花几何体和一个雪花材质,然后将它们组合成一个雪花网格对象,并将其添加到场景中:

let snowFlakeGeometry = new THREE.BufferGeometry();
let positions = [];
for (let i = 0; i < 1000; i++) {positions.push(Math.random() * 2000 - 1000);positions.push(Math.random() * 2000 - 1000);positions.push(Math.random() * 2000 - 1000);
}
snowFlakeGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
let snowFlakeMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 2 });
let snowFlake = new THREE.Points(snowFlakeGeometry, snowFlakeMaterial);
scene.add(snowFlake);

最后,我们需要添加一个渲染循环,以便不断地更新场景中的物体并渲染到屏幕上:

function animate() {requestAnimationFrame(animate);trunk.rotation.y += 0.01;leaves.rotation.y += 0.01;for (let i = 0; i < lights.length; i++) {lights[i].rotation.y += 0.02;}snowFlake.rotation.y -= 0.001;renderer.render(scene, camera);
}
animate();

这就是如何使用Three.js创建一个完整的圣诞树的全部过程。如果你有女朋友,可以尝试写一个哄女朋友开心一下

最终效果: 

image.png

所有代码

<!DOCTYPE html>
<html lang="es">
<head><meta charset="utf-8"><title>完整的圣诞树</title><style>body { margin: 0; }canvas { display: block; }</style>
</head>
<body>
<script src="https://threejs.org/build/three.js"></script>
<script >// 创建场景let scene = new THREE.Scene();// 添加背景颜色scene.background = new THREE.Color(0x002633);// 创建相机let camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);camera.position.z = 5;// 创建渲染器let renderer = new THREE.WebGLRenderer();renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);// 创建材质let brownMaterial = new THREE.MeshBasicMaterial({ color: 0x7f4014 });let greenMaterial = new THREE.MeshBasicMaterial({ color: 0x006400, transparent: true, opacity: 0.8 });let redMaterial = new THREE.MeshBasicMaterial({ color: 0xff0000 });let yellowMaterial = new THREE.MeshBasicMaterial({ color: 0xffff00 });// 创建树干let trunkGeometry = new THREE.CylinderGeometry(0.2, 0.4, 1.6, 8);let trunk = new THREE.Mesh(trunkGeometry, brownMaterial);scene.add(trunk);// 创建树叶let leavesGeometry = new THREE.ConeGeometry(1.2, 2.4, 8);let leaves = new THREE.Mesh(leavesGeometry, greenMaterial);leaves.position.y = 1.6;scene.add(leaves);// 创建彩灯let lightGeometry = new THREE.SphereGeometry(0.1, 4, 4);let lights = [];let colors = [redMaterial, yellowMaterial, new THREE.MeshBasicMaterial({ color: 0x0000ff }), new THREE.MeshBasicMaterial({ color: 0x00ff00 })];let angles = [0, Math.PI / 3, 2 * Math.PI / 3, Math.PI, 4 * Math.PI / 3, 5 * Math.PI / 3];for (let i = 0; i < angles.length; i++) {let light = new THREE.Mesh(lightGeometry, colors[i % 4]);light.position.set(Math.cos(angles[i]) * 0.9, 2.2, Math.sin(angles[i]) * 0.9);scene.add(light);lights.push(light);}// 创建星星let starGeometry = new THREE.SphereGeometry(0.2, 4, 4);let star = new THREE.Mesh(starGeometry, yellowMaterial);star.position.y = 2.7;scene.add(star);// 创建礼物盒let giftGeometry = new THREE.BoxGeometry(0.5, 0.5, 0.5);let giftMaterials = [new THREE.MeshBasicMaterial({ color: 0xff0000 }),new THREE.MeshBasicMaterial({ color: 0x00ff00 }),new THREE.MeshBasicMaterial({ color: 0x0000ff }),new THREE.MeshBasicMaterial({ color: 0xffff00 }),new THREE.MeshBasicMaterial({ color: 0xff00ff }),new THREE.MeshBasicMaterial({ color: 0x00ffff })];let giftMesh = new THREE.Mesh(giftGeometry, giftMaterials);giftMesh.position.set(0, -1.3, 0);scene.add(giftMesh);// 添加雪花效果let snowFlakeGeometry = new THREE.BufferGeometry();let positions = [];for (let i = 0; i < 1000; i++) {positions.push(Math.random() * 2000 - 1000);positions.push(Math.random() * 2000 - 1000);positions.push(Math.random() * 2000 - 1000);}snowFlakeGeometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));let snowFlakeMaterial = new THREE.PointsMaterial({ color: 0xffffff, size: 2 });let snowFlake = new THREE.Points(snowFlakeGeometry, snowFlakeMaterial);scene.add(snowFlake);// 渲染循环function animate() {requestAnimationFrame(animate);trunk.rotation.y += 0.01;leaves.rotation.y += 0.01;for (let i = 0; i < lights.length; i++) {lights[i].rotation.y += 0.02;}snowFlake.rotation.y -= 0.001;renderer.render(scene, camera);}animate();
</script>
</body>
</html>

圣诞节快到了,用ThreeJS给女朋友写了一个圣诞树🎄,她很开心
原文链接:https://juejin.cn/post/7314189771378065443

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

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

相关文章

SpringBoot3知识总结

SpringBoot3 1、简介 1. 前置知识 Java17Spring、SpringMVC、MyBatisMaven、IDEA 2. 环境要求 环境&工具版本&#xff08;or later&#xff09;SpringBoot3.0.5IDEA2022Java17Maven3.5 3. SpringBoot是什么 Spring Boot是Spring项目中的一个子工程&#xff0c;与我们…

第二百一十五回 如何创建单例模式

文章目录 1. 概念介绍2. 思路与方法2.1 实现思路2.2 实现方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"分享三个使用TextField的细节"沉浸式状态样相关的内容&#xff0c;本章回中将介绍 如何创建单例模式.闲话休提&#xff0c;让我们一起Talk Flutter吧。 …

java实现局域网内视频投屏播放(三)投屏原理

常见投屏方案 常见的投屏方案主要有以下几种&#xff1a; DLNA DLNA的全称是DIGITAL LIVING NETWORK ALLIANCE(数字生活网络联盟)。DLNA委员会已经于2017年1月5日正式解散&#xff0c;原因是旧的标准已经无法满足新设备的发展趋势&#xff0c;DLNA标准将来也不会再更新。但是…

【MySQL】数据库基础入门 安装MySQL

目录 介绍&#xff1a; 安装MySQL: 设置 root 账号密码 2.配置环境变量 2.找到 Path 系统变量, 点击 "编辑" 介绍&#xff1a; MySQL是一个开源的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;它是一种用于管理和存储数据的软件。 安装MySQL: …

MyBatis进行CRUD中添加数据实现主键回填

文章目录 MyBatis进行CRUD中添加数据实现主键回填1、创建一个mybatis项目2、实现添加数据时主键回填在MyBatisTest.java中添加下面方法在UserMapper.java中添加对应的属性在UserMapper.xml中添加sql语句如下运行结果如下(取消commit方法注释后就不会出现Rolling back回滚进行真…

JRT打印元素绘制协议整合PDF

打印不光要能打印内部的单据&#xff0c;对于检验的打印还有外送回传的PDF报告也需要能够打印&#xff0c;所以需要把打印PDF文件整合进来&#xff0c;为此给打印元素绘制协议增加PDF类型的元素。 定义如下&#xff0c;由绘制协议按地址下载文件后和其他打印元素整合&#xff…

107基于matlab的模糊推理系统(ANFIS)的时间序列预测

基于matlab的模糊推理系统&#xff08;ANFIS&#xff09;的时间序列预测&#xff0c;输出训练集、测试集和预测数据结果&#xff0c;数据可更换自己的&#xff0c;程序已调通&#xff0c;可直接运行。 107 时间序列预测模糊推理系统 (xiaohongshu.com)

[ZJCTF 2019]NiZhuanSiWei1

[ZJCTF 2019]NiZhuanSiWei1 预测试 打开网页就是代码&#xff1a; <?php $text $_GET["text"]; $file $_GET["file"]; $password $_GET["password"]; if(isset($text)&&(file_get_contents($text,r)"welcome to the zjct…

【论文笔记】MCANet: Medical Image Segmentation withMulti-Scale Cross-Axis Attention

医疗图像分割任务中&#xff0c;捕获多尺度信息、构建长期依赖对分割结果有非常大的影响。该论文提出了 Multi-scale Cross-axis Attention&#xff08;MCA&#xff09;模块&#xff0c;融合了多尺度特征&#xff0c;并使用Attention提取全局上下文信息。 论文地址&#xff1a…

蔚来打败“蔚来”

作者 | 魏启扬 来源 | 洞见新研社 继2019年后&#xff0c;又一次深陷倒闭传闻的蔚来汽车&#xff0c;“在关键时刻找到钱了”。 12月18日&#xff0c;蔚来汽车宣布&#xff0c;与阿布扎比投资机构CYVN Holdings签订新一轮股份认购协议&#xff0c;CYVN Holdings将通过其附属公…

四色问题(图论)python

四色问题是一种著名的图论问题&#xff0c;它要求在给定的地图上给每个区域着一种颜色&#xff0c;使得相邻的区域颜色不同&#xff0c;而只使用四种颜色。这个问题可以通过图的着色来解决&#xff0c;其中图的节点表示区域&#xff0c;边表示相邻的关系。 在 Python 中&#…

excel导出,post还是get请求?

1&#xff0c;前提 今天在解决excel导出的bug时&#xff0c;因为导出接口查询参数较多&#xff0c;所以把原来的get请求接口修改为post请求 原代码&#xff1a; 修改后&#xff1a; 2&#xff0c;修改后 postman请求正常&#xff0c;然后让前端对接口进行同步修改&#xff0…

Clion自定义管理和配置软件构建过程的工具(代替CMake)构建程序

在公司由于需要x86环境和其他arm环境&#xff0c;同时需要使用公司自定义的mine_x86或者mine_orin对代码进行编译。 编译命令如下mine_x86 build -Dlocal1 -j8,为使用Clion对程序进行调试&#xff0c;需要对程序进行设置。方便调试代码时能够断点查看变量。尝试了很多次&#…

@WebMethod 这个注解的作用

WebMethod 注解是 Java 中 JAX-WS&#xff08;Java API for XML Web Services&#xff09;的一部分&#xff0c;用于将一个特定的方法标记为 Web 服务操作。当你在类方法上使用 WebMethod 注解时&#xff0c;这表明该方法是一个对外暴露的 Web 服务方法&#xff0c;即这个方法可…

pytorch实现DCP暗通道先验去雾算法及其onnx导出

pytorch实现DCP暗通道先验去雾算法及其onnx导出 简介实现ONNX导出导出测试 简介 最近在做图像去雾&#xff0c;于是在Pytorch上复现了一下dcp算法。暗通道先验去雾算法是大神何恺明2009年发表在CVPR上的一篇论文&#xff0c;还获得了当年的CVPR最佳论文。 实现 具体原理就不…

计算机组成原理综合1

1、完整的计算机系统应包括______。D A. 运算器、存储器和控制器 B. 外部设备和主机 C. 主机和实用程序 D. 配套的硬件设备和软件系统 2、计算机系统中的存储器系统是指______。D A. RAM存储器 B. ROM存储器 C. 主存储器 …

安捷伦Agilent 34970A数据采集

易学易用 从34972A简化的配置到内置的图形Web界面&#xff0c;我们都投入了非常多的时间和精力&#xff0c;以帮助您节约宝贵的时间。一些非常简单的东西,例如模块上螺旋型端子连接器内置热电偶参考结、包括众多实例和提示的完整用户文档&#xff0c;以及使您能够在开机数分钟后…

接口测试和测试用例分析

只要有软件产品的公司百分之九十以上都会做接口测试&#xff0c;要做接口测试的公司那是少不了接口测试工程师的&#xff0c;接口测试工程师相对于其他的职位又比较轻松并且容易胜任。如果你想从事接口测试的工作那就少不了对接口进行分析&#xff0c;同时也会对测试用例进行研…

node.js mongoose middleware

目录 官方文档 简介 定义模型 注册中间件 创建doc实例&#xff0c;并进行增删改查 方法名和注册的中间件名相匹配 执行结果 分析 错误处理中间件 手动抛出错误 注意点 官方文档 Mongoose v8.0.3: Middleware 简介 在mongoose中&#xff0c;中间件是一种允许在执…

DDD领域驱动设计(二)

软件系统复杂性的应对 解决复杂和大规模软件的武器可以粗略的归位三种:抽象 分治和知识 抽象: 使用抽象能够精简问题空间&#xff0c;而且问题越小越容易理解。比如你去一个地方 一开始的时候并不需要确定用什么方式到达。分治: 类似算法里面的dp用的就是分治的想法。分割后的…