无法理解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); }
代码说明:
u_resolution是屏幕分辨率 uniforms,需要在Shader外部传入(比如通过WebGL的JS代码)。- 通过坐标转换,把x轴限制在
[-2π, 2π],这样能完整展示sin(x)的两个周期变化。 - 通过判断当前像素y坐标与函数值的距离,绘制出清晰的曲线,
line_width可以调整线条粗细。
内容的提问来源于stack exchange,提问作者Pravin Poudel
相关产品推荐
相关产品推荐

