我正在尝试使用严格 FP16 限制来编写紧凑且简单的噪声函数。 这是我到目前为止所发布的内容,但我认为在操作中某个地方的数字对于 fract 或 sin 来说太小了,因为在GPU中我必须写这个这些都在 FP16 限制范围内。关于我做错什么的任何想法?顺便说一句,我不能使用时间变量,也不能使用样本噪声纹理。我需要正确的功能必须紧凑,小巧且自给自足,并产生简单的颗粒噪声效果。 注意:下一个算法适用于任何桌面GPU卡,但在“ MALI 400 MP ”GPU上完全失败,因为这个浮点值具有FP16限制。
vec3 noise(vec3 color)
{
float variation = length(color);
float dot_product = dot(variation, -0.577350269);
float sin_result = sin(dot_product) * 1.19245;
float random = fract(sin_result);
return color + vec3(random);
}
如果任何人可以为 GLSL-ES 推荐任何其他随机功能,但严格遵守 FP16 限制,那么也会很棒。我知道其他随机实现,例如单纯形噪声,但是这些对于我需要做的事情来说太大而且速度太慢。因此 Perlin 和 Simplex 噪声算法不是一种选择。
答案 0 :(得分:1)
这些是我使用的但我不知道是否在FP16限制中工作:
// source: http://byteblacksmith.com/improvements-to-the-canonical-one-liner-glsl-rand-for-opengl-es-2-0/
highp float rand(vec2 co)
{
highp float a = 12.9898;
highp float b = 78.233;
highp float c = 43758.5453;
highp float dt= dot(co.xy ,vec2(a,b));
highp float sn= mod(dt,3.14);
return fract(sin(sn) * c);
}
float rand2(vec2 co)
{
return fract(sin(dot(co.xy,vec2(12.9898,78.233))) * 43758.5453);
}
我没有创造其中任何一个。上面是原作者的链接。我实际上使用rand2并没有在该博客上提到的问题。要制作灰度噪声,请执行以下操作:
float randColor = rand(v_position);
gl_FragColor = vec4(randColor);
要做全彩色噪音,需要花费3倍的时间,而且你会这样做:
gl_FragColor = vec4(rand(v_position), rand(v_position), rand(v_position), 1.0);
要为您绘制的任何内容添加噪音,您可以:
float randColor = rand(v_position) * .1; // to add 10% noise
gl_FragColor = vec4(gl_FragColor.r + randColor, gl_FragColor.g + randColor, gl_FragColor.b + randColor, 1.0);
顺便说一下,这很慢。在iPhone5上,这可以正常工作,没有重大减速。但是在4S上,fps下降到30.如果我删除了添加噪音,它会将其提高到60.所以要小心。
答案 1 :(得分:0)
哈希函数是否足够? Pearson hashing是在过去的日子里为8位寄存器设计的,并且非常简单:你对256字节的查找表进行硬编码(或者如果这是不可能的,那就是某种简单但非线性的排列)我们称之为T.对于输入的每个字节,你用哈希对它进行异或,然后查找该值以获得新的哈希值。
在您的情况下,让R,G和B成为您的输入字节。然后哈希可能是
E:要清楚,这不会产生随机输出,因为输入中没有随机性。但我认为它模仿了你的代码试图做的事情。
答案 2 :(得分:0)
尽管这是一个老问题,但我很久以前终于找到了解决方案。接下来是脚本,任何人都可以使用它。作为种子,您应该传递一个动态或随机值,您可以将其作为属性传递给着色器。
float getNoise(vec2 seed)
{
vec2 theta_factor_a = vec2(0.9898, 0.233);
vec2 theta_factor_b = vec2(12.0, 78.0);
float theta_a = dot(seed.xy, theta_factor_a);
float theta_b = dot(seed.xy, theta_factor_b);
float theta_c = dot(seed.yx, theta_factor_a);
float theta_d = dot(seed.yx, theta_factor_b);
float value = cos(theta_a) * sin(theta_b) + sin(theta_c) * cos(theta_d);
float temp = mod(197.0 * value, 1.0) + value;
float part_a = mod(220.0 * temp, 1.0) + temp;
float part_b = value * 0.5453;
float part_c = cos(theta_a + theta_b) * 0.43758;
return fract(part_a + part_b + part_c);
}