I have a game that runs on mobile devices (OpenGL ES 2.0) and for which I would like to create some sea water using the shaders. Now, the plane on which the sea water texture will be has only 4 vertices and I need it to remain like that (because of performance issues). So, I think, my only option is to simulate the water from the fragment shader. At conceptual level, how should I do it? I must mention I'm a beginner with the programmable pipeline (I barely learned the language, in some extent) and have no idea where should I start.
See the paper in the GPU Gems series treating this subject: http://http.developer.nvidia.com/GPUGems/gpugems_ch01.html
What you can do is to adapt that idea (Gerstner waves) and compute the normals for each of your rendered fragment. The way to do that would be to assign a water texture (without too much light information in it, since you're gonna compute colours on in the shader anyway). That texture also comes with a texcoord set mapping (for each of your 4 vertices you get an uv pair of texture coordinates in the range of [0,1]). All in all, you have a plane you can deform in the fragment shader: the [0,1]x[0,1] square described by your uv texcoordset. Each uv pair that will be interpolated and present in your fragment shader can be used to recover a normal vector like you would in the vertex shader. That is useful only if the water surface is relatively far away from the camera: since you can't deform/displace vertices, you can observe light reflecting in different directions and shading that surface according to a time variable. It should work in a sense and it should be easier and more convincing than distorting/moving a texture through texcoord manipulation as older game effects do.
Implementation details Consider the above picture to be your water surface given as a quad. When you prepare it for shader drawing, you must supply a texture to it (if you don't want to colour it solidly). When you bind a texture to it, for that to work, you mus associate to each of the vertices an attribute containing the texture coordinates. This is the so called uv set and, if there's no tiling involved on your quad, these could be given as A(0,0), B(1,0), C(1,1), D(0,1), where A, B, C, D are the vertices of your quad.
in the vertex shader
compute the position as you normally would and pass the uv you get as an attribute input variable to the fragment shader through a varying variable. The other, simpler way, could be to pass the object frame vertex coordinates (the positions prior to their multiplication through the worldvieprojection matrix). The varying descriptor will make sure the fragment gets an interpolated position on the quad. Let's call this variable xy and pass it to the frag shader as said.
in the fragment shader
Pass as an input uniform the world transformation matrix because you'll have to transform the computed normals to align with your lights position. Alternatively, pass the light already transformed in the object's own frame of reference and use the directly computed normal (should be quite faster and more elegant).
xy is a 2D vector and we need a 3D point on a water surface. Gerstner waves associate to a flat rectangle a height for each of its inner points. If you then consider the union of all of those xy displaced via that height function, you get the wave surface. We can't discuss positions in the frag shader, but we can compute and use normals for other purposes.
The normal you are looking for can be computed from the xy pair following this rationale: http://mathbin.net/105022 . For the waves to be animated, make sure to pass a time instance as an input uniform to the fragment shader. It is required as an input for the H(x,y,t) height function. That should be all. The rest is just plain lighting computation in a frag shader.