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

GLSL中sin/cos返回值超出[-1,1]范围的原因咨询

GLSL sin/cos 超出[-1,1]范围的跨设备异常解释

问题描述

我在ShaderToy中编写了如下GLSL着色器代码:

void mainImage( out vec4 fragColor, in vec2 fragCoord )
{
    // Normalized pixel coordinates (from 0 to 1)
    vec2 uv = fragCoord/iResolution.xy;

    
    vec3 col = vec3(0.);
    col.r = cos(uv.x* 0.05) > 1. ? 1. : 0.;
    col.g = sin(uv.y*0.05 - 1.5707963267948966) < -1. ? 1. : 0.;

    // Output to screen
    fragColor = vec4(col,1.0);
}

根据数学定义,sin和cos函数的返回值应始终处于[-1,1]区间内,因此我预期屏幕会完全显示黑色。但实际在Mac设备的Chrome和Firefox浏览器中运行时,会看到一条红色窄条和一条绿色窄条,而在iPad和iPhone上无此现象,恳请解释该异常的原因。

原因解释

这是浮点数精度误差导致的硬件级计算偏差,具体细节如下:

  • 不同GPU的浮点精度实现存在差异:Mac上的桌面级GPU(如Apple Silicon M系列或Intel核显)在计算三角函数时,因浮点数舍入、近似算法的特性,可能产生极轻微的结果溢出(比如1.0000001或-1.0000001)。而iOS设备的移动GPU对三角函数的精度校准更严格,或采用了不同的近似逻辑,避免了这种微小溢出。
  • 代码逻辑放大了误差:你的判断条件刚好卡在三角函数的理论边界上,一旦计算结果因精度问题略超出[-1,1],就会触发颜色通道的赋值,形成可见的窄条。比如uv.x*0.05的范围是0到0.05,cos在该区间的结果非常接近1,微小的浮点误差就可能让结果略大于1;同理,uv.y*0.05 - π/2的范围接近-π/2,sin在此处的理论值是-1,计算误差可能让结果略小于-1。

验证与修复方案

  • 验证:将判断条件改为cos(uv.x*0.05) > 1.000001或sin(uv.y*0.05 - 1.5707963267948966) < -1.000001,异常条纹会消失,屏幕显示预期的黑色。
  • 修复:实际开发中,避免依赖三角函数的严格边界做判断,或者给条件添加微小容差,比如用cos(...) > 1.0 + 1e-6来过滤精度误差带来的异常触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 13:50:08