尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

学习threejs,使用自定义GLSL 着色器,实现抽象艺术特效 - 实践

学习threejs,使用自定义GLSL 着色器,实现抽象艺术特效 - 实践
📅 发布时间:2026/6/20 14:10:52

学习threejs,使用自定义GLSL 着色器,实现抽象艺术特效 - 实践

‍⚕️ 主页: gis分享者
‍⚕️ 感谢各位大佬 点赞 收藏⭐ 留言 加关注✅!
‍⚕️ 收录于专栏:threejsgis工程师


文章目录

  • 一、前言
    • 1.1 ☘️GLSL着色器
      • 1.1.1 ☘️着色器类型
      • 1.1.2 ☘️工作原理
      • 1.1.3 ☘️核心特点
      • 1.1.4 ☘️应用场景
      • 1.1.5 ☘️实战示例
  • 二、使用自定义GLSL 着色器,实现抽象艺术特效
    • 1. ☘️实现思路
    • 2. ☘️代码样例


一、前言

本文详细介绍如何基于threejs在三维场景中使用自定义GLSL 着色器,实现抽象艺术特效。亲测可用。希望能帮助到您。一起学习,加油!加油!

1.1 ☘️GLSL着色器

GLSL(OpenGL Shading Language)是OpenGL的核心编程语言,用于编写图形渲染管线中可定制的计算逻辑。其核心设计目标是通过GPU并行计算实现高效的图形处理,支持从基础几何变换到复杂物理模拟的多样化需求。

1.1.1 ☘️着色器类型

顶点着色器(Vertex Shader)

  • 功能:处理每个顶点的坐标变换(如模型视图投影矩阵变换)、法线计算及顶点颜色传递。
  • 输出:裁剪空间坐标gl_Position,供后续光栅化阶段使用。

片段着色器(Fragment Shader)

  • 功能:计算每个像素的最终颜色,支持纹理采样、光照模型(如Phong、PBR)及后处理效果(如模糊、景深)。
  • 输出:像素颜色gl_FragColor或gl_FragColor(RGBA格式)。

计算着色器(Compute Shader,高级)

  • 功能:执行通用并行计算任务(如物理模拟、图像处理),不直接绑定渲染管线。
  • 特点:通过工作组(Work Group)实现高效数据并行处理。

1.1.2 ☘️工作原理

渲染管线流程

  • 顶点处理:CPU提交顶点数据(位置、颜色、纹理坐标),GPU并行执行顶点着色器处理每个顶点。
  • 光栅化:将顶点数据转换为像素片段,生成片段着色器输入。
  • 片段处理:GPU并行执行片段着色器计算每个像素颜色。
  • 输出合并:将片段颜色与帧缓冲区混合,生成最终图像。

数据流动

  • 顶点属性:通过glVertexAttribPointer传递位置、颜色等数据,索引由layout(location=N)指定。
  • Uniform变量:CPU通过glGetUniformLocation传递常量数据(如变换矩阵、时间),在渲染循环中更新。
  • 内置变量: gl_Position(顶点着色器输出):裁剪空间坐标。 gl_FragCoord(片段着色器输入):当前像素的窗口坐标。
    gl_FrontFacing(片段着色器输入):判断像素是否属于正面三角形。

1.1.3 ☘️核心特点

语法特性

  • C语言变体:支持条件语句、循环、函数等结构,天然适配图形算法。
  • 向量/矩阵运算:内置vec2/vec3/vec4及mat2/mat3/mat4类型,支持点乘、叉乘等操作。
  • 精度限定符:如precision mediump float,控制计算精度与性能平衡。

硬件加速

  • 并行计算:GPU数千个核心并行执行着色器代码,适合处理大规模数据(如粒子系统、体素渲染)。
  • 内存模型:支持常量内存(Uniform)、纹理内存(Sampler)及共享内存(计算着色器),优化数据访问效率。

灵活性

  • 可编程管线:完全替代固定渲染管线,支持自定义光照、阴影、后处理效果。
  • 跨平台兼容性:OpenGL ES(移动端)与WebGL(Web)均支持GLSL,代码可移植性强。

1.1.4 ☘️应用场景

游戏开发

  • 实时渲染:实现PBR材质、动态阴影、屏幕空间反射。
  • 特效系统:粒子火焰、流体模拟、布料物理。
  • 性能优化:通过计算着色器加速AI计算、碰撞检测。

数据可视化

  • 科学计算:将多维数据映射为颜色/高度图(如气象数据、流场可视化)。
  • 信息图表:动态生成3D柱状图、热力图,增强数据表现力。

艺术创作

  • 程序化生成:使用噪声函数(如Perlin、Simplex)生成地形、纹理。
  • 交互式装置:结合传感器数据实时修改着色器参数,创造动态艺术作品。

教育与研究

  • 算法实验:实时调试光线追踪、路径追踪算法。
  • 教学工具:可视化线性代数运算(如矩阵变换、向量投影)。

1.1.5 ☘️实战示例

顶点着色器(传递法线与世界坐标):

#version 330 core
layout(location=0) in vec3 aPos;
layout(location=1) in vec3 aNormal;
out vec3 FragPos;
out vec3 Normal;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
void main() {
FragPos = vec3(model * vec4(aPos, 1.0));
Normal = mat3(transpose(inverse(model))) * aNormal; // 模型空间到世界空间的法线变换
gl_Position = projection * view * vec4(FragPos, 1.0);
}

片段着色器(实现Blinn-Phong光照):

#version 330 core
in vec3 FragPos;
in vec3 Normal;
out vec4 FragColor;
uniform vec3 lightPos;
uniform vec3 viewPos;
uniform vec3 lightColor;
uniform vec3 objectColor;
void main() {
// 环境光
vec3 ambient = 0.1 * lightColor;
// 漫反射
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;
// 镜面反射
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32);
vec3 specular = 0.5 * spec * lightColor;
// 最终颜色
vec3 result = (ambient + diffuse + specular) * objectColor;
FragColor = vec4(result, 1.0);
}

官方文档

二、使用自定义GLSL 着色器,实现抽象艺术特效

1. ☘️实现思路

使用自定义GLSL 着色器定义THREE.ShaderMaterial材质material,定义THREE.PlaneGeometry作为颜色渲染平面,实现抽象艺术特效。具体代码参考代码样例。可以直接运行。

2. ☘️代码样例

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>glsl颜色_抽象艺术作品</title><style>body {margin: 0;overflow: hidden;background: #020010;}canvas {display: block;width: 100vw;height: 100vh;}</style></head><body></body><script type="importmap">{"imports": {"three": "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js"}}</script><script type="module">import * as THREE from 'three';const scene = new THREE.Scene();scene.background = new THREE.Color(0x000000);const camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1);const renderer = new THREE.WebGLRenderer({ antialias: true });renderer.setSize(window.innerWidth, window.innerHeight);document.body.appendChild(renderer.domElement);const material = new THREE.ShaderMaterial({uniforms: {time: { value: 0 },resolution: { value: new THREE.Vector2(window.innerWidth, window.innerHeight) },mouse: { value: new THREE.Vector2(0.5, 0.5) }},vertexShader: `varying vec2 vUv;void main() {vUv = uv;gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);}`,fragmentShader: `uniform float time;uniform vec2 resolution;uniform vec2 mouse;varying vec2 vUv;mat2 rot(float a) {float s = sin(a);float c = cos(a);return mat2(c, -s, s, c);}void main() {vec2 FC = gl_FragCoord.xy;vec2 r = resolution;float t = time;vec4 o = vec4(0.0);vec2 uv = (FC * 2.0 - r.xy) / r.y;vec3 rayDir = normalize(vec3(uv, 1.0));for(float i = 0.0; i < 20.0; i++) {float z = i * 0.5 + 0.1;vec3 p = z * rayDir;vec2 mouseOffset = (mouse - 0.5) * 1.0;p.xz *= rot(t * 0.2 + mouseOffset.x);p.yz *= rot(t * 0.15 + mouseOffset.y);vec3 a = p;float d;for(d = 1.0; d < 4.0; d += 1.0) {a -= sin(a * d + t + i*0.1).yzx / (d * 0.8);}vec3 q = abs(a);float mx = max(max(q.x, q.y), q.z);float s = a.z + a.y - t;d = abs(2.0 - mx) + abs(cos(s)) / 7.0;float z_col = z + d;vec4 colorPhase = vec4(0.0, 2.0 + mouse.y * 2.0, 4.0 - mouse.y * 2.0, 0.0);o += (cos(s - z_col + colorPhase) + 1.0) / (d*0.5 + 0.01);}o = o / 20.0;o = o / (1.0 + o);o = smoothstep(0.15, 0.85, o);gl_FragColor = o;gl_FragColor.a = 1.0;}`});const geometry = new THREE.PlaneGeometry(2, 2);const mesh = new THREE.Mesh(geometry, material);scene.add(mesh);window.addEventListener('resize', () => {const width = window.innerWidth;const height = window.innerHeight;renderer.setSize(width, height);material.uniforms.resolution.value.set(width, height);});window.addEventListener('mousemove', (event) => {material.uniforms.mouse.value.x = event.clientX / window.innerWidth;material.uniforms.mouse.value.y = 1.0 - (event.clientY / window.innerHeight);});function animate() {requestAnimationFrame(animate);material.uniforms.time.value += 0.02;renderer.render(scene, camera);}window.onload = function () {animate();}</script></html>

效果如下
在这里插入图片描述
参考:源码

相关新闻

  • 广西省贵港市自建房设计公司哪家强?2026年最新权威靠谱测评榜单抢先看 - 苏木2025
  • 为什么你的CUDA程序跑不快?深度剖析C语言内核编译的3大常见错误
  • Yomiuri Shimbun日媒接触:进入日本市场的第一步

最新新闻

  • 2026 年晋中厨卫屋顶防水修缮三家对比测评 吉修匠 99.8 分 - 吉修匠
  • 北京外国语大学考研辅导班TOP推荐:核心指南与深度拆解 - michalwang
  • 嘉湖黄金回收大摸底!平湖海宁嘉善三地亲测,这三家店让街坊们彻底放心 - 百福黄金回收
  • 综合能力实训笔记——2026.6.4
  • Python setuptools高危漏洞解析:供应链攻击与安全加固实践
  • 视频压缩革命:如何用开源工具CompressO让文件体积缩小90%而不失画质

日新闻

  • 信任的进化:技术实现详解——如何用JavaScript构建博弈论模拟器
  • Terrakube自定义工作流:如何集成OPA、Infracost等工具扩展IaC能力
  • grunt-concurrent快速入门:5分钟学会并行运行Grunt任务

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号