Shader for a cartoon-like sea

Hi! I would like to program a cartoon-like sea but my experience in shaders is very short.

My idea is to create a set of parallel ribbons modified by a sin function so they become wavy. The
ribbons will be moving (by changing the sin offset for each). I also want to use this
toon shader: http://www.lighthouse3d.com/tutorials/glsl-tutorial/toon-shading-version-iii/
to process the ribbons and make them look like 3d toon.

Should I use the geometryshaderexample project, modify it in order to make a plane of parallel lines and then
mix its original shader with the lighthouse shader example? is it possible to make the ribbons wavy by using
a sin function at any of the vertex or fragment shader? which one would be better (vertex? frag?).

Any advises or better ideas?

Thanks in advance!

Hi
I made an example base on your idea
but the output is not very satisfy for me
I would like to share the code with all OFers to improve this effect
ripple routine base on flight404.com processing ripple example
reference:
processing.org/discourse/yabb2/YaBB.pl?num=1159134845
testApp.h

  
#pragma once  
  
#include "ofMain.h"  
  
class testApp : public ofBaseApp{  
  
public:  
	void setup();  
	void update();  
	void draw();  
  
	void keyPressed  (int key);  
	void mousePressed(int x, int y, int button);  
  
  
	ofShader shader;  
	void findRipples();  
	void swapBuffers();  
	void render();  
	void makeRipples(float _x, float  _y);  
	float				**r0;  
	float				**r1;  
	float				**r2;  
  
};  
  

testApp.cpp

  
  
#include "testApp.h"  
int xSize           = 1024;  
int ySize           = 768;  
int xMid            = xSize/2;  
int yMid            = ySize/2;  
int xRes            = 60;  
int yRes            = 60;  
float _decay		= .991;  
int res             = 15;  
float heightMulti = 1;  
float xm = 0, ym = 0;  
float xp = 0, yp = 0, zp = 0;  
float xa = 0, ya = 0, za = 0;  
float xb = 0, yb = 0, zb = 0;  
float elevation;  
  float azimuth;  
  float _distance;  
  bool lighting = true;  
  float angle = 0;  
  string msg = "press arraw key to rotat\npress space to toggle shader\nframerate :";  
void testApp::findRipples(){  
	for (int y=1; y<yRes-1; y++){  
		for (int x=1; x<xRes-1; x++){  
			r0[x][y] = (r1[x-1][y] + r1[x+1][y] + r1[x][y-1] + r1[x][y+1]) / 4.0;  
			r0[x][y] = r0[x][y] * 2.0 - r2[x][y];  
			r0[x][y] *= _decay;  
		}  
	}  
}  
  
void testApp::swapBuffers(){  
	for (int y=0; y<yRes; y++){  
		for (int x=0; x<xRes; x++){  
			r2[x][y] -= (r2[x][y] - r1[x][y]) * _decay;  
			r1[x][y] -= (r1[x][y] - r0[x][y]) * _decay;  
		}  
	}  
}  
void testApp::render(){  
	for (int y=2; y<yRes; y++){  
		glBegin(GL_QUAD_STRIP);  
		for (int x=1; x<xRes; x++){  
			xp = (x - xRes/2) * res;  
			yp = (y - yRes/2) * res;  
			zp = r1[x][y] * heightMulti;  
  
			if (lighting){  
			ya = (y - yRes/2) * res;  
			za = r1[x][y] * heightMulti;  
			yb = ((y-1) - yRes/2) * res;  
			zb = r1[x-1][y-1] * heightMulti;  
  
			angle = ofVec2f(ya, za).angle(ofVec2f( yb, zb))*125.0 + 125;  
			ofNoFill();  
			ofSetColor(angle/2.0 + 125,50,angle);  
			} else {  
			ofSetColor(r0[x][y]/5.0 + 125.0);  
			}  
			glNormal3f(xp, yp, zp);  
			glVertex3f(xp, yp, zp);  
  
			xp = (x - xRes/2) * res;  
			yp = ((y-1) - yRes/2) * res;  
			zp = r1[x][y-1] * heightMulti;  
			if (lighting){  
				ya = ((y-1) - yRes/2) * res;  
				za = r1[x][y-1] * heightMulti;  
				yb = ((y-2) - yRes/2) * res;  
				zb = r1[x-1][y-2] * heightMulti;  
  
				angle = ofVec2f(ya, za).angle(ofVec2f( yb, zb))*125.0 + 125;  
			ofNoFill();  
				ofSetColor(angle/2.0 + 125,50,angle);  
  
			} else {  
			ofSetColor(r0[x][y-1]/5.0 + 125.0);  
			}  
			glNormal3f(xp, yp, zp);  
			glVertex3f(xp, yp, zp);  
		}  
		glEnd();  
	}  
}  
//--------------------------------------------------------------  
void testApp::makeRipples(float _x, float  _y){  
	xm = ofClamp((int)(_x/(xSize/xRes)),0,xRes-1);  
	ym = ofClamp((int)(_y/(ySize/yRes)),0,xRes-1);  
	for (int y=1; y<yRes-1; y++){  
		for (int x=1; x<xRes-1; x++){  
			float d = ofDist(xm,ym,x,y);  
			if (d < 3){  
				r1[x][y] -= pow(((3 - d)/3.0),2) * 500.0;  
			}  
		}  
	}  
}  
//--------------------------------------------------------------  
void testApp::setup(){  
	glEnable(GL_DEPTH_TEST);  
	ofSetWindowShape(xSize,ySize);  
	ofSetFrameRate(60);  
	//ofHideCursor();  
	//pov = POV(200);  
	r0 = new float* [xRes];  
	r1 = new float* [xRes];  
	r2 = new float* [xRes];  
	  
	for(int y = 0 ; y < yRes ; y++)  
	{  
		r0[y] = new float [yRes];  
		r1[y] = new float [yRes];  
		r2[y] = new float [yRes];  
		for(int x = 0 ; x < xRes ; x++)	  
		{  
			r0[y][x] = 0;  
			r1[y][x] = 0;  
			r2[y][x] = 0;  
		}  
	}  
  
	shader.load("shaders/toon.vert","shaders/toon.frag");  
	_distance     = 200;  
    azimuth      = 0.0;  
    elevation    = 0.0;  
}  
  
//--------------------------------------------------------------  
void testApp::update(){  
	  
	findRipples();  
	swapBuffers();  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
	glEnable(GL_DEPTH_TEST);  
	if(lighting)shader.begin();  
	ofPushMatrix();  
	ofTranslate(xMid,yMid,_distance);  
    ofRotate(elevation,1,0,0);  
    ofRotate(azimuth,0,0,1);  
	render();  
	//glutSolidTeapot(10);  
	ofPopMatrix();  
	  
	if(lighting)shader.end();  
  
	glDisable(GL_DEPTH_TEST);  
	ofSetColor(255);  
	ofDrawBitmapString(msg+ofToString(ofGetFrameRate()),20,20);  
}  
  
//--------------------------------------------------------------  
void testApp::keyPressed(int key){  
if (key == OF_KEY_UP){  
    elevation += 11;  
  } else if (key == OF_KEY_DOWN){  
    elevation -= 1;  
  } else if (key == OF_KEY_RIGHT){  
    azimuth -= 1;  
  } else if (key == OF_KEY_LEFT){  
    azimuth += 1;  
  }  
   if (key == ' '){  
    lighting = !lighting;  
  }  
}  
  
//--------------------------------------------------------------  
void testApp::mousePressed(int x, int y, int button){  
	makeRipples(x,y);  
}  
  

thanks

Ripple.zip

Ripple2.zip

Hello I want to try the example, but the Ripple.zip and Ripple2.zip is not exist, could you share it again? thx