【Three.js基础学习】29.Hologram Shader
前言
three.js 通过着色器如何实现全息影像,以及一些动态的效果。
一些难点的思维,代码目录
下面图是摄像机视角观看影响上的时候,如何实现光影的渐变,透视以及叠加等。
一、代码
1.index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Holographic</title><link rel="stylesheet" href="./style.css">
</head>
<body><canvas class="webgl"></canvas><script type="module" src="./script.js"></script>
</body>
</html>
2.style.css
*
{margin: 0;padding: 0;
}html,
body
{overflow: hidden;
}.webgl
{position: fixed;top: 0;left: 0;outline: none;
}
3.script.js
import * as THREE from 'three'
import { OrbitControls } from 'three/addons/controls/OrbitControls.js'
import GUI from 'lil-gui'
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js'
import holographicVertexShader from './shaders/holographic/vertex.glsl'
import holographicFragmentShader from './shaders/holographic/fragment.glsl'/*** Base*/
// Debug
const gui = new GUI()// Canvas
const canvas = document.querySelector('canvas.webgl')// Scene
const scene = new THREE.Scene()// Loaders
const gltfLoader = new GLTFLoader()/*** Sizes*/
const sizes = {width: window.innerWidth,height: window.innerHeight
}window.addEventListener('resize', () =>
{// Update sizessizes.width = window.innerWidthsizes.height = window.innerHeight// Update cameracamera.aspect = sizes.width / sizes.heightcamera.updateProjectionMatrix()// Update rendererrenderer.setSize(sizes.width, sizes.height)renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
})/*** Camera*/
// Base camera
const camera = new THREE.PerspectiveCamera(25, sizes.width / sizes.height, 0.1, 100)
camera.position.set(7, 7, 7)
scene.add(camera)// Controls
const controls = new OrbitControls(camera, canvas)
controls.enableDamping = true/*** Renderer*/
const rendererParameters = {}
rendererParameters.clearColor = '#1d1f2a'const renderer = new THREE.WebGLRenderer({canvas: canvas,antialias: true
})
renderer.setClearColor(rendererParameters.clearColor)
renderer.setSize(sizes.width, sizes.height)
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))gui.addColor(rendererParameters, 'clearColor').onChange(() =>{renderer.setClearColor(rendererParameters.clearColor)})/*** Material*/
const materialParameters = {}
materialParameters.color = '#70c1ff'gui.addColor(materialParameters,'color').onChange(()=>{material.uniforms.uColor.value.set(materialParameters.color)})const material = new THREE.ShaderMaterial({vertexShader:holographicVertexShader,fragmentShader:holographicFragmentShader,uniforms:{uTime:new THREE.Uniform(0),uColor:new THREE.Uniform(new THREE.Color(materialParameters.color))},transparent:true, // 设置透明材质side:THREE.DoubleSide,depthWrite:false, // 停止深度写入blending:THREE.AdditiveBlending, // 混合叠加 叠加起来的颜色更亮})/*** Objects*/
// Torus knot
const torusKnot = new THREE.Mesh(new THREE.TorusKnotGeometry(0.6, 0.25, 128, 32),material
)
torusKnot.position.x = 3
scene.add(torusKnot)// Sphere
const sphere = new THREE.Mesh(new THREE.SphereGeometry(),material
)
sphere.position.x = - 3
scene.add(sphere)// Suzanne
let suzanne = null
gltfLoader.load('./suzanne.glb',(gltf) =>{suzanne = gltf.scenesuzanne.traverse((child) =>{if(child.isMesh)child.material = material})scene.add(suzanne)}
)/*** Animate*/
const clock = new THREE.Clock()const tick = () =>
{const elapsedTime = clock.getElapsedTime()// Update material.uniforms.uTime.value = elapsedTime;// Rotate objectsif(suzanne){suzanne.rotation.x = - elapsedTime * 0.1suzanne.rotation.y = elapsedTime * 0.2}sphere.rotation.x = - elapsedTime * 0.1sphere.rotation.y = elapsedTime * 0.2torusKnot.rotation.x = - elapsedTime * 0.1torusKnot.rotation.y = elapsedTime * 0.2// Update controlscontrols.update()// Renderrenderer.render(scene, camera)// Call tick again on the next framewindow.requestAnimationFrame(tick)
}tick()
4.fragment.glsl 顶点着色器
uniform float uTime;
uniform vec3 uColor;varying vec3 vPosition;
varying vec3 vNormal;/* mod(X, Y)函数返回X对Y取模的结果。如果X和Y都是数组,mod函数会对数组的每个元素分别进行取模运算对上一步的结果取模 1.0,即计算该值除以 1.0 的余数。由于取模 1.0 的效果是将值限制在 0 到 1 之间(不包括1),这个操作实际上是在做一个周期性变换,使得 vUv.x 在 0 到 10 之间变化时,结果会在 0 到 1 之间循环pow(x,y)x的y次方。如果x小于0,结果是未定义的。同样,如果x=0并且y<=0,结果也是未定义的normalize 标准化向量,返回一个方向和x相同但长度为1的向量dot 向量x,y之间的点积Fresnel 根据相机角度,进行判断,相同方向1,直角0 ,相反 1同样法线应该渲染,vertex.glsl
*/void main(){// Normal 法线标准值重新定义为1vec3 normal = normalize(vNormal); // 两个角度大的法线之间,的法线长度不是标准,重新初始化1if(!gl_FrontFacing)normal *= - 1.0;// Stripes 条纹 float stripes = mod((vPosition.y - uTime * 0.02) * 20.0, 1.0);stripes = pow(stripes, 3.0);// Fresnel 菲涅尔效果 全息vec3 viewDirection = normalize(vPosition - cameraPosition) ; // 模型位置 - 相机位置,得到视图位置float fresnel = dot(viewDirection,normal) + 1.0; // 这里加上一,原本的0变成1,-1变成0fresnel = pow(fresnel,2.0);// Falloff 平滑重映射 想要实现边界处 1-0转变 逐渐消失的效果float falloff = smoothstep(0.8,0.0,fresnel);// Holographic 全息float holographic = stripes * fresnel;holographic += fresnel * 1.25;holographic *= falloff;// Final Colorgl_FragColor = vec4(uColor,holographic);#include <tonemapping_fragment>#include <colorspace_fragment>
}
5.vertex.glsl 片段着色器
uniform float uTime; varying vec3 vPosition;
varying vec3 vNormal;/* smoothstep(edge0, edge1, x) 如果x <= edge0,返回0.0 ;如果x >= edge1 返回1.0;如果edge0 < x < edge1,则执行0~1之间的平滑埃尔米特差值。如果edge0 >= edge1,结果是未定义的。
*/#include ../includes/random2D.glslvoid main(){// Positionvec4 modelPosition = modelMatrix * vec4(position,1.0);// Glitch random2D函数会给我0-1的数据,减去0.5 相机的中心位置就不会偏移float glitchTime = uTime - modelPosition.y; // 设置故障时间float glitchStrength = sin(glitchTime) + sin(glitchTime * 3.45) + sin(glitchTime * 8.76); // 改变频率glitchStrength /= 3.0;glitchStrength = smoothstep(0.3,1.0,glitchStrength);glitchStrength *= 0.25;modelPosition.x += (random2D(modelPosition.xz + uTime) - 0.5) * glitchStrength;modelPosition.z += (random2D(modelPosition.zx + uTime) - 0.5) * glitchStrength;gl_Position = projectionMatrix * viewMatrix * modelPosition;// Model normal/* 当第四个值为1.0时,向量为“同质”,所有3个变换(翻译、旋转、比例)都将被应用。当第四个值为0.0时,向量不是“同质的”,因此不会应用转换在正常情况下是理想的,因为正常不是一个职位,而是一个*/vec4 modelNormal = modelMatrix * vec4(normal,0.0); // 为什么设置0.0 就是不希望正常,保持法线向上vPosition = modelPosition.xyz;vNormal = modelNormal.xyz;
}
6.random2D.glsl 随机数方法
float random2D(vec2 value)
{return fract(sin(dot(value.xy, vec2(12.9898,78.233))) * 43758.5453123);
}
二、效果
Hologram Shader
总结
全息影像显示,可以加到自己个人的项目中。感觉还不错!
相关文章:

【Three.js基础学习】29.Hologram Shader
前言 three.js 通过着色器如何实现全息影像,以及一些动态的效果。 一些难点的思维,代码目录 下面图是摄像机视角观看影响上的时候,如何实现光影的渐变,透视以及叠加等。 一、代码 1.index.html <!DOCTYPE html> <html …...

文件包含进阶玩法以及绕过姿态
前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理文件包含漏洞的进阶玩法与绕过姿态 不涉及基础原理了 特殊玩法汇总 本地包含 文件包含上传文件 原理: php的文件包含有着把其他文件类型当做php代码执行的功效,文件上传一般会限制后缀&am…...

Markdown编辑器工具--Typora
下载链接...
PyTorch 的 torch.unbind 函数详解与进阶应用:中英双语
中文版 PyTorch 的 torch.unbind 函数详解与进阶应用 在深度学习中,张量的维度操作是基础又重要的内容。PyTorch 提供了许多方便的工具来完成这些操作,其中之一便是 torch.unbind。与常见的堆叠函数(如 torch.stack)相辅相成&am…...
四十六:如何使用Wireshark解密TLS/SSL报文?
TLS/SSL是保护网络通信的重要协议,其加密机制可以有效地防止敏感信息被窃取。然而,在调试网络应用或分析安全问题时,解密TLS/SSL流量是不可避免的需求。本文将介绍如何使用Wireshark解密TLS/SSL报文。 前提条件 在解密TLS/SSL报文之前&…...

【人工智能】OpenAI O1模型:超越GPT-4的长上下文RAG性能详解与优化指南
在人工智能(AI)领域,长上下文生成与检索(RAG) 已成为提升自然语言处理(NLP)模型性能的关键技术之一。随着数据规模与应用场景的不断扩展,如何高效地处理海量上下文信息,成…...

Ubuntu22.04搭建FTP服务器保姆级教程
在网络环境中,文件传输是一项至关重要的任务。FTP(文件传输协议)是一种基于客户端/服务器模式的协议,广泛用于在互联网上传输文件。Ubuntu作为一款流行的Linux发行版,因其稳定性和易用性而广受开发者和系统管理员的喜爱…...

操作系统(4)操作系统的结构
一、无序结构(整体结构或模块组合结构) 1.特点: 以大型表格和队列为中心,操作系统的各部分程序围绕着这些表格进行。操作系统由许多标准的、可兼容的基本单位(称为模块)构成,模块之间通过规定的…...
Python数据分析(OpenCV视频处理)
处理视频我们引入的还是numpy 和 OpenCV 的包 引入方式如下: import numpy as np import cv2 我们使用OpenCV来加载本地视频,参数就是你视频的路径就可以 #加载视频 cap cv2.VideoCapture(./1.mp4) 下面我们进行读取视频 #读取视频 flag,frame cap.re…...
跨域 Cookie 共享
跨域请求经常遇到需要携带 cookie 的场景,为了确保跨域请求能够携带用户的认证信息或其他状态,浏览器提供了 withCredentials 这个属性。 如何在 Axios 中使用 withCredentials 为了在跨域请求中携带 cookie,需要在 Axios 配置中设置 withCr…...

【视频异常检测】Real-Time Anomaly Detection and Localization in Crowded Scenes 论文阅读
文章信息: 发表于:CVPR2015(workshop) 原文链接:https://www.cv-foundation.org/openaccess/content_cvpr_workshops_2015/W04/papers/Sabokrou_Real-Time_Anomaly_Detection_2015_CVPR_paper.pdf Real-Time Anomaly D…...
设计模式12:抽象工厂模式
系列总链接:《大话设计模式》学习记录_net 大话设计-CSDN博客 参考: C设计模式:抽象工厂模式(风格切换案例)_c 抽象工厂-CSDN博客 1.概念 抽象工厂模式(Abstract Factory Pattern)是软件设计…...

论文学习——多种变化环境下基于多种群进化的动态约束多目标优化
论文题目:Multipopulation Evolution-Based Dynamic Constrained Multiobjective Optimization Under Diverse Changing Environments 多种变化环境下基于多种群进化的动态约束多目标优化(Qingda Chen , Member, IEEE, Jinliang Ding , Senior Member, …...

Jenkins参数化构建详解(This project is parameterized)
本文详细介绍了Jenkins中不同类型的参数化构建方法,包括字符串、选项、多行文本、布尔值和git分支参数的配置,以及如何使用ActiveChoiceParameter实现动态获取参数选项。通过示例展示了传统方法和声明式pipeline的语法 文章目录 1. Jenkins的参数化构建1…...

Cerebras 推出 CePO,填补推理与规划能力的关键空白
每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...
广东省食品销售中高级题库及答案
1.有关食品安全标准的说法正确的是(C)。 A.鼓励性标准 B.推荐性标准 C.强制性标准 D.引导性标准 2.食品经营许可证载明的许可事项发生变化的,食品经营者应当在变化后(D)个工作日内向原发证的食品药品监督管理部门申请变更经营许可。 A.3 B.5 C.7 D.10 3.食品销售经营者对食品…...

JAVA基础-深入理解Java内存模型(一)-- 重排序与先行发生原则(happens-before)
深入理解Java内存模型(一)-- 重排序 很棒的一个关于Java内存模型系列文章,首先感谢作者,转载自深入理解java内存模型系列文章 ,为了方便阅读,做了一些内容整合和重排版。 提纲 Java线程之间的通信对程序…...

【Lambda】java之lambda表达式stream流式编程操作集合
java之lambda表达式&stream流式编程操作集合 1 stream流概念1.1 中间操作1.1.1 无状态操作1.1.2 有状态操作 1.2 终端操作1.2.1 非短路操作1.2.2 短路操作 2 steam流的生成2.1 方式一:数组转为stream流2.2 方式二:集合转为steam流2.3 方式三…...

家具购物小程序+php
基于微信小程序的家具购物小程序的设计与实现 摘要 随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了基于微信小程序的家具购物小程序的设计与实现的开发全过程。通过分析基于微信小程序的家具购物小程序的设计与实…...

【GIS教程】使用GDAL-Python将tif转为COG并在ArcGIS Js前端加载-附完整代码
目录 一、数据格式 二、COG特点 三、使用GDAL生成COG格式的数据 四、使用ArcGIS Maps SDK for JavaScript加载COG格式数据 一、数据格式 COG(Cloud optimized GeoTIFF)是一种GeoTiff格式的数据。托管在 HTTP 文件服务器上,可以代替geose…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

练习(含atoi的模拟实现,自定义类型等练习)
一、结构体大小的计算及位段 (结构体大小计算及位段 详解请看:自定义类型:结构体进阶-CSDN博客) 1.在32位系统环境,编译选项为4字节对齐,那么sizeof(A)和sizeof(B)是多少? #pragma pack(4)st…...
Python爬虫实战:研究feedparser库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
Linux离线(zip方式)安装docker
目录 基础信息操作系统信息docker信息 安装实例安装步骤示例 遇到的问题问题1:修改默认工作路径启动失败问题2 找不到对应组 基础信息 操作系统信息 OS版本:CentOS 7 64位 内核版本:3.10.0 相关命令: uname -rcat /etc/os-rele…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

深度学习水论文:mamba+图像增强
🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...
【学习笔记】erase 删除顺序迭代器后迭代器失效的解决方案
目录 使用 erase 返回值继续迭代使用索引进行遍历 我们知道类似 vector 的顺序迭代器被删除后,迭代器会失效,因为顺序迭代器在内存中是连续存储的,元素删除后,后续元素会前移。 但一些场景中,我们又需要在执行删除操作…...