I created a wave equation shader on shadertoy.com: You can see how it works by the link https://www.shadertoy.com/view/dtsyD2
Then I copied the code into my Android project working with GLES 2.0, changed texture()
to texture2D()
and also replaced fragColor
and fragCoord
with global gl_FragColor
and gl_FragCoord
. But the result doesn't look the same as on shadertoy (which works with WebGL).
Here's how it looks on Android:
What did I do wrong? Maybe there's something I didn't take into account.
Here is my code for vertex shaders (identical for both the main and buffer programs):
attribute vec2 pos;
void main()
{
gl_Position = vec4(pos.xy, 0.0, 1.0);
}
Here is my code for main fragment shader:
precision lowp float;
uniform vec2 iResolution;
uniform sampler2D iChannel0;
void main()
{
vec2 uv = gl_FragCoord.xy / iResolution.xy;
gl_FragColor = texture2D(iChannel0, uv);
}
Here is my code for buffer fragment shader:
precision lowp float;
uniform vec3 iMouse;
uniform vec2 iResolution;
uniform float iTime;
uniform sampler2D iChannel0;
const float delta = 1.0;
void main()
{
float pressure = texture2D(iChannel0, gl_FragCoord.xy / iResolution.xy).x;
float pVel = texture2D(iChannel0, gl_FragCoord.xy / iResolution.xy).y;
float pright = texture2D(iChannel0, (gl_FragCoord.xy + vec2(1., 0.)) / iResolution.xy).x;
float pleft = texture2D(iChannel0, (gl_FragCoord.xy + vec2(-1., 0.)) / iResolution.xy).x;
float pup = texture2D(iChannel0, (gl_FragCoord.xy + vec2(0., 1.)) / iResolution.xy).x;
float pdown = texture2D(iChannel0, (gl_FragCoord.xy + vec2(0., -1.)) / iResolution.xy).x;
// Apply horizontal wave function
pVel += delta * (-2.0 * pressure + pright + pleft) / 4.0;
// Apply vertical wave function (these could just as easily have been one line)
pVel += delta * (-2.0 * pressure + pup + pdown) / 4.0;
// Change pressure by pressure velocity
pressure += delta * pVel;
// "Spring" motion. This makes the waves look more like water waves and less like sound waves.
pVel -= 0.005 * delta * pressure;
// Velocity damping so things eventually calm down
pVel *= 1.0 - 0.002 * delta;
// Pressure damping to prevent it from building up forever.
pressure *= 0.999;
//x = pressure. y = pressure velocity. Z and W = X and Y gradient
gl_FragColor.xyzw = vec4(pressure, pVel, (pright - pleft) / 2.0, (pup - pdown) / 2.0);
if (iMouse.z > 1.0) {
float dist = distance(gl_FragCoord.xy, iMouse.xy);
if (dist <= 20.0) {
gl_FragColor.x += 1.0 - dist / 20.0;
}
}
}
Answer: OpenGL's GL_RGBA
format clamps values to the range [0,1]
:
https://registry.khronos.org/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml
So i did some adjustments to my shaders.
Mapping my values from [-1; 1]
to [0; 1]
in buffer shader before writing to gl_FragColor and changing
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, null)
to
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, null)
helped me. Also i had to switch my version from 2.0
to 3.0
Also there is some difference in shaders because values are not in range [-1; 1]
. But on 99% it works correctly.
Thank you Ruud Helderman for your assumption.
Update. I added blur into my fragment shader:
precision lowp float;
uniform vec2 iResolution;
uniform sampler2D iChannel0;
void main()
{
vec2 uv = gl_FragCoord.xy / iResolution.xy;
gl_FragColor = blur(iChannel0, gl_FragCoord.xy);
}
So now it works perfectly. I used blur function from this shader: https://www.shadertoy.com/view/XssSDs