片元着色器中Blob反转方向异常:到达屏幕中心后消失的修复
GLSL Blob移动异常消失问题分析与修复
问题描述
原代码意图实现红色Blob沿Y轴向上移动,到达屏幕中心(Y=0位置)后反转方向向下移动,但实际运行时,Blob上移至中心后直接消失。
问题原因
- 帧间状态丢失导致位置计算错误:GLSL片段着色器逐帧重新执行,每次都会重新初始化
uBlob和direction,没有保留上一帧的状态。当uTime足够大使得blobPos > 0时,direction被反转,但后续计算uBlob.y时使用了完整的uTime值而非从反转时刻开始的增量,导致Blob直接跳转到屏幕外极远的位置(uBlob.y = -5 - uTime/1000),此时像素到Blob的距离平方dist2变得极大,1.0/dist2趋近于0,Blob因颜色值为0而消失。 - 方向反转逻辑未考虑时间阶段:仅在单帧内临时修改
direction,未根据uTime所处的阶段(到达中心前/后)计算正确的位移,导致位置计算逻辑完全错误。
修复方案
核心思路是通过计算到达反转点的时间阈值,分阶段计算Blob位置,避免依赖帧间状态:
- 先计算Blob从初始位置(Y=-5)移动到中心(Y=0)所需的时间
t_reverse。 - 根据当前
uTime是否超过t_reverse,分别计算正向或反向移动的位置。 - 也可以使用取模运算实现周期性来回移动,逻辑更简洁。
修复后代码
uniform float uTime; varying vec2 vXY; void main(void) { vec2 uBlob = vec2(0.0, -5.0); // 计算到达Y=0所需的时间:初始Y=-5,速度为1单位/1000时间单位 float t_reverse = 5.0 * 1000.0; float blobPos; if (uTime <= t_reverse) { // 到达中心前,正向移动 blobPos = uBlob.y + uTime / 1000.0; } else { // 到达中心后,反向移动:从Y=0开始,移动时间为uTime - t_reverse float reverse_time = uTime - t_reverse; blobPos = 0.0 - reverse_time / 1000.0; } uBlob.y = blobPos; vec4 color = vec4(0.0, 0.0, 0.0, 1.0); float dist2 = pow(vXY.x - uBlob.x, 2.0) + pow(vXY.y - uBlob.y, 2.0); // 增加小偏移避免dist2为0时出现无穷大 float red = 1.0 / (dist2 + 0.01); color = vec4(red, 0.0, 0.0, 1.0); gl_FragColor = color; }
更简洁的周期性实现(可选)
利用取模运算实现Blob在-5到0之间来回移动,无需分支判断:
uniform float uTime; varying vec2 vXY; void main(void) { vec2 uBlob = vec2(0.0, -5.0); // 周期为10000时间单位(去程5000,回程5000) float cycle = 10000.0; // 计算当前周期内的相对时间,转换为-5000到5000的范围 float relative_time = mod(uTime, cycle) - cycle/2.0; // 转换为Y轴位置:-5到0之间来回移动 uBlob.y = abs(relative_time)/1000.0 - 5.0; vec4 color = vec4(0.0, 0.0, 0.0, 1.0); float dist2 = pow(vXY.x - uBlob.x, 2.0) + pow(vXY.y - uBlob.y, 2.0); float red = 1.0 / (dist2 + 0.01); color = vec4(red, 0.0, 0.0, 1.0); gl_FragColor = color; }
补充说明
修复代码中额外增加了+0.01的偏移,避免Blob中心位置的dist2为0时出现无穷大的颜色值,防止渲染异常。
内容的提问来源于stack exchange,提问作者Jonas
相关产品推荐
相关产品推荐

