看Threejs好玩示例,学习创新与技术(GridDistortionEffect)(完结)

示例来自Grid Displacement Texture | Codrops (tympanus.net)。原以为比较容易,一上手发现技术要求挺深。可参考使用 Three.js GPGPU 和着色器的 RGB Shift 网格置换纹理 (tympanus.net)辅助学习。

1、怎么看本文?

本文会点到一些技术概念。这些了解基本概念,在日后工作中想到就有帮助。包括第3章“ 什么是GPUComputationRenderer”、第6章的“幻影”。

有些内容需要沉入时间。这部分内容我也是经过仔细观察及不断调试才理解的。适合时间多的同学。

对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的代码,稍微改造下就可以变成下面的效果。这是怎么做到的呢?

彗星贪吃蛇的特点是蛇头跟随鼠标,有长长的尾巴,并且会逐步的消失。根据这个特点,代码应该实现如下三个特征:

  1. 获得鼠标的位置,鼠标范围内的点设置为比较亮的颜色。
  2. 与鼠标点距离远的位置的颜色逐步降低亮度。
  3. 如果要表现不同的颜色,那么就更鼠标的前进方向,向下向上(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、幻影

我们都看过抖音里面,一个人跳舞身体出幻影的效果。原理是比较简单的,就是图像做一些偏移,不同颜色的偏移量不同,就可以得到这样的效果。代码也很简单如下:

float redStrengh = 1.+displacementStrengh*0.25;
redUvs += shift*redStrengh;    
    
float blueStrengh = 1.+displacementStrengh*1.5;
blueUvs += shift*blueStrengh; 
    
float greenStrengh = 1.+displacementStrengh*2.;
greenUvs += shift*greenStrengh;
    
float red = texture2D(uTexture,redUvs).r;
float blue = texture2D(uTexture,blueUvs).b;    
float green = texture2D(uTexture,greenUvs).g; 

7、总结

本示例初看比较难,但如果明白了什么是GPUComputationRenderer及其用途,那么就比较容易理解,可以将这个方法应用在非常多有意思的地方。最后回答为啥图像有方块的效果。答案是GPUComputationRenderer 可以设置尺寸,如果尺寸小于屏幕尺寸,那么铺满屏幕就是方块的了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值