看Threejs好玩示例,学习创新与技术(GridDistortionEffect)
示例来自Grid Displacement Texture | Codrops (tympanus.net)。原以为比较容易,一上手发现技术要求挺深。可参考使用 Three.js GPGPU 和着色器的 RGB Shift 网格置换纹理 (tympanus.net)进行内容解析。
本文未完结...(2024年9月25日第二次更新,还有一次)
1、怎么看本文?
本文会简单的点到一些技术,这些了解基本概念,在日后工作中想到就有帮助。内容包括“第三章 什么是GPUComputationRenderer”。
有些内容需要沉入时间去理解,需要动脑子。这部分内容我也是经过仔细观察、调试才理解。适合时间多的同学。对本文涉及的技术,如果不经过调试,其实是比较难分析问题的。对glsl的调试,最佳策略就是修改gl_FragColor的输出,因为它可以反推哪些参数在影响效果。
最后,也希望大家注意到,随着ChatGPT的发展及应用,了解每一行代码已经不那么重要。核心是培养观察力和逻辑组织能力。
2、恐怖的效果
GridDistortionEffect的意思是网格失真效果。鼠标在场景移动的时候,图片会展示出网格状,并且给网格赋予一种眩晕颜色。这个效果非常适合放在悬疑片的开头。
20240924_224651
3、什么是GPUComputationRenderer
承接第二节,我们分析如下glsl。先尝试对A讨论点的代码进行注释 。
void main()
{
//B讨论点
vec2 uv = gl_FragCoord.xy/resolution.xy;
vec4 color = texture(uGrid,uv);
float dist = distance(uv,uMouse);
dist = 1.-(smoothstep(0.,uDistance/uGridSize,dist));
vec2 delta = uDeltaMouse;
//A讨论点
color.rg+=delta*dist;
//调试的时候对这里注释
color.rg*=min(uRelaxation,uMouseMove);
gl_FragColor = color;
}
图1 基于 GPUComputationRenderer的叠加渲染代码
结果发现渲染得到的效果如下——每个网格色块它回不去了!而根据纹理采样的一般逻辑,如果外部不加影响参数,纹理效果应该是可以回去的。为什么呢?
原因就在该着色器采用的纹理不是一般的纹理,而是由 GPUComputationRenderer 创建的内存纹理。GPUComputationRenderer 会继续使用上一次的纹理作为新的输入,因此不重置的情况系,就等于在一块画板永远的画下去。其中min(uRelaxation,uMouseMove)的作用就是把color.rg慢慢的置为0。
在这里我放一个问题:为啥图像有方块的效果,即本文标题的Grid,欢迎大家去猜,文末给答案。
GPUComputationRenderer它通过 WebGL 或 OpenGL 的 framebuffer 对象,可以将计算结果存储为纹理,并作为输入传递给后续的渲染步骤。
关于GPUComputationRenderer的使用可以直接询问ChatGPT。
GPUComputationRenderer一个典型案例是ThreeJS中鸟类飞行模拟(webgl_gpgpu_birds)。
4、彗星贪吃蛇
还是上面图1的代码,稍微改造下就可以变成下面的效果。这是怎么做到的呢?
彗星贪吃蛇的特点是蛇头跟随鼠标,有长长的尾巴,并且会逐步的消失。根据这个特点,代码应该实现如下三个特征:
- 获得鼠标的位置,鼠标范围内的点设置为比较亮的颜色。
- 与鼠标点距离远的位置的颜色逐步降低亮度。
- 如果要表现不同的颜色,那么就更鼠标的前进方向,向下向上(Y值变化多则绿色),向左向右(X值变化多则红色)。
改造后的代码如下,我把方法的作用写了出来。(有了我这个思路,后面自己做好看的贪吃蛇应该不成问题了吧。)
void main()
{
vec2 uv = gl_FragCoord.xy/resolution.xy;
vec4 color = texture(uGrid,uv);
//根据距离进行衰减,不要一下子就衰减了。
float dist = distance(uv,uMouse);
dist = 1.-(smoothstep(0.,uDistance/uGridSize,dist));
//不考虑鼠标移动的绝对量
vec2 delta = abs(uDeltaMouse);
//贪吃蛇头部
if(dist>0.02){
color.b=255.0;
}else{
color.b=0.0;
}
//贪吃蛇身体,头部因距离鼠标近,颜色越鲜艳
color.rg+=delta*dist;
//随着时间消退
color.rg*=min(uRelaxation,uMouseMove);
gl_FragColor = color;
}
5、一起摇摆
写到这里,我差不多明白本示例的逻辑了,哈哈。简单的说,就是原贴图的UV减去第四章得到颜色转换的UV,就能实现原贴图的失真混乱。技术示意图如下:
//原贴图UV
vec2 newUvs = coverUvs(uImageResolution,uContainerResolution);
//获得彗星贪吃蛇的颜色
vec2 squareUvs = coverUvs(vec2(1.),uContainerResolution);
vec4 displacement = texture2D(uGrid,squareUvs);
//彗星贪吃蛇的颜色转换为UV,并对原贴图UV进入扰动
vec2 finalUvs = newUvs - displacement.rg*0.01;
//得到扰动后的效果
vec4 finalImage = texture2D(uTexture,finalUvs);
gl_FragColor = finalImage;
6、余光乍现
未完待续..
原文地址:https://blog.csdn.net/htsitr2/article/details/142502144
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!