Random function

I ported some effects from Windows to the phone. One effect Windows doesn’t look like a phone. Patiently crop the GLSL code to locate this random function.

Float rand(vec2 co) {return fract(sin(dot(co.xy,vec2(12.9898,78.233)) * 43758.5453123); float rand(vec2 co) {return fract(sin(dot(co.xy,vec2(12.9898,78.233)) * 43758.5453123); }Copy the code

See here. Random / noise functions for GLSL


Correct Noise Map (Shadertoy)

The above functions are very common and generate random numbers between [0, 1]. Paste the following code in shadertoy

Float rand(vec2 co) {return fract(sin(dot(co.xy,vec2(12.9898,78.233)) * 43758.5453123); float rand(vec2 co) {return fract(sin(dot(co.xy,vec2(12.9898,78.233)) * 43758.5453123); } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 uv = fragCoord/iResolution.xy; float r = rand(uv); FragColor = vec4(r, r, r, 1.0); }Copy the code

Noise map can be generated:

Correct noise map

Error noise chart (iPhone 7+)

Run similar code on iPhone 7+

precision mediump float; varying vec2 vTexCoord; Float rand(vec2 co) {return fract(sin(dot(co.xy,vec2(12.9898,78.233)) * 43758.5453123); float rand(vec2 co) {return fract(sin(dot(co.xy,vec2(12.9898,78.233)) * 43758.5453123); } void main() { vec2 uv = vTexCoord; float r = rand(uv); Gl_FragColor = VEC4 (r, r, r, 1.0); }Copy the code

Wrong noise map generated with half of the data black (black for 0) due to poor accuracy.

Error noise diagram

precision

When porting, pay attention to precision. OpenGL is much more accurate than OpenGL ES. The following example

precision mediump float; varying vec2 vTexCoord; Void main() {float r = sin(1.0); Float k = abs(r-0.8414709848079); float k = abs(r-0.8414709848079); If (k < 0.0005) {gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); } else {gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0); }}Copy the code

Running on Windows, with enough accuracy, red. Running on iPhone 7+, not accurate enough, showing green. Even if you change mediump to highp, the iPhone 7+ still shows green.

According to tests, the number of the GLES is relatively safe between 4-digit integers (decimal) and 4-digit decimals (decimal). Of course, the smaller the range, the more accurate it is.


Amendment 1

Add the HIGHP flag

Float rand(highp vec2 co) {return fract(sin(dot(co.xy,vec2(12.9898,78.233)) * 43758.5453123); float rand(highp vec2 co) {return fract(sin(dot(co.xy,vec2(12.9898,78.233)) * 43758.5453123); }Copy the code

Get the noise map:

Noise Map (Amendment 1)

Fix 2

If you do not want to specify the highP precision, you cannot multiply the number by an Ethernet large number. Replace the original number of 43758.5453123 with 758.545.

Float rand(vec2 co) {return fract(sin(dot(co.xy,vec2(12.9898,78.233)) * 758.545); float rand(vec2 co) {return fract(sin(dot(co.xy,vec2(12.9898,78.233)) * 758.545); }Copy the code

Get the noise map:

Noise Map (Amendment 2)

It’s not random enough, but it’s better than fixing the first half of the black line, and it’s good enough for some situations.


Other considerations during migration

  • GLES must be explicitly written as a floating point number, as shown infloat k = 1;Compilation error, need to writeFloat k = 1.0;
  • Pay attention to precision. The value should not be too large or too small. If you want to be more consistent with the above random function, you should honestly load the noise texture and take its pixels as random values.
  • If use kEAGLRenderingAPIOpenGLES2 create EAGLContext, texture WrapMode GL_REPEAT there is a limit to, must be high to width of 2 n (2, 4, 8, 16, 32, 64 of these Numbers), or it will blank screen. KEAGLRenderingAPIOpenGLES3 no this limit, but some models do not support ES3, such as the iPhone 5 c.
  • The GLES does not support certain functions, such as fwidth.