# Phong reflection on a water surface.

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

## Recommended Posts

I try to implement a reflection on a water waves so  (something similar to the reflection of the sun on the water surface)

now i get this what is below:

(top left, bottom right)

bottom left shows another shader (lighting shader - which shows normal direction) - so i assume somewhat normals are calculated properly

top right the mesh with all normals set to 0, 1, 0 (as in a mirror) and the result

now top left and bottom right is actually that top right one but with normals calculated that way showed in bottom left image

maybe the thing is because i way too much stretch the mesh (64x64 grid is stretched to 512x512) - ah red thing indicates light position

any suggestions how can i fix that>?

basically i aim for this:

NOTE i jus scaled the heightmap gemoetry when i was calculating nromals and it looks now like:

shader somewhat looks like this

float PhongReflection(vec3 DirFromVertToLight, vec3 surfnormal, vec3 PerfectlyReflectedDir, vec3 DirVertexCam)
{
return 0.5*dot(DirFromVertToLight,surfnormal) + 0.8*dot(PerfectlyReflectedDir,DirVertexCam);
}

gl_FragColor = vec4(reflection_color,1.0)*PhongReflection(dfvtl, u_normalMap, Reflect(-dfvtl, vertex_normal), dvc);


Edited by WiredCat

##### Share on other sites

shader somewhat looks like this

float PhongReflection(vec3 DirFromVertToLight, vec3 surfnormal, vec3 PerfectlyReflectedDir, vec3 DirVertexCam)
{
return 0.5*dot(DirFromVertToLight,surfnormal) + 0.8*dot(PerfectlyReflectedDir,DirVertexCam);
}

gl_FragColor = vec4(reflection_color,1.0)*PhongReflection(dfvtl, u_normalMap, Reflect(-dfvtl, vertex_normal), dvc);


I'm assuming the 0.5 and 0.8 are intensity tweaks?

One thing that comes to mind is that you're not clamping your dot products to 0-1 range. That means your specular result will be removing from your diffuse light whenever the dot product is negative. Same goes for diffuse.

Also the phong result should also be multiplied by the lambertian term for correctness, and taken to a power for glossiness.

It should look more like this (I've added your 0.5 and 0.8 to this, but I'm not sure you need or even want those):

float PhongReflection(vec3 DirFromVertToLight, vec3 surfnormal, vec3 PerfectlyReflectedDir, vec3 DirVertexCam)
{
float nDotL = clamp(dot(DirFromVertToLight,surfnormal), 0.0, 1.0);
float rDotV = clamp(dot(PerfectlyReflectedDir,DirVertexCam), 0.0, 1.0);
return 0.5*nDotL + (0.8 * nDotL * pow(rDotV, 32.0));
}


The 32 is the "glossiness". Higher = sharper highlights. Currently you're just using 1 which gives you a super spread out highlight.

Also, what is "reflection_color"? If all you want is the reflection highlight and not direct/diffuse lighting, then you don't need to add "0.5*nDotL" to that last line at all.

Edited by Styves

##### Share on other sites
Phong shading produces perfectly round highlights. You probably want to use Blinn-Phong shading, which correctly stretches highlights on rough surfaces at glancing angles (producing the characteristic streaky reflections seen on water or wet roads).

##### Share on other sites

Also the phong result should also be multiplied by the lambertian term for correctness, and taken to a power for glossiness.
It should look more like this (I've added your 0.5 and 0.8 to this, but I'm not sure you need or even want those):

float PhongReflection(vec3 DirFromVertToLight, vec3 surfnormal, vec3 PerfectlyReflectedDir, vec3 DirVertexCam)
{
float nDotL = clamp(dot(DirFromVertToLight,surfnormal), 0.0, 1.0);
float rDotV = clamp(dot(PerfectlyReflectedDir,DirVertexCam), 0.0, 1.0);
return 0.5*nDotL + (0.8 * nDotL * pow(rDotV, 32.0));
}


as long as DirFromVertToLight , surfnormal , PerfectlyReflectedDir and DirVertexCam are normalized (and they should be) the results of dot products are in the range of [-1,1]  so no clamping is needed the code should be :


float PhongReflection(vec3 DirFromVertToLight, vec3 surfnormal, vec3 PerfectlyReflectedDir, vec3 DirVertexCam)
{
float nDotL = max(dot(DirFromVertToLight,surfnormal), 0.0);
float rDotV = max(dot(PerfectlyReflectedDir,DirVertexCam), 0.0);
return 0.5*nDotL + (0.8 * nDotL * pow(rDotV, 32.0));
}


and as hodgman said you should use blinn-phong shading:

and also I guess you should give the ratios "0.5" and "0.8" as a material to the shader

Edited by IYP

##### Share on other sites

HLSL's saturate(x) or GLSL's clamp(x,0.0,1.0) is usually implemented as a free instruction modifier, whereas max(x,0.0) is an independent instruction.
e.g.
c=clamp(a+b,0,1)
will compile into
But
c=max(a+b, 0)
will compile into
max c c 0

So even though it seems more complex than is required here, it's probably actually simpler after the compiler is done with the code

1. 1
2. 2
3. 3
Rutin
15
4. 4
5. 5

• 13
• 26
• 10
• 11
• 9
• ### Forum Statistics

• Total Topics
633729
• Total Posts
3013578
×