使用three.js 实现蜡烛效果

使用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 tile
            float 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 percentages
            return 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 height

          pos.x += noise(vec2(time * 2., (position.y - time) * 4.0)) * hValue * 0.0312; // flame trembling
          pos.z += noise(vec2((position.y - time) * 4.0, time * 2.)) * hValue * 0.0312; // flame trembling

          gl_Position = projectionMatrix * modelViewMatrix * vec4(pos,1.0);
        }
      `,
        fragmentShader: `
        varying float hValue;
        varying vec2 vUv;

        // honestly stolen from https://www.shadertoy.com/view/4dsSzr
        vec3 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 transparency
          alpha -= 1. - smoothstep(1.0, 0.97, hValue); // tip transparency
          gl_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 bottom
          gl_FragColor.rgb += vec3(1, 0.9, 0.5) * (1.25 - vUv.y); // make the midst brighter
          gl_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
*/

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【opengl学习】opengl的compute shader

目的 opengl虽然老&#xff0c;但是算上opengl es&#xff0c;应该是应用最广泛的显卡api。用compute shader做计算&#xff0c;可以一定程度上摆脱N卡的限制&#xff0c;也摆脱windows和linux&#xff0c;mac等平台的限制。 计算着色器应该没有完全榨干硬件的性能&#xff0c…

CUDA - 如何让线程和内存对应

前提&#xff1a; 本文的目的就是设置的程序中&#xff0c;每个线程可以负责一个单独的计算任务。帮助学习和理解线程是如何组织的。 本文处理一个二维数据的加法。 数据在内存中的存储 以线性、行为主的方式存储。 例如&#xff0c;一个16*8的一维数组&#xff0c;在内存…

站在用户视角审视:以太彩光与PON之争

作者:科技作家-郑凯 园区,是企业数字化转型的“中心战场”。 云计算、大数据、人工智能等数智化技术在园区里“战火交织”;高清视频、协同办公,智慧安防等大量创新应用产生的海量数据在园区内“纵横驰骋”;加上大量的IOT和智能化设备涌入“战场”,让园区网络面对着难以抵御的…

查看PyTorch的GPU使用情况的工具

文章目录 torch.cuda APIPyTorch SnapshotPyTorch ProfilerNVIDIA Nsight Systemstorchinfo torch.cuda API torch.cuda.memory_stats&#xff1a;返回给定设备的 CUDA 内存分配器统计信息字典。该函数的返回值是一个统计字典&#xff0c;每个字典都是一个非负整数。torch.cud…

antDesign Form.List下的Form.Item如何通过setFieldsValue设置值

翻了一下antDesign官网只看见了Form可以使用setFieldsValue设置值&#xff0c;却没找到Form.List使用setFieldsValue设置值。 于是研究了一下&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 我的解决方案是&#xff1a; 先设置为空数组, 再设置成…

利用编程思维做题之反转链表

牛客网题目 1. 理解问题 给到我们的是一个单链表的头节点 pHead&#xff0c;要求反转后&#xff0c;返回新链表的头节点。 首先在心里设想能够快速理解的例子&#xff0c;如给你123序列&#xff0c;要你反转此序列如何回答&#xff1f;将最后一个数字3作为头&#xff0c;然后修…

学习threejs,THREE.MeshBasicMaterial网格材质、THREE.MeshLambertMaterial漫反射材质

&#x1f468;‍⚕️ 主页&#xff1a; gis分享者 &#x1f468;‍⚕️ 感谢各位大佬 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍⚕️ 收录于专栏&#xff1a;threejs gis工程师 文章目录 一、&#x1f340;前言1.1 ☘️THREE.MeshBasicMaterial网…

MATLAB代码解析:利用DCGAN实现图像数据的生成

摘要 经典代码&#xff1a;利用DCGAN生成花朵 MATLAB官方其实给出了DCGAN生成花朵的示范代码&#xff0c;原文地址&#xff1a;训练生成对抗网络 (GAN) - MATLAB & Simulink - MathWorks 中国 先看看训练效果 训练1周期 训练11周期 训练56个周期 脚本文件 为了能让各位…

centos7 Oracle 11g rac 静默安装(NFS配置共享存储)

1.环境信息准备 注意&#xff1a; 在配置网络时&#xff0c;Oracle RAC的每个节点必须具有至少两个以上的网卡&#xff0c;一张网卡对外提供网络服务&#xff0c;另一张网卡用于各个节点间的通信和心跳检测等。在配置RAC集群的网卡时&#xff0c;如果节点1的公共接口是eth0&…

下一代安全:融合网络和物理策略以实现最佳保护

在当今快速发展的技术环境中&#xff0c;网络和物理安全融合变得比以往任何时候都更加重要。随着物联网 (IoT) 和工业物联网 (IIoT) 的兴起&#xff0c;组织在保护数字和物理资产方面面临着独特的挑战。 本文探讨了安全融合的概念、说明其重要性的实际事件以及整合网络和物理安…

本地装了个pytorch cuda

安装命令选择 pip install torch1.13.1cu116 torchvision0.14.1cu116 torchaudio0.13.1 --extra-index-url https://download.pytorch.org/whl/cu116 torch版本查看 python import torch print(torch.__version__) 查看pytorch能否使用cuda import torch# 检查CUDA是否可用…

鸿蒙NEXT开发-动画(基于最新api12稳定版)

注意&#xff1a;博主有个鸿蒙专栏&#xff0c;里面从上到下有关于鸿蒙next的教学文档&#xff0c;大家感兴趣可以学习下 如果大家觉得博主文章写的好的话&#xff0c;可以点下关注&#xff0c;博主会一直更新鸿蒙next相关知识 专栏地址: https://blog.csdn.net/qq_56760790/…

241014-绿联UGOSPro-通过虚拟机访问主机的用户目录及文件夹

如图所示&#xff0c;两种方式&#xff1b; 方式1: 通过Files中的Other Locations 添加主机ip&#xff0c;随后输入主机的用户名及密码即可系统及文件加载可能需要一段时间&#xff0c;有点卡&#xff0c;加载完应该就可以点击访问了 方式2: 通过命令行直接ssh/sftp userna…

【C++网络编程】(一)Linux平台下TCP客户/服务端程序

文章目录 Linux平台下TCP客户/服务端程序服务端客户端相关头文件介绍 Linux平台下TCP客户/服务端程序 图片来源&#xff1a;https://subingwen.cn/linux/socket/ 下面实现一个Linux平台下TCP客户/服务端程序&#xff1a;客户端向服务器发送&#xff1a;“你好&#xff0c;服务…

网络资源模板--Android Studio 实现简易新闻App

目录 一、项目演示 二、项目测试环境 三、项目详情 四、完整的项目源码 一、项目演示 网络资源模板--基于Android studio 实现的简易新闻App 二、项目测试环境 三、项目详情 登录页 用户输入&#xff1a; 提供账号和密码输入框&#xff0c;用户可以输入登录信息。支持“记…

[ComfyUI]Flux:国漫经典!斗破苍穹古熏儿之绮梦流光模型来袭

在数字艺术和创意领域&#xff0c;FLUX以其独特的虚实结合技术&#xff0c;已经成为艺术家和设计师们手中的利器。今天&#xff0c;我们激动地宣布&#xff0c;FLUX推出了一款全新的ComfyUI版本——Flux&#xff0c;它将国漫经典《斗破苍穹》中的古熏儿之绮梦流光模型完美融合&…

第十四章 RabbitMQ延迟消息之延迟队列

目录 一、引言 二、死信队列 三、核心代码实现 四、运行效果 五、总结 一、引言 什么是延迟消息&#xff1f; 发送者发送消息时指定一个时间&#xff0c;消费者不会立刻收到消息&#xff0c;而是在指定时间后收到消息。 什么是延迟任务&#xff1f; 设置在一定时间之后才…

Qt入门教程:创建我的第一个小程序

本章教程&#xff0c;主要介绍如何编写一个简单的QT小程序。主要是介绍创建项目的过程。 一、打开QT软件编辑器 这里使用的是QT5.14.2版本的&#xff0c;安装教程参考以往教程&#xff1a;https://blog.csdn.net/qq_19309473/article/details/142907096 二、创建项目 到这里&am…

使用Docker部署nextjs应用

最近使用nextjs网站开发&#xff0c;希望使用docker进行生产环境的部署&#xff0c;减少环境的依赖可重复部署操作。我采用的是Dockerfile编写应用镜像方式 docker-compose实现容器部署的功能。 Docker Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器…

【大模型问答测试】大模型问答测试脚本实现(第一版)

背景 公司已经做了一段时间的大模型&#xff0c;每次测试或者回归的时候都需要针对问答进行测试回归&#xff0c;耗费大量的时间与精力&#xff0c;因此结合产品特点&#xff0c;开发自动化脚本替代人工的操作&#xff0c;提升测试回归效率 设计 使用pythonrequestExcel进行…