当前位置: 首页 > news >正文

【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 通过着色器如何实现全息影像&#xff0c;以及一些动态的效果。 一些难点的思维&#xff0c;代码目录 下面图是摄像机视角观看影响上的时候&#xff0c;如何实现光影的渐变&#xff0c;透视以及叠加等。 一、代码 1.index.html <!DOCTYPE html> <html …...

文件包含进阶玩法以及绕过姿态

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

Markdown编辑器工具--Typora

下载链接...

PyTorch 的 torch.unbind 函数详解与进阶应用:中英双语

中文版 PyTorch 的 torch.unbind 函数详解与进阶应用 在深度学习中&#xff0c;张量的维度操作是基础又重要的内容。PyTorch 提供了许多方便的工具来完成这些操作&#xff0c;其中之一便是 torch.unbind。与常见的堆叠函数&#xff08;如 torch.stack&#xff09;相辅相成&am…...

四十六:如何使用Wireshark解密TLS/SSL报文?

TLS/SSL是保护网络通信的重要协议&#xff0c;其加密机制可以有效地防止敏感信息被窃取。然而&#xff0c;在调试网络应用或分析安全问题时&#xff0c;解密TLS/SSL流量是不可避免的需求。本文将介绍如何使用Wireshark解密TLS/SSL报文。 前提条件 在解密TLS/SSL报文之前&…...

【人工智能】OpenAI O1模型:超越GPT-4的长上下文RAG性能详解与优化指南

在人工智能&#xff08;AI&#xff09;领域&#xff0c;长上下文生成与检索&#xff08;RAG&#xff09; 已成为提升自然语言处理&#xff08;NLP&#xff09;模型性能的关键技术之一。随着数据规模与应用场景的不断扩展&#xff0c;如何高效地处理海量上下文信息&#xff0c;成…...

Ubuntu22.04搭建FTP服务器保姆级教程

在网络环境中&#xff0c;文件传输是一项至关重要的任务。FTP&#xff08;文件传输协议&#xff09;是一种基于客户端/服务器模式的协议&#xff0c;广泛用于在互联网上传输文件。Ubuntu作为一款流行的Linux发行版&#xff0c;因其稳定性和易用性而广受开发者和系统管理员的喜爱…...

操作系统(4)操作系统的结构

一、无序结构&#xff08;整体结构或模块组合结构&#xff09; 1.特点&#xff1a; 以大型表格和队列为中心&#xff0c;操作系统的各部分程序围绕着这些表格进行。操作系统由许多标准的、可兼容的基本单位&#xff08;称为模块&#xff09;构成&#xff0c;模块之间通过规定的…...

Python数据分析(OpenCV视频处理)

处理视频我们引入的还是numpy 和 OpenCV 的包 引入方式如下&#xff1a; import numpy as np import cv2 我们使用OpenCV来加载本地视频&#xff0c;参数就是你视频的路径就可以 #加载视频 cap cv2.VideoCapture(./1.mp4) 下面我们进行读取视频 #读取视频 flag,frame cap.re…...

跨域 Cookie 共享

跨域请求经常遇到需要携带 cookie 的场景&#xff0c;为了确保跨域请求能够携带用户的认证信息或其他状态&#xff0c;浏览器提供了 withCredentials 这个属性。 如何在 Axios 中使用 withCredentials 为了在跨域请求中携带 cookie&#xff0c;需要在 Axios 配置中设置 withCr…...

【视频异常检测】Real-Time Anomaly Detection and Localization in Crowded Scenes 论文阅读

文章信息&#xff1a; 发表于&#xff1a;CVPR2015&#xff08;workshop&#xff09; 原文链接&#xff1a;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:抽象工厂模式

系列总链接&#xff1a;《大话设计模式》学习记录_net 大话设计-CSDN博客 参考&#xff1a; C设计模式&#xff1a;抽象工厂模式&#xff08;风格切换案例&#xff09;_c 抽象工厂-CSDN博客 1.概念 抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;是软件设计…...

论文学习——多种变化环境下基于多种群进化的动态约束多目标优化

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

Jenkins参数化构建详解(This project is parameterized)

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

Cerebras 推出 CePO,填补推理与规划能力的关键空白

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

广东省食品销售中高级题库及答案

1.有关食品安全标准的说法正确的是(C)。 A.鼓励性标准 B.推荐性标准 C.强制性标准 D.引导性标准 2.食品经营许可证载明的许可事项发生变化的,食品经营者应当在变化后(D)个工作日内向原发证的食品药品监督管理部门申请变更经营许可。 A.3 B.5 C.7 D.10 3.食品销售经营者对食品…...

JAVA基础-深入理解Java内存模型(一)-- 重排序与先行发生原则(happens-before)

深入理解Java内存模型&#xff08;一&#xff09;-- 重排序 很棒的一个关于Java内存模型系列文章&#xff0c;首先感谢作者&#xff0c;转载自深入理解java内存模型系列文章 &#xff0c;为了方便阅读&#xff0c;做了一些内容整合和重排版。 提纲 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 方式一&#xff1a;数组转为stream流2.2 方式二&#xff1a;集合转为steam流2.3 方式三&#xf…...

家具购物小程序+php

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

【GIS教程】使用GDAL-Python将tif转为COG并在ArcGIS Js前端加载-附完整代码

目录 一、数据格式 二、COG特点 三、使用GDAL生成COG格式的数据 四、使用ArcGIS Maps SDK for JavaScript加载COG格式数据 一、数据格式 COG&#xff08;Cloud optimized GeoTIFF&#xff09;是一种GeoTiff格式的数据。托管在 HTTP 文件服务器上&#xff0c;可以代替geose…...

深入浅出:JavaScript 中的 `window.crypto.getRandomValues()` 方法

深入浅出&#xff1a;JavaScript 中的 window.crypto.getRandomValues() 方法 在现代 Web 开发中&#xff0c;随机数的生成看似简单&#xff0c;却隐藏着许多玄机。无论是生成密码、加密密钥&#xff0c;还是创建安全令牌&#xff0c;随机数的质量直接关系到系统的安全性。Jav…...

IT供电系统绝缘监测及故障定位解决方案

随着新能源的快速发展&#xff0c;光伏电站、储能系统及充电设备已广泛应用于现代能源网络。在光伏领域&#xff0c;IT供电系统凭借其持续供电性好、安全性高等优势成为光伏首选&#xff0c;但在长期运行中&#xff0c;例如老化、潮湿、隐裂、机械损伤等问题会影响光伏板绝缘层…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

蓝桥杯 冶炼金属

原题目链接 &#x1f527; 冶炼金属转换率推测题解 &#x1f4dc; 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V&#xff0c;是一个正整数&#xff0c;表示每 V V V 个普通金属 O O O 可以冶炼出 …...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

GitFlow 工作模式(详解)

今天再学项目的过程中遇到使用gitflow模式管理代码&#xff0c;因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存&#xff0c;无论是github还是gittee&#xff0c;都是一种基于git去保存代码的形式&#xff0c;这样保存代码…...

MySQL 8.0 事务全面讲解

以下是一个结合两次回答的 MySQL 8.0 事务全面讲解&#xff0c;涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容&#xff0c;并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念&#xff08;ACID&#xff09; 事务是…...

手机平板能效生态设计指令EU 2023/1670标准解读

手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读&#xff0c;综合法规核心要求、最新修正及企业合规要点&#xff1a; 一、法规背景与目标 生效与强制时间 发布于2023年8月31日&#xff08;OJ公报&…...

适应性Java用于现代 API:REST、GraphQL 和事件驱动

在快速发展的软件开发领域&#xff0c;REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名&#xff0c;不断适应这些现代范式的需求。随着不断发展的生态系统&#xff0c;Java 在现代 API 方…...