I am trying to write a compact and simple noise function with a strictly FP16 limit. This is with what I came out so far, but I think somewhere on the operation the number gets too small for fract or sin, since in the GPU I must write this for these are within the FP16 limits. Any ideas on what am I doing wrong? BY the way, I cannot use a time variables, neither sample noise textures. The function I need to get right must be compact, small and self-sufficient, and produce a simple grainy noise effect. Note: The next algorithm works fine in any desktop GPU card, but fails completely on the "MALI 400 MP" GPU, since this one has a FP16 limitation on float values.
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);
}
If any one can recommend any other random function for GLSL-ES but strictly with a FP16 limit, would also be great. I know about other random implementations such as simplex noise, but these are too large and slow for what I need to do. So Perlin and Simplex noise algorithms are not an option.
Although is an old question I eventually found the solution long ago. Next the script so anyone can use it. As seed you should pass a dynamic or random value which you may pass to the shader as an attribute.
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);
}