Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GLSL-ES Random grainy noise with FP16 limit

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.

like image 614
PerracoLabs Avatar asked Nov 24 '12 11:11

PerracoLabs


1 Answers

These are the ones that I use but I don't know if either works in a FP16 limit:

// 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);
}

I didn't create either of these. The link to the original author is above. I actually use rand2 and didn't have the issue mentioned on that blog. To make a greyscale noise do something like:

float randColor = rand(v_position);
gl_FragColor = vec4(randColor);

To do a full color noise it would take 3 times longer and you'd do:

gl_FragColor = vec4(rand(v_position), rand(v_position), rand(v_position), 1.0);

To add noise to whatever you're drawing you could:

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);

By the way, this is slow. On an iPhone5 this works fine with no major slowdown. But on a 4S it dropped by fps down to 30. If I removed adding the noise it raised it to 60. So beware.

like image 130
badweasel Avatar answered Sep 28 '22 02:09

badweasel