使用three.js 实现蜡烛效果

news/2024/10/15 21:26:26/

使用three.js 实现蜡烛效果

在这里插入图片描述

import * as THREE from "three"
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js"var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(3, 5, 8).setLength(15);
var renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x101005);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
window.addEventListener("resize", event => {camera.aspect = innerWidth / innerHeight;camera.updateProjectionMatrix()renderer.setSize(innerWidth, innerHeight);
})var controls = new OrbitControls(camera, renderer.domElement);
controls.enablePan = false;
controls.minPolarAngle = THREE.MathUtils.degToRad(60);
controls.maxPolarAngle = THREE.MathUtils.degToRad(95);
controls.minDistance = 4;
controls.maxDistance = 20;
controls.autoRotate = true;
controls.autoRotateSpeed = 1;
controls.target.set(0, 2, 0);
controls.update();var light = new THREE.DirectionalLight(0xffffff, 0.025);
light.position.setScalar(10);
scene.add(light);
scene.add(new THREE.AmbientLight(0xffffff, 0.0625));var casePath = new THREE.Path();
casePath.moveTo(0, 0);
casePath.lineTo(0, 0);
casePath.absarc(1.5, 0.5, 0.5, Math.PI * 1.5, Math.PI * 2);
casePath.lineTo(2, 1.5);
casePath.lineTo(1.99, 1.5);
casePath.lineTo(1.9, 0.5);
var caseGeo = new THREE.LatheGeometry(casePath.getPoints(), 64);
var caseMat = new THREE.MeshStandardMaterial({ color: "silver" });
var caseMesh = new THREE.Mesh(caseGeo, caseMat);
caseMesh.castShadow = true;var paraffinPath = new THREE.Path();
paraffinPath.moveTo(0, -.25);
paraffinPath.lineTo(0, -.25);
paraffinPath.absarc(1, 0, 0.25, Math.PI * 1.5, Math.PI * 2);
paraffinPath.lineTo(1.25, 0);
paraffinPath.absarc(1.89, 0.1, 0.1, Math.PI * 1.5, Math.PI * 2);
var paraffinGeo = new THREE.LatheGeometry(paraffinPath.getPoints(), 64);
paraffinGeo.translate(0, 1.25, 0);
var paraffinMat = new THREE.MeshStandardMaterial({ color: 0xffff99, side: THREE.BackSide, metalness: 0, roughness: 0.75 });
var paraffinMesh = new THREE.Mesh(paraffinGeo, paraffinMat);
caseMesh.add(paraffinMesh);var candlewickProfile = new THREE.Shape();
candlewickProfile.absarc(0, 0, 0.0625, 0, Math.PI * 2);var candlewickCurve = new THREE.CatmullRomCurve3([new THREE.Vector3(0, 0, 0),new THREE.Vector3(0, 0.5, -0.0625),new THREE.Vector3(0.25, 0.5, 0.125)
]);var candlewickGeo = new THREE.ExtrudeGeometry(candlewickProfile, {steps: 8,bevelEnabled: false,extrudePath: candlewickCurve
});var colors = [];
var color1 = new THREE.Color("black");
var color2 = new THREE.Color(0x994411);
var color3 = new THREE.Color(0xffff44);
for (let i = 0; i < candlewickGeo.attributes.position.count; i++) {if (candlewickGeo.attributes.position.getY(i) < 0.4) {color1.toArray(colors, i * 3);}else {color2.toArray(colors, i * 3);};if (candlewickGeo.attributes.position.getY(i) < 0.15) color3.toArray(colors, i * 3);
}
candlewickGeo.setAttribute('color', new THREE.BufferAttribute(new Float32Array(colors), 3));
candlewickGeo.translate(0, 0.95, 0);
var candlewickMat = new THREE.MeshBasicMaterial({ vertexColors: true });var candlewickMesh = new THREE.Mesh(candlewickGeo, candlewickMat);
caseMesh.add(candlewickMesh);// candle light
var candleLight = new THREE.PointLight(0xffaa33, 1, 5, 2);
candleLight.position.set(0, 3, 0);
candleLight.castShadow = true;
caseMesh.add(candleLight);
var candleLight2 = new THREE.PointLight(0xffaa33, 1, 10, 2);
candleLight2.position.set(0, 4, 0);
candleLight2.castShadow = true;
caseMesh.add(candleLight2);var flameMaterials = [];
function flame(isFrontSide) {let flameGeo = new THREE.SphereGeometry(0.5, 32, 32);flameGeo.translate(0, 0.5, 0);let flameMat = getFlameMaterial(true);flameMaterials.push(flameMat);let flame = new THREE.Mesh(flameGeo, flameMat);flame.position.set(0.06, 1.2, 0.06);flame.rotation.y = THREE.MathUtils.degToRad(-45);caseMesh.add(flame);
}flame(false);
flame(true);// table
var tableGeo = new THREE.CylinderGeometry(14, 14, 0.5, 64);
tableGeo.translate(0, -0.25, 0);
var tableMat = new THREE.MeshStandardMaterial({ map: new THREE.TextureLoader().load("https://threejs.org/examples/textures/hardwood2_diffuse.jpg"), metalness: 0, roughness: 0.75 });
var tableMesh = new THREE.Mesh(tableGeo, tableMat);
tableMesh.receiveShadow = true;tableMesh.add(caseMesh);
scene.add(tableMesh);var clock = new THREE.Clock();
var time = 0;render();
function render() {requestAnimationFrame(render);time += clock.getDelta();flameMaterials[0].uniforms.time.value = time;flameMaterials[1].uniforms.time.value = time;candleLight2.position.x = Math.sin(time * Math.PI) * 0.25;candleLight2.position.z = Math.cos(time * Math.PI * 0.75) * 0.25;candleLight2.intensity = 2 + Math.sin(time * Math.PI * 2) * Math.cos(time * Math.PI * 1.5) * 0.25;controls.update();renderer.render(scene, camera);
}function getFlameMaterial(isFrontSide) {let side = isFrontSide ? THREE.FrontSide : THREE.BackSide;return new THREE.ShaderMaterial({uniforms: {time: { value: 0 }},vertexShader: `uniform float time;varying vec2 vUv;varying float hValue;float random (in vec2 st) {return fract(sin(dot(st.xy,vec2(12.9898,78.233)))* 43758.5453123);}float noise (in vec2 st) {vec2 i = floor(st);vec2 f = fract(st);// Four corners in 2D of a tilefloat a = random(i);float b = random(i + vec2(1.0, 0.0));float c = random(i + vec2(0.0, 1.0));float d = random(i + vec2(1.0, 1.0));// Smooth Interpolation// Cubic Hermine Curve.  Same as SmoothStep()vec2 u = f*f*(3.0-2.0*f);// u = smoothstep(0.,1.,f);// Mix 4 coorners percentagesreturn mix(a, b, u.x) +(c - a)* u.y * (1.0 - u.x) +(d - b) * u.x * u.y;}void main() {vUv = uv;vec3 pos = position;pos *= vec3(0.8, 2, 0.725);hValue = position.y;//float sinT = sin(time * 2.) * 0.5 + 0.5;float posXZlen = length(position.xz);pos.y *= 1. + (cos((posXZlen + 0.25) * 3.1415926) * 0.25 + noise(vec2(0, time)) * 0.125 + noise(vec2(position.x + time, position.z + time)) * 0.5) * position.y; // flame heightpos.x += noise(vec2(time * 2., (position.y - time) * 4.0)) * hValue * 0.0312; // flame tremblingpos.z += noise(vec2((position.y - time) * 4.0, time * 2.)) * hValue * 0.0312; // flame tremblinggl_Position = projectionMatrix * modelViewMatrix * vec4(pos,1.0);}`,fragmentShader: `varying float hValue;varying vec2 vUv;// honestly stolen from https://www.shadertoy.com/view/4dsSzrvec3 heatmapGradient(float t) {return clamp((pow(t, 1.5) * 0.8 + 0.2) * vec3(smoothstep(0.0, 0.35, t) + t * 0.5, smoothstep(0.5, 1.0, t), max(1.0 - t * 1.7, t * 7.0 - 6.0)), 0.0, 1.0);}void main() {float v = abs(smoothstep(0.0, 0.4, hValue) - 1.);float alpha = (1. - v) * 0.99; // bottom transparencyalpha -= 1. - smoothstep(1.0, 0.97, hValue); // tip transparencygl_FragColor = vec4(heatmapGradient(smoothstep(0.0, 0.3, hValue)) * vec3(0.95,0.95,0.4), alpha) ;gl_FragColor.rgb = mix(vec3(0,0,1), gl_FragColor.rgb, smoothstep(0.0, 0.3, hValue)); // blueish for bottomgl_FragColor.rgb += vec3(1, 0.9, 0.5) * (1.25 - vUv.y); // make the midst brightergl_FragColor.rgb = mix(gl_FragColor.rgb, vec3(0.66, 0.32, 0.03), smoothstep(0.95, 1., hValue)); // tip}`,transparent: true,side: side})}/*** 名称: 蜡烛* 作者: 优雅永不过时 https://github.com/z2586300277
*/

http://www.ppmy.cn/news/1539622.html

相关文章

香港大学神作 LightRAG 横空出世!AI 检索生成系统革命,秒懂复杂信息,动态数据无所遁形!

❤️ 如果你也关注大模型与 AI 的发展现状&#xff0c;且对大模型应用开发非常感兴趣&#xff0c;我会快速跟你分享最新的感兴趣的 AI 应用和热点信息&#xff0c;也会不定期分享自己的想法和开源实例&#xff0c;欢迎关注我哦&#xff01; 微信订阅号&#xff5c;搜一搜&…

Python基础知识9

Python推导式 1.Python 推导式是一种独特的数据处理方式&#xff0c;可以从一个数据序列构建另一个新的数据序列的结构体。 2.Python 支持各种数据结构的推导式&#xff1a; 列表(list)推导式字典(dict)推导式集合(set)推导式元组(tuple)推导式 列表推导式 1.列表推导式格…

PHP DateTime基础用法

PHP DateTime 的用法详解 一、引言 在开发 PHP 应用程序时&#xff0c;处理日期和时间是一个至关重要的任务。PHP 提供了强大的日期和时间处理功能&#xff0c;其中 DateTime 类是最常用的工具之一。DateTime 类提供了丰富的方法来创建、格式化、计算和比较日期时间&#xff…

QT QML 练习8-Simple Transformations

简单的转换&#xff08;Simple Transformations&#xff09; 转换操作改变了一个对象的几何状态。QML元素对象通常能够被平移&#xff0c;旋转&#xff0c;缩放。下面我们将讲解这些简单的操作和一些更高级的用法。 我们先从一个简单的转换开始。用下面的场景作为我们学习的开始…

C++20那些事之constexpr与comma expr

C20那些事之constexpr与comma expr C20 引入了多项新特性&#xff0c;进一步增强了编译时能力和代码安全性。本文将深入探讨两项重要的变更&#xff1a;constexpr 函数中的异常处理以及下标运算符中逗号运算符的弃用。 注&#xff1a;懒人版&#xff0c;本节的代码示例与相关文…

【氮化镓】低温对p-GaN HEMT迁移率、阈值电压和亚阈值摆幅的影响

本期分享一篇低温对p-GaN HEMT 迁移率、阈值电压和亚阈值摆幅影响进行表征和建模的研究论文。文章作者Shivendra Kumar Singh、Thien Sao Ngo、Tian-Li Wu(通讯作者)和Yogesh Singh Chauhan,分别来资源中国台湾阳明交通大学国际半导体技术学院、印度理工学院坎普尔分校电气工…

多层嵌套json字符串(jsonStr)写入redis

1、连接redis Jedis jedis new Jedis("localhost", 6379); 2、将字符串转为json格式 JSONObject jsJSONObject.fromObject(jsonStr); 3、对json格式进行解析 4、将json写入redis public static void RedisSet(JSONObject js,Jedis js01){ //获取json中的所有ke…

大模型推理框架选型调研

文章目录 背景选型评估指标推理性能推理优化支持程度易用性与学习成本可持续维护性技术兼容性 技术备选老牌新贵 分析TensorRT-LLMNvidia Triton Inference ServerTensorRT-LLM 与 vLLM 对比 建议与结论 背景 公司需要新增了 GPU 机器自部署大模型服务用于支撑 AI 业务。目前市…