Specular highlights on water

Started by
11 comments, last by Hiyar 12 years, 5 months ago
Hi,
I am using animated normalmaps and usual specular calculation result looks not that good,
Is there a way to make specular highlights on water look better and natural?

Thanks
Advertisement

I take it you already tried doing it the "right" way, so if you're interested in other approaches...

sunshine1.png

Super Mario Sunshine's Water Effect
Super Mario Sunshine uses strongly-colored ocean floors and a waving water mesh with a special noise texture. This texture is used in combination with a shader calculation to define where the shines on this water mesh will happen. An analytical view of this texture:

sunshine2.png

Notice it is mip-mapped, which means that under distance it will look different based on which pair of stages are being interpolated. The second stage is the brightest, so areas at a medium distance will be stronger than closer or really far away ones. Also note that the texture itself is completely blank, so there's no way the water will shine near the camera; only where the mip levels are used.
Anyway, SMS uses a single instance of that texture tiled over the entire water mesh (just one texture unit), but this texture is sampled twice, with two different UV values; these UV values should be scrolled in different directions and at different speeds in your game code, so that when they sample the same texture they can be added together and give an entirely unique, composited value. The water mesh also performs a waving animation with its vertices.
The shader then compares this unique color value (you can use any of the RGB channels, since the texture is grayscale) against a constant threshold\cutoff value - if the composited value is whiter\stronger than the cutoff value, it's discarded or rendered as transparent. Optionally, you can also set a lower cutoff value as the code below exemplifies:


float4 PS(
float4 Diff : COLOR0,
float4 Spec : COLOR1,
float4 Vert : TEXCOORD0,
float2 Tex1 : TEXCOORD1,
float2 Tex2 : TEXCOORD2 ) : COLOR
{
float4 waterTex0 = tex2D(baseSampler,Tex1); // The same texture, sampled twice to simulate...
float4 waterTex1 = tex2D(baseSampler,Tex2); // ...two scrolling textures without using 2 texture units.

float water = ((waterTex0.r + waterTex1.r) * Vert.r); // Composited value from the two samples.

if((water >= cutoff_bottom && water <= cutoff_top))
discard;

return float4(water,water,water,1.0f);
}

The resulting fragment will be blended with the ocean floor, thus acquiring that water-like color while giving the impression of a shine. If it fails the cutoff values, you just get the ocean floor's color. You can see this in that screenshot at the top of the post. The water mesh doesn't cover all of the visible ocean, just an area around the player - most likely to increase the performance of this effect on the GameCube. You can shape this technique to achieve whatever result you want: adding different parameters, using a 1D texture instead of that "IF" shader instruction (might be faster) etc.

I wouldn't know all this if it weren't for the ingeniousness of Arthur Carvalho (nicked "Yoasakura") of the Dolphin-Emulator forums, so big thanks to him.

Bye.

thanks for sharing this
No problem.

Forgot to say; you can use the Photoshop NVIDIA DDS plugin to draw custom data on the mip-levels: http://www.modwiki.n...diting_MIP_Maps

Alternatively you can use the GIMP plugin: http://code.google.c...p-dds/
I am using animated normalmaps and usual specular calculation result looks not that good,
Is there a way to make specular highlights on water look better and natural?
That depends on what is not good-looking about it... Can you post a picture?


If the problem is specular aliasing, then mipmapping your normal maps with a toksvig factor, or using LEAN mapping, will help.
I am just trying to create sparkles, little specular highlights on water surface, what I am having looks more like a flat disc with little distortion.
I am using fresnel term to blend refraction and reflection maps, should I use this for specular heighlights too?
I second Hodgman's question - please post a picture. It'll be loads easier to tell what's wrong.
click
Hi Hiyar, I can see now what needs improvement. You said you wanted more noise, that it's looking "flat" the way it is. What you're missing right now is one major coloring factor: the lighting. All the noise you need is stored in those animated normal-maps; you just need something to compare them with.

There is a quick and easy way to implement something in this style. I'd like you to do the following:

• Define the sun's vector. This is a constant Float3 value, with a negative Y axis since it's pointing down. Prefer a vector that points in the same direction as the sun in your environment.

• Choose a deep-water color. This is a constant Float4 value. I suggest something in the lines of RGBA (0.0, 0.23, 0.31, 1.0).

• Compute the Dot product of the sun's vector with the current fragment's normal (taken from the animated normal-map), but transfer the result to the '1.0 ~ 0.0' range:

float lighting = (dot(sunVector, normalSample.rgb) + 1.0) * 0.5 // Transfer the dot result from '1.0 ~ -1.0' to the '1.0 ~ 0.0' range.

• Add a small offset to the lighting factor so the water doesn't perfectly reflect the environment - so it doesn't look like a flawless mirror:

lighting = max(lighting - 0.1, 0.0)

• Use that computed lighting factor to Lerp between 'deep-water color' and 'reflection map':

return lerp(deepWaterColor, reflectionSample, lighting)

• Consider that Lerp as your final fragment color.

This doesn't represent what goes on in reality, but it's a good substitute. If this doesn't look good I'll suggest you another method.
If you can, please post a picture of above in action so we can see if it's working.
I am not sure if I understand you correctly.
What exactly do you mean by deepwater color? I am using height based fog for underwater and I am using refraction map too.
You can not see this in the picture maybe
See this

for the lerp blending I am using fresnel term.
I think I am just going to experiment with different normal maps, should I use fresnel for this additional specular highlights too?

This topic is closed to new replies.

Advertisement