Normals for water simulation

This topic is 4779 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Hi i was just wondering what would be the best way to calculate the normals for the water reflections......best and most economical way in matter of calculations as i want my simulation to run real-time... right now i was just calculating the normal for each faces but that doesn't give a really smooth surface... any ideas??

Share on other sites
well while im at it...
i also have trouble getting my projection to work with shaders
now i've been able to have it work without shaders by supplying the coords to my vertex, but when i try with my shaders it just won't happen...im pretty sure my shaders are alright but.....then again it still doesn't work :(

// FRAGMENT SHADERuniform sampler2D myTexture;void main (void){  gl_FragColor  = texture2DProj(myTexture, gl_TexCoord[0]);         }// VERTEX SHADERuniform mat4 Mprojtex;void main(void){ gl_Position = ftransform(); gl_TexCoord[0] = Mprojtex * ftransform();}// Here is my main program where i start the shader and send it the projection matrix i calculated:float Mr[16] = { 	0.5, 0, 0, 0,	0, 0.5, 0, 0,	0, 0, 0.5, 0,	0.5, 0.5, 0.5, 1 };	float Mprojtex[16], Model[16], MProj[16];	glGetFloatv(GL_MODELVIEW_MATRIX, Model);	glGetFloatv(GL_PROJECTION_MATRIX, MProj);	glMatrixMode(GL_PROJECTION);	glPushMatrix();        glLoadMatrixf(Mr);        glMultMatrixf(MProj);	glMultMatrixf(Model);	glGetFloatv(GL_PROJECTION_MATRIX, Mprojtex);	glPopMatrix();	glMatrixMode(GL_TEXTURE);	glLoadMatrixf(Mprojtex);	glMatrixMode(GL_MODELVIEW);	glUseProgramObjectARB(ShaderObject);	GLint texLoc   = glGetUniformLocationARB(ShaderObject, "myTexture");	glUniform1iARB(texLoc, 0);	GLint MprojLoc = glGetUniformLocationARB(ShaderObject, "Mprojtex");	glUniformMatrix4fvARB(MprojLoc,16,0,Mprojtex);	glBindTexture(GL_TEXTURE_2D, render_texture);	glEnable(GL_TEXTURE_2D);	int t=0;	for(int x=0; x<m-2; x++)	{		glBegin(GL_TRIANGLE_STRIP);		{			for(int y=0; y<n-1; y++)		{			vert[t%3].x = x;			vert[t%3].y = y;			vert[t%3].z = Height[x+y*(m-1)];			t++;			norm =	getnormal(vert[1], vert[0], vert[2]);			glNormal3f(norm.x, norm.y, 1); 		//	glTexCoord3f(x, y, Height[x+y*(m-1)]);			glVertex3f(x, y, Height[x+y*(m-1)]);						vert[t%3].x = x+1;			vert[t%3].y = y;			vert[t%3].z = Height[x+1+y*(m-1)];			t++;						norm =	getnormal(vert[1], vert[0], vert[2]);			glNormal3f(norm.x, norm.y, 1); 					//	glTexCoord3f(x+1, y, Height[x+1+y*(m-1)]);			glVertex3f(x+1, y, Height[x+1+y*(m-1)]);			}				glEnd();				}		t=0;	}	glUseProgramObjectARB(0);  	glDisable(GL_TEXTURE_2D);

PLEASE let me know if you see anything wrong as i've pretty much tried anything i could think of :/
also ignore the glNormal3f as like my first question i am not sure yet how im gonna calculate them..
tks

Oh and, like i said before im pretty sure i calculate the MProjtex matrix right cause if i try it without the shaders, it works fine...

Share on other sites
For calculating normals, you might find this thread useful.

Share on other sites
tks a lot!!
the technique used there seems to be a good compromise of speed and accuracy

now i just need to find out how to make my shaders work properly...

Share on other sites
your vertex program is wrong [smile]

- No need to supply a uniform to it, just use the texture matrix you already setup
- ftransform() performs the calculation gl_ModelViewMatrix * gl_Vertex, so the 2nd time you use it is wrong as you are multiplying the product of that by the matrix used to setup the projective lookup, so god knows where you end up [grin]

The shader is very simple (without lighting or any other effects, just working out the projection)
void main(void){ gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_Vertex;}

Also, I wouldnt do the texture matrix setup in the projection matrix, it just confuses things.

Instead change it so that the code is
float Mprojtex[16], Model[16], MProj[16];glGetFloatv(GL_MODELVIEW_MATRIX, Model);glGetFloatv(GL_PROJECTION_MATRIX, MProj);glMatrixMode(GL_TEXTURE);glLoadMatrixf(Mr);glMultMatrixf(MProj);glMultMatrixf(Model);glMatrixMode(GL_MODELVIEW);

so it makes it clear what you are doing to the matrix and that code is alot more compact compared to what you were doing [smile]

Share on other sites
OK
i have to say im kinda angry at you
cause it WORKED THE FIRST TIME i tried your code!!!
gggrrrr..........i spent so much time on this...actually im pretty sure at one point i also tried something like

void main(void)
{
gl_Position = ftransform();
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_Vertex;
}

except instead of gl_TextureMatrix[0] i had the matrix Mprojtex which i had sent through a uniform variable....
anyway...it works now so i guess i won't mess with it!

one thing tho, it projects the reflection alright but i don't see my water plane anymore? it became white or something, could that be because i don't take into account the lighting in my shaders or something? cause when i was doing it without shaders i could still see my water plane...
if not its probably something else in my code i guess

Share on other sites
Quote:
 Original post by tasseloffOKi have to say im kinda angry at youcause it WORKED THE FIRST TIME i tried your code!!!gggrrrr..........i spent so much time on this...

thats coz its basically what my code is, so i knew it would work [grin]

Quote:
 one thing tho, it projects the reflection alright but i don't see my water plane anymore? it became white or something, could that be because i don't take into account the lighting in my shaders or something? cause when i was doing it without shaders i could still see my water plane...if not its probably something else in my code i guess

post a screen shot (before and after is possible) so I can see whats going on, its hard to guess from that description.

Share on other sites
yup ok ill post a screenshot...
first tho, like i said before, i HAD tried with something similar and i tried again just to see and it DOESN'T work....id really like to know why tho...here it is:

uniform mat4 Mprojtex;void main(void){ gl_Position = ftransform();// just changed gl_TextureMatrix[0] to MProjtex as you can see...// gl_TexCoord[0] = gl_TextureMatrix[0] * gl_Vertex; gl_TexCoord[0] = Mprojtex* gl_Vertex;}instead ofvoid main(void){ gl_Position = ftransform(); gl_TexCoord[0] = gl_TextureMatrix[0] * gl_Vertex;}

if Mprojtex contains the same as the texture it should work no??
maybe im just not sending the variable right i dunno, i just don't get it.....as you can i just added a glGetFLoatfv to your code to get the content of the texture matrix and then send it to the shader:
float Mprojtex[16], Model[16], MProj[16];glGetFloatv(GL_MODELVIEW_MATRIX, Model);glGetFloatv(GL_PROJECTION_MATRIX, MProj);glMatrixMode(GL_TEXTURE);glLoadMatrixf(Mr);glMultMatrixf(MProj);glMultMatrixf(Model);glGetFloatv(GL_TEXTURE_MATRIX, Mprojtex);glMatrixMode(GL_MODELVIEW);	glUseProgramObjectARB(ShaderObject);	GLint texLoc   = glGetUniformLocationARB(ShaderObject, "myTexture");	glUniform1iARB(texLoc, 0);	GLint MprojLoc = glGetUniformLocationARB(ShaderObject, "Mprojtex");	glUniformMatrix4fvARB(MprojLoc,16,0,Mprojtex);

i really don't see what could be wrong, but it has to do with how i send the matrix i guess!! since it doesn'T seem to be sent right or else it would work...:/

as for the screenshot here is before the projection:
BEFORE
http://pallots.kicks-ass.net/planarreflect/ref_before.jpg
AFTER
http://pallots.kicks-ass.net/planarreflect/ref_after.jpg

and this is how it should look...and how it looks when i do the projection without the shaders:

not sure how come my water plane disappears...
(also, how in hell do you post a picture on here?? had to put them on my server...)
sorry for the long post, tks in advance

nm

Share on other sites
i'm guesing the lack of plane is due to you not working out the lighting as happens down the fixed function pipeline.

As to why your other shader doesnt work, I dont know, your right in that it should work and there is probably a good reason why it doesnt however atm i cant see it

Share on other sites
k....
so i guess ill try to look into the lighting stuff, but im not 100% sure its that tho because if there was no lighting then my plane should be black as thats the original color i gave it...

Share on other sites
ah, my brain has just worken up [grin]

You draw the reflection with a white background, yes?
Thus, when you project the texture you are projecting a white texture onto the plane which will vanish into the background.

Just to give you a hint on the shaders, the ones i'm using are
// vertex programvarying vec4 projCoord;void main(){  vec3 lightVect, trueNormal;  vec4 realPos = gl_ModelViewMatrix * gl_Vertex;    lightVect = normalize(gl_LightSource[0].position.xyz - realPos.xyz);  trueNormal = gl_NormalMatrix * gl_Normal;    projCoord = gl_TextureMatrix[0] * gl_Vertex;  gl_FrontColor = vec4(dot(lightVect, trueNormal) - 0.1);    gl_Position = ftransform();}// fragment programuniform sampler2D reflectTex;varying vec4 projCoord;const vec4 ambient = vec4(0.13), boost = vec4(1.06);void main(){  vec4 reflectionValue = texture2DProj(reflectTex, projCoord);  gl_FragColor = boost * gl_Color * reflectionValue + ambient;}

(projCoord is the same as using the multi-texture coord thing you use)

It could be adjusted to use glLighting later, but as a proof of concept it works well [smile]

Share on other sites
ahh yeah....so i guess i have to set some sort of blending on my projection....
well, i've got some work ahead :)
tks a LOT for your help...
also to calculate the normals i've used the technique on the site given by gamelife
N = Vector3D(z[x-1][y] - z[x+1][y], z[x][y-1] - z[x][y+1], 2);
N.Normalize();

so far it seems to work ok, so now i guess i just have to work a bit more on my shaders and implement a few things concerning lighting and colors.
ill keep ya posted :)
tks again

Share on other sites
ok....i calculated the normals and everything but....shouldn't the surface be all smooth now when i disburb it??

http://pallots.kicks-ass.net/planarreflect/disturb.jpg
and you can see better here without any reflections:
http://pallots.kicks-ass.net/planarreflect/disturb2.jpg
there you can see a bit what it looks like... whatever disturbance i do i still see all the square facets and afaik with a normal for every vertex i shouldn't....

also im wondering if anyone had or could tell me where i could get just a small surrounding (like a terrain) on which i could put my water to really see if the reflections are right...

Share on other sites
hi, i know this is my old thread but, didn't want to start a new one for nothing.....
right now, im using the calculation given on the link above to calculate normals.....basically its

normalize(height[x-1,y] - height[x+1,y], height[x,y-1] - height[x,y+1], 2)

however...id like to know where that comes from.....it seems to be a common way to calculate normals on a heightfield but im just wondering what's the math behind all that...

Share on other sites
the math term for that equation is finite difference. It's a way to compute the derivative of a discrete data field. Geometrically speaking, it approximates the 2D tangential plane over each texel. The surface normal of that plane is the normal of the height field texel.

Share on other sites
ahh, tks a lot Yann :)