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

无法理解fract(sin(x)*1.0)函数图像,求助解惑

问题解惑:fract(sin(x))的图像差异与GLSL绘制方法

为什么实际图像和你的预期不同?

你预期的是一维函数的曲线(x取小范围连续值,y随x变化),但实际看到的是全屏噪声效果,核心原因是变量x的取值范围和应用场景不同:

  • 你的预期场景:x是小范围值(比如[-2π, 2π]),此时sin(x)在[-1,1]区间波动,fract(sin(x))会把负数部分加1(比如sin(x)=-0.5时,fract结果为0.5),最终得到在[0,1]区间内周期性波动的锯齿状曲线,也就是你预期的图像。
  • 实际Shader场景:x通常是屏幕像素的横向坐标(比如范围是[0, 屏幕宽度],可能是几百到几千),此时sin(x)的周期仅为2π≈6.28,x每增加6.28就完成一个周期,fract(sin(x))会把每个周期内的sin值映射到[0,1],当x范围极大时,这些值看起来就像随机噪声,再把每个x对应的函数值作为横向条纹填充全屏,就出现了你看到的噪声图像。

如何在GLSL中绘制你预期的一维函数图像?

通过将屏幕坐标转换为自定义坐标系,把x限制在小范围区间,然后绘制函数曲线即可。以下是片段着色器代码:

#ifdef GL_ES
precision mediump float;
#endif

uniform vec2 u_resolution;

void main() {
    // 将屏幕像素坐标转为[0,1]范围的UV坐标
    vec2 st = gl_FragCoord.xy / u_resolution;
    // 把x轴映射到[-2π, 2π],覆盖两个sin周期
    float x = st.x * 4.0 * 3.1415926 - 2.0 * 3.1415926;
    // 计算目标函数值
    float y_target = fract(sin(x));
    
    // 绘制函数曲线:距离曲线足够近的像素显示白色,其余黑色
    float line_width = 0.005;
    float distance_to_curve = abs(st.y - y_target);
    vec3 color = distance_to_curve < line_width ? vec3(1.0) : vec3(0.0);
    
    gl_FragColor = vec4(color, 1.0);
}

代码说明:

  1. u_resolution是屏幕分辨率 uniforms,需要在Shader外部传入(比如通过WebGL的JS代码)。
  2. 通过坐标转换,把x轴限制在[-2π, 2π],这样能完整展示sin(x)的两个周期变化。
  3. 通过判断当前像素y坐标与函数值的距离,绘制出清晰的曲线,line_width可以调整线条粗细。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 03:51:22