0

I've been playing with shaders with a toy called ShaderToy and trying to create a top-down view water effect for a 2D game based on the code (for the shader) from Jonas Wagner. You can easily copy/paste this code in ShaderToy and see the effect.

The shader looks cool in ShaderToy, but when I try to replicate the same in my code, something goes wrong, see image below:

http://ivan.org.es/temp/shader_problems.png

My vertex shader (I don't know what's the one used in ShaderToy):

uniform mat4 Projection;
attribute vec2 Position;

void main(){
    gl_Position = Projection*vec4(Position, 0.0, 1.0);
}

The Fragment shader:

precision lowp float;

vec3 sunDirection = normalize(vec3(0.0, -1.0, 0.0));
vec3 sunColor = vec3(1.0, 0.8, 0.7);
vec3 eye = vec3(0.0, 1.0, 0.0);

vec4 getNoise(vec2 uv){
    vec2 uv0 = (uv/103.0)+vec2(iGlobalTime/17.0, iGlobalTime/29.0);
    vec2 uv1 = uv/107.0-vec2(iGlobalTime/-19.0, iGlobalTime/31.0);
    vec2 uv2 = uv/vec2(897.0, 983.0)+vec2(iGlobalTime/101.0, iGlobalTime/97.0);
    vec2 uv3 = uv/vec2(991.0, 877.0)-vec2(iGlobalTime/109.0, iGlobalTime/-113.0);
    vec4 noise = (texture2D(iChannel0, uv0)) +
                 (texture2D(iChannel0, uv1)) +
                 (texture2D(iChannel0, uv2)) +
                 (texture2D(iChannel0, uv3));
    return noise*0.5-1.0;
}

void sunLight(const vec3 surfaceNormal, const vec3 eyeDirection, float shiny, float spec, float diffuse, inout vec3 diffuseColor, inout vec3 specularColor){
    vec3 reflection = normalize(reflect(-sunDirection, surfaceNormal));
    float direction = max(0.0, dot(eyeDirection, reflection));
    specularColor += pow(direction, shiny)*sunColor*spec;
    diffuseColor += max(dot(sunDirection, surfaceNormal),0.0)*sunColor*diffuse;
}

void main(){
    vec2 uv = gl_FragCoord.xy / iResolution.xy;
    uv *= 100.0;

    vec4 noise = getNoise(uv);
    vec3 surfaceNormal = normalize(noise.xzy*vec3(2.0, 1.0, 2.0));

    vec3 diffuse = vec3(0.3);
    vec3 specular = vec3(0.0);

    vec3 worldToEye = vec3(0.0, 1.0, 0.0);//eye-worldPosition;
    vec3 eyeDirection = normalize(worldToEye);
    sunLight(surfaceNormal, eyeDirection, 100.0, 1.5, 0.5, diffuse, specular);

    gl_FragColor = vec4((diffuse+specular+vec3(0.1))*vec3(0.3, 0.5, 0.9), 1.0);
}

Please notice that the fragment shader code is exactly the same in ShaderToy and in my engine, it seems to me like uv coords from gl_FragCoord are somehow wrong or a precision problem, because after a while the effect goes worse and worse. I'm using an orthographic projection, but it shouldn't have too much to do with this since I'm getting uv coordinates directly from screen.

Some insights on what's going on?

Ivan
  • 51
  • 1
  • 6
  • 1
    Try increasing the precision as described here http://stackoverflow.com/a/6336285/187752 – Kimi Aug 06 '13 at 12:11
  • Ahh... I was loading my textures with GL_CLAMP_TO_EDGE and the noise function assumed GL_REPEAT. Now it works. – Ivan Aug 06 '13 at 14:55
  • Please answer your own question. But anyways you have to specify precision in fragment shaders - this is according to OpenGL ES 2.0 specs. Please read link provided by @Kimi for more info. – keaukraine Aug 07 '13 at 10:18
  • Done. I've updated the code also, now specifying precision. – Ivan Aug 07 '13 at 16:49

1 Answers1

0

It turns out that I was loading my textures with

glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

The shader noise function was expecting GL_REPEAT instead.

Ivan
  • 51
  • 1
  • 6