You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用片段着色器实现类似Processing效果的鼠标拖拽轨迹

基于WebGL片段着色器实现Processing风格鼠标轨迹的解决方案

现有代码问题定位

  • 混合系数错误:你当前使用的stack*2.逻辑会让历史帧的颜色值不断超过1.0的有效范围,导致历史轨迹快速溢出丢失,仅鼠标附近的内容能正常显示
  • 缺少数值钳制:计算得到的pct可能出现负数,叠加后会抵消历史轨迹的正常颜色

核心实现逻辑

Processing不清除画布的堆叠绘制效果,本质是新绘制内容直接叠加到上一帧的画布结果。WebGL中可以通过ping-pong FBO(双离屏帧缓存)技术实现同样效果,不需要额外存储鼠标坐标历史数据:

  • 创建两个相同尺寸的纹理和对应的帧缓存对象,交替作为「上一帧结果输入」和「当前帧渲染输出」
  • 每帧先读取上一帧的纹理作为背景,再叠加当前鼠标位置的画笔图形,输出到另一个帧缓存
  • 最后将存储了完整轨迹的帧缓存纹理渲染到屏幕即可

修正后代码示例

# 离屏渲染Pass:叠加新内容到历史轨迹
void main(void) {
    float pct = 0.0;
    pct = distance(inData.v_texcoord.xy, vec2(mouse.x, 1.-mouse.y)) * SIZE;
    pct = 1.0 - pct - BRIGHTNESS;
    // 钳制数值避免负数
    pct = max(pct, 0.0);
    vec3 blob = vec3(pct);
    
    // 读取上一帧轨迹
    vec3 stack = texture(prevPass, inData.v_texcoord.xy).xyz;
    
    // 混合逻辑:完全保留历史轨迹 + 叠加当前画笔内容
    // 如果需要轨迹缓慢消失,可以改为 stack * 0.99 + blob * 0.1
    fragColor = vec4(stack + blob * 0.1, 1.0);
}
# 屏幕输出Pass:把轨迹纹理渲染到画布
void main(void) {
    fragColor = texture(prevPass, inData.v_texcoord);
}

注意事项

  • 初始化的时候需要先将存储历史的纹理填充为背景色(对应你Processing示例里的background(255))
  • 渲染离屏Pass的时候不要开启颜色清除,否则上一帧的结果会被清空
  • 如果要实现半透明轨迹的效果,可以调整blob的透明度系数,或者给混合逻辑加alpha通道处理

内容的提问来源于stack exchange,提问作者msalla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 05:36:04