easy/fast oceans

Started by
7 comments, last by VanKurt 20 years, 10 months ago
I have read a lot of posts, lectures and articles about water rendering but I''m still not sure about what to do. What I want to have is an ocean surrounding my island. Right now this ocean is just a really BIG quad with a moving texture on it. (Looks awfull!!) :-) But I don''t want to spend too much time on this thing and it should run very fast. So things like physically correct 3D Waves, realtime reflections etc. are not neccessary. I thought of this method: Draw 3 layers (Big quads), each one having it''s own moving (tiled) texture (different speed/direction) to create a goodlooking, animated (but flat) water surface. Then add something like a bumpmap to achieve a cool pseudo 3D wave effect. What do you think of this? Is this absolutely stupid? I''m happy about any ideas/suggestions! BTW: I like the water in BF1942. They have a nice *glow* (?) effect. The sun makes the water shine very nicely. (This screenshot doesn''t show this very well)
Advertisement
There is no recipe for making oceans, in my opinion it''s more of an artistic project than a technical challenge. Get some photos of beaches and oceans. I think the key points are:

- The way the ocean looks depends on the angle you view it at. From the sand, it''s mostly reflection of the sky. From above, you can see right down to the bottom (near the coast, anyway). Look up ''Fresnel effect'' for more info.

- I''m picturing the Hawaiian islands right now, but I imagine most Pacific islands would be similar - there is always lots of bright and dark green coral in patches around the coast, which you can kind of see through the waves. So your bottom static layer should be heavily burred sand and coral.

- You only really need one moving layer for waves, because only the top of the water really moves. The waves don''t break until they''re fairly near the shore, outside of a few hundred feet they''re just regular swells.

Good luck! Post a screen shot here when you''re done.

Tom
"E-mail is for geeks and pedophiles." -Cruel Intentions
how about animated bump maps? to create the waves

thats a really nice effect and in fact you don t translate a single water vertex

you could divide your ocean into a lot of quads
and all quads which lie in a certain radius around your player could be animated with vertex manipulation

sinus wave nothing difficult

you could also create a wave effect towards to beach by getting the ocean->island intersection edges by clipping the island polygons against the ocean top plane
and then create quads with animated wave textures with alpha channel

http://www.8ung.at/basiror/theironcross.html
@Basiror
That''s similar to what I was thinking about. Sounds great!
But the problem is that I don''t know anything about bumpmapping...

I found one tut about DOT3 in delphi but that didn''t help me much. I guess you don''t know where to find a "creating-a-cool-ocean-with-bumpmapping" tut???

Thanks, vK
um... ocean simulation tutorials are on naturewizard
if you want to get things fast, simply calculate the height of every fourth point (close to the camera & in the view frustum) and interpolate the other points using catmtull patches. you can "increase" your "waves" in radicaling your normals (double x, double z and same y)...
for the lighting simply use arb dot3 bumpmaps. (look at my post for the effect... )

[edited by - 666_1337 on June 17, 2003 10:42:39 AM]
our new version has many new and good features. sadly, the good ones are not new and the new ones are not good
The naturewizzard page seems to be about simulating 3d waves only. I think that''s to complicated right now, so I''d rather go for the bumpmap-approach.
The way you did that in your screenshot looks good! Any hints on how you did that? Or some good resource/tutorial?

Thanks a lot!
quote:
The way you did that in your screenshot looks good! Any hints on how you did that? Or some good resource/tutorial?

Thanks a lot!


tutorials i don''t have...
but i can give you the source... (I use the way it''s done at naturewizzard o_O)

void oceanWaves :: init(void) {    texture tex(env->getRootnodePointer()->getImageIOPointer()->loadImage("data/water_1.png"));  waterTexture = env->getRootnodePointer()->getTextureManagerPointer()->addTexture(&tex, GL_TEXTURE_2D, GL_TRUE);    texture _tex(env->getRootnodePointer()->getImageIOPointer()->loadImage("data/water_2.png"));  waterBumpMap = env->getRootnodePointer()->getTextureManagerPointer()->addTexture(&_tex, GL_TEXTURE_2D, GL_TRUE);    OCEAN_GRID_WIDTH = env->getRootnodePointer()->getTerrainPointer()->getWidth()/4;  OCEAN_GRID_HEIGHT = env->getRootnodePointer()->getTerrainPointer()->getHeight()/4;  sea       = (float*)malloc(sizeof(float)*OCEAN_GRID_WIDTH*OCEAN_GRID_HEIGHT);  normalMap = (float*)malloc(sizeof(float)*OCEAN_GRID_WIDTH*OCEAN_GRID_HEIGHT*3);      float windSpeed = env->wind.length();  float windDir = atan(env->wind.z/env->wind.x);    fpeak=0.13*GRAVITY_CONSTANT/windSpeed;  max_waves = 250;  for(int i = 0; i < max_waves; i++)   {	WAVE w;    waves.push_back(w);   }        int done = 0;  boost:rogress_display pt(max_waves);     while(done < max_waves)   {	WAVE *w = &waves[done];	float f = genrand();	if(f > 0.0f)     {	  w->lambda     = 2.0*3.141592*GRAVITY_CONSTANT/(pow( 2.0*3.141592*f,2.0));      w->k          = 2.0*3.141592/w->lambda;      w->omega      = sqrt(GRAVITY_CONSTANT*w->k);      w->freq       = w->omega / (2.0*3.141592);      w->periode    = 1.0f/w->freq;      w->direction  = (genrand()*2.0f)*3.141592;      w->dirX       = cos(w->direction)*0.5f;      w->dirY       = sin(w->direction)*0.5f;      float phi0   = 2*genrand()*3.141592;      float a0     = amplitude(w->freq, w->direction - windDir, w->k);      w->amplitude  = a0*cos( phi0 );      w->phase      = a0*sin( phi0 );	 }	 	if(fabs(w->amplitude) >=0.0001f )	 {      done++;	  ++pt;	 }   } }#define ax(x) ((x<0)?(x+OCEAN_GRID_WIDTH)(x>=OCEAN_GRID_WIDTH)?(x-OCEAN_GRID_WIDTH):x))#define ay(y) ((y<0)?(y+OCEAN_GRID_HEIGHT)(y>=OCEAN_GRID_HEIGHT)?(y-OCEAN_GRID_HEIGHT):y)) void oceanWaves :: draw(void) {  float time = 0.001f * glutGet(GLUT_ELAPSED_TIME);  viewFrustum *vf = env->getRootnodePointer()->getViewFrustumPointer();  glPushMatrix();    glScalef(4.0f, 1.0f, 4.0f);    vf->redefine();      for(int i = 0; i < OCEAN_GRID_WIDTH; i++)	  for(int j = 0; j < OCEAN_GRID_HEIGHT; j++)	   {		if(! vf->sphereIsInside( point4f((float)((float)OCEAN_GRID_WIDTH*-0.5f + i), 0.0f, (float)((float)OCEAN_GRID_HEIGHT*-0.5f + j)), 2.0f) )		  continue;        point4f campos = env->getRootnodePointer()->getCameraPointer()->position;				point4f actpos( ((float)OCEAN_GRID_WIDTH*-0.5f + i)*4.0f, 0.0f, (OCEAN_GRID_HEIGHT*-0.5f + j)*4.0f);		vector4f vec = campos.vectorTo(actpos);		if( vec.length() - 5.0f > env -> getFogDistance())		  continue;				float height = 0.0f;		for(int k = 0; k < waves.size(); k++)		  height += waves[k].amplitude*sin(waves[k].phase + waves[k].omega * waves[k].freq * (time + waves[k].dirX * i + waves[k].dirY * j ) );        sea[i*OCEAN_GRID_WIDTH + j] = height;	   }	   	for(int i = 0; i < OCEAN_GRID_WIDTH; i++)	  for(int j = 0; j < OCEAN_GRID_WIDTH; j++)	   {		vector4f v(sea[ax(i+1)*OCEAN_GRID_WIDTH + j] - sea[ax(i-1)*OCEAN_GRID_WIDTH + j],		           4.0f,		           sea[i*OCEAN_GRID_WIDTH+ay(j+1)] - sea[i*OCEAN_GRID_WIDTH + ay(j-1)]);		v.x *= 4.0f;		v.z *= 4.0f;		v.normalize();				size_t actualindex = (i * OCEAN_GRID_WIDTH + j)*3;		normalMap[actualindex  ] = v.x;		normalMap[actualindex+1] = v.y;		normalMap[actualindex+2] = v.z;	   }	   	float mat[4] = {1.0f, 1.0f, 1.0f, 0.2f};	float spec[4] = {1.0f, 1.0f, 1.0f, 1.0f};	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, mat);	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, spec);	glMaterialf (GL_FRONT_AND_BACK, GL_SHININESS, 96.0f);	glLightModelf(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);		glEnable(GL_LINE_SMOOTH);	glEnable(GL_BLEND);	glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);		glActiveTextureARB(GL_TEXTURE0_ARB);	glMatrixMode(GL_TEXTURE);	  glLoadIdentity();	  glTranslatef(0.2f * sin(time), 0.2f * cos(time), 0.0f);	glMatrixMode(GL_MODELVIEW);        /*I need to draw the surface two times because else the wave behind another wave would be blended, and that would result into a bad effect, looking like having no depth test        */        for(int m = 0; m < 3; m++)	   	 {	  for(int i = 0; i < OCEAN_GRID_WIDTH-1; i+=8)		for(int j = 0; j < OCEAN_GRID_HEIGHT-1; j+=8)		 {		  if(! vf->sphereIsInside( point4f((float)((float)OCEAN_GRID_WIDTH*-0.5f + i + 4.0f), 0.0f, (float)((float)OCEAN_GRID_HEIGHT*-0.5f + j + 4.0f)), 10.0f) )			continue;		  point4f campos = env->getRootnodePointer()->getCameraPointer()->position;				  point4f actpos( ((float)OCEAN_GRID_WIDTH*-0.5f + i + 4.0f)*4.0f, 0.0f, (OCEAN_GRID_HEIGHT*-0.5f + j + 4.0f)*4.0f);		  vector4f vec = campos.vectorTo(actpos);		  if( vec.length() - 5.0f*4.0f > env -> getFogDistance())			continue;		  		  for(int k = 0; k < 8; k++)		   {			glBegin(GL_TRIANGLE_STRIP);			for(int l = 0; l < 9; l++)			 {			  glMultiTexCoord2fARB( GL_TEXTURE0_ARB, (float)((float)OCEAN_GRID_WIDTH*-0.5f + i + k), (float)((float)OCEAN_GRID_HEIGHT*-0.5f + j + l));			  glNormal3fv( &normalMap[((i+k)*OCEAN_GRID_WIDTH + j+l)*3] );			  glVertex3f( (float)((float)OCEAN_GRID_WIDTH*-0.5f + i + k    ), sea[(i+k)*OCEAN_GRID_WIDTH + j+l],   (float)((float)OCEAN_GRID_HEIGHT*-0.5f + j + l) );			  glMultiTexCoord2fARB( GL_TEXTURE0_ARB, (float)((float)OCEAN_GRID_WIDTH*-0.5f + i + k + 1), (float)((float)OCEAN_GRID_HEIGHT*-0.5f + j + l));			  glNormal3fv( &normalMap[((i+k+1)*OCEAN_GRID_WIDTH + j+l)*3] );			  glVertex3f( (float)((float)OCEAN_GRID_WIDTH*-0.5f + i + k + 1), sea[(i+k+1)*OCEAN_GRID_WIDTH + j+l], (float)((float)OCEAN_GRID_HEIGHT*-0.5f + j + l) );			 }			glEnd();		   }	     }	  if(m == 0)	   {		glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);		glActiveTextureARB(GL_TEXTURE0_ARB);		env->getRootnodePointer()->getTextureManagerPointer()->activateTexture(waterTexture);		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);	   }	  if(m == 1)	   {		env->getRootnodePointer()->getTextureManagerPointer()->activateTexture(waterBumpMap);		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);        glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE);        glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_DOT3_RGB_ARB);	   }   	 }  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);	   glMatrixMode(GL_TEXTURE);	glLoadIdentity();  glMatrixMode(GL_MODELVIEW);    glPopMatrix(); } 
our new version has many new and good features. sadly, the good ones are not new and the new ones are not good
note that i don''t use spline interpolation. I (*aiee*) deleted the original source by mistace some days ago and am now rewriting it...
our new version has many new and good features. sadly, the good ones are not new and the new ones are not good
Wow, that''s a lot of stuff to look at... thanks!

This topic is closed to new replies.

Advertisement