Three.js 中实现自定义光圈 Shader 效果

news/2025/2/1 19:36:18/

目录

前言

Three.js 与自定义着色器的基础知识

效果展示代码概览

顶点着色器的作用

Uniforms 的作用

 动画实现


 

前言

Three.js 是一个功能强大的 WebGL 库,它让开发者能够轻松地创建复杂的 3D 场景、动画和交互效果。然而,有时候内置的材质和效果无法满足项目的特定需求。在这种情况下,我们可以通过使用自定义着色器来实现独特的视觉效果。 

Three.js 与自定义着色器的基础知识

在 Three.js 中,自定义着色器是通过 ShaderMaterial 实现的。ShaderMaterial 允许你完全控制顶点着色器和片段着色器的行为。以下是自定义着色器的一些关键组件:

  1. 顶点着色器(Vertex Shader):负责处理每个顶点的位置。
  2. 片段着色器(Fragment Shader):负责为每个像素计算颜色。
  3. Uniforms:在 JavaScript 和着色器之间传递的全局变量,用于动态更新效果。

效果展示代码概览

我们先来看一个完整的代码示例,后续会逐步拆解每个部分。

import * as THREE from 'three';// 顶点着色器
const vertexShader = `
varying vec2 vUv;
void main() {vUv = uv;gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`;// 片段着色器
const fragmentShader = `
uniform vec2 iResolution;
uniform float iTime;varying vec2 vUv;// SDF 圆形函数
float sdCircle(vec2 p, float r) {return length(p) - r;
}// 效果一:波纹效果
vec4 effect_1(vec2 uv) {float c = length(uv);c = abs(sin(c * 6.0 - iTime) / 6.0);c = smoothstep(0.0, 0.125, c);return vec4(vec3(1.0 - c), 1.0);
}// 效果二:辐射效果
vec4 effect_2(vec2 uv) {vec3 color = vec3(1.0, 2.0, 4.0);float c = length(uv);c = abs(sin(c * 2.0 - iTime) / 4.0);c = 0.0125 / c;color *= c;return vec4(color, 1.0);
}void main() {vec2 uv = vUv;float ratio = iResolution.x / iResolution.y;vec2 center = vec2(0.5, 0.5); // 中心位置uv -= center; // 居中 UV 坐标uv *= 2.0;    // 归一化uv.x *= ratio;// 选择效果(effect_1 或 effect_2)gl_FragColor = effect_2(uv);
}
`;// Uniforms 设置
const uniforms = {iResolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) },iTime: { value: 0 },
};// Shader 材质
const material = new THREE.ShaderMaterial({vertexShader,fragmentShader,uniforms,
});// 创建一个平面来应用 Shader
const geometry = new THREE.PlaneGeometry(2, 2);
const mesh = new THREE.Mesh(geometry, material);// 场景与相机设置
const scene = new THREE.Scene();
scene.add(mesh);
const camera = new THREE.Camera();// 渲染器设置
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);// 动画循环
function animate() {uniforms.iTime.value += 0.05; // 更新时间renderer.render(scene, camera);requestAnimationFrame(animate);
}animate();

顶点着色器的作用

顶点着色器定义了如何将三维点映射到二维屏幕上。在我们的代码中,顶点着色器非常简单,只是将 UV 坐标传递到片段着色器中:

varying vec2 vUv;
void main() {vUv = uv;gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}

vUv 是 UV 坐标,它描述了纹理如何映射到几何体表面。gl_Position 则是顶点的最终位置。

片段着色器解析 片段着色器是实现视觉效果的核心。在这个示例中,我们定义了两个效果函数:

效果一:波纹效果 波纹效果利用了 SDF(有符号距离函数)的特性,通过 sin 函数和 smoothstep 产生渐变波纹。

vec4 effect_1(vec2 uv) {float c = length(uv);c = abs(sin(c * 6.0 - iTime) / 6.0);c = smoothstep(0.0, 0.125, c);return vec4(vec3(1.0 - c), 1.0);
}

 效果二:辐射效果 辐射效果通过缩放颜色强度实现,创造出一种动态发光的视觉效果。

vec4 effect_2(vec2 uv) {vec3 color = vec3(1.0, 2.0, 4.0);float c = length(uv);c = abs(sin(c * 2.0 - iTime) / 4.0);c = 0.0125 / c;color *= c;return vec4(color, 1.0);
}

Uniforms 的作用

uniform 是一种全局变量,可以从 JavaScript 中传递给 GLSL。这里的 iResolution 和 iTime 是两个关键变量:

iResolution:屏幕分辨率,用于调整 UV 坐标比例。 iTime:时间变量,用于为动画效果提供动态输入。 将着色器应用到平面 为了将着色器可视化,我们将其应用到一个 2D 平面上。PlaneGeometry 用于创建一个平面,而 ShaderMaterial 则绑定了我们的着色器。

 动画实现

通过在每一帧更新 iTime,我们可以为效果注入时间维度,从而实现动态动画: 

function animate() {uniforms.iTime.value += 0.05; // 更新时间renderer.render(scene, camera);requestAnimationFrame(animate);
}

 


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

相关文章

图漾相机——C++语言属性设置

文章目录 前言1.SDK API功能介绍1.1 Device组件下的API测试1.1.1 相机工作模式设置(TY_TRIGGER_PARAM_EX)1.1.2 TY_INT_FRAME_PER_TRIGGER1.1.3 TY_INT_PACKET_DELAY1.1.4 TY_INT_PACKET_SIZE1.1.5 TY_BOOL_GVSP_RESEND1.1.6 TY_BOOL_TRIGGER_OUT_IO1.1.…

Pyecharts之图表样式深度定制

在数据可视化的世界里,图表的样式定制对于提升数据展示效果和用户体验至关重要。Pyecharts 提供了丰富的样式定制功能,能让我们创建出独具特色的可视化作品。本篇将深入探讨如何使用 Pyecharts 为图表添加线性渐变色、径向渐变色,以及如何添加…

从传统桌面应用到现代Web前端开发:技术对比与高效迁移指南20250122

从传统桌面应用到现代Web前端开发:技术对比与高效迁移指南 在软件开发的广袤领域中,技术栈犹如奔腾不息的江河,持续迭代演进。从早期的桌面应用开发(如MFC、PyQt)到现代Web前端框架(如React、Vue&#xff…

SpringBoot开发(二)Spring Boot项目构建、Bootstrap基础知识

1. Spring Boot项目构建 1.1. 简介 基于官方网站https://start.spring.io进行项目的创建. 1.1.1. 简介 Spring Boot是基于Spring4框架开发的全新框架,设计目的是简化搭建及开发过程,并不是对Spring功能上的增强,而是提供了一种快速使用Spr…

Hive:日志,hql运行方式,Array,行列转换

日志 可以在终端通过 find / | grep hive-log4j2 命令查找Hive的日志配置文件 这些文件用于配置Hive的日志系统。它们不属于系统日志也不属于Job日志,而是用于配置Hive如何记录系统日志和Job日志, 可以通过hive-log4j2 查找日志的位置 HQL的3种运行方式 第1种就是l…

C语言指针专题二 -- 字符指针与字符串

目录 1. 字符指针与字符串的核心原理 字符串的本质 字符串的存储 字符指针的特性 字符指针的操作 2. 编程实例 3. 常见陷阱与注意事项 4. 总结 1. 字符指针与字符串的核心原理 字符串的本质 C语言中没有独立的字符串类型,字符串本质是 以\0(空…

CTF-web: phar反序列化+数据库伪造 [DASCTF2024最后一战 strange_php]

step 1 如何触发反序列化? 漏洞入口在 welcome.php case delete: // 获取删除留言的路径,优先使用 POST 请求中的路径,否则使用会话中的路径 $message $_POST[message_path] ? $_POST[message_path] : $_SESSION[message_path]; $msg $userMes…

双向链表在系统调度、游戏、文本编辑及组态方面的应用

在编程的奇妙世界里,数据结构就像是一把把神奇的钥匙(前面我们介绍过单向链表的基础了,这里我们更进一步),能帮我们打开解决各种问题的大门。今天,咱们就来聊聊其中一把特别的钥匙——双向链表。双向链表和…