Jump to content
  • Advertisement
Sign in to follow this  
Waaayoff

Need a fast technique to render good looking water?

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

If you intended to correct an error in the post then please contact us.

Recommended Posts

A quick google search gave me at least a dozen different articles on water rendering. I was wondering if someone can recommend a certain method and save me days of research :)

I should say i'm not fussed about old hardware. Also i would like to render different kinds of water: ocean, lake, ponds. I don't know if the same method can be used to realistically model all scenarios.

Cheers

Share this post


Link to post
Share on other sites
Advertisement
Could you narrow down your requirements a bit more? What are you looking for specifically in terms of reflections? Are you looking for rivers or is that unneccessary?

What are your system requirements in more specificity? Are you looking for 3d waves, or is a flate plane good enough?

Share this post


Link to post
Share on other sites
It's difficult. The approach you want to use varies depending on the kind of water you want to render. Lake water in a clearly defined contained area (where you can fake it with a normal map) is a bit easier than sea water. I've been playing around with sea water for about a week now. Basically what I did was make a grid of triangles, put that in a buffer, pass it to a vertex shader that moves the 'y' coordinate using a sine wave function, calculate the normals, and pass it to the pixel shader where I applied a repeating texture. I abstracted most of it from this article (although I had to convert it from GLSL to HLSL):

http://www.jayconrod...ulation-in-glsl

I simplified it by having only one wave and one direction. I've put some code below that give you a starting point if you decide to do sea-water. It's still under development, I'm new to shader programming, and I do not fully understand the math....so if anyone wants to pick it apart that would be appreciated.


float4x4 World;
float4x4 View;
float4x4 Projection;
float4 ambientColor;
float ambientIntensity;
float3 lightDirection;
float4 diffuseColor;
float diffuseIntensity;
int time;
float amplitude;
float speed;
float wavelength;
float2 direction;
Texture xColoredTexture;
float4 SpecularColor;
float3 EyePosition;
float3 EyeDirection;
sampler ColoredTextureSampler = sampler_state
{
texture = <xColoredTexture>;
magfilter = LINEAR;
minfilter = LINEAR;
mipfilter = LINEAR;
AddressU = WRAP;
AddressV = WRAP;
};
struct VertexShaderInput
{
float4 Position : POSITION0;
// TODO: add input channels such as texture
// coordinates and vertex colors here.
};
struct VertexShaderOutput
{
float4 Position : POSITION0;
float2 TexCoords : TEXCOORD0;
float3 normal : TEXCOORD1;
float3 View : TEXCOORD2;
};
float dWavedx(float x, float z)
{
float pi = 3.14159;
float frequency = 2*pi/wavelength;
float phase = speed * frequency;
float2 pos;
pos[0] = x;
pos[1] = z;
float theta = dot(direction, pos);
float A = amplitude * direction[0] * frequency;
return A * cos(theta * frequency + time * phase);
}
float dWavedz(float x, float z)
{
float pi = 3.14159;
float frequency = 2*pi/wavelength;
float phase = speed * frequency;
float2 pos;
pos[0] = x;
pos[1] = z;
float theta = dot(direction, pos);
float A = amplitude * direction[1] * frequency;
return A * cos(theta * frequency + time * phase);
}
VertexShaderOutput VertexShaderFunction(VertexShaderInput input, float2 inTexCoords : TEXCOORD0)
{
VertexShaderOutput output = (VertexShaderOutput)0;
float pi = 3.14159;
float freq = 2*pi/wavelength;
float phase = speed * freq;
float2 pos;
pos[0] = input.Position.x;
pos[1] = input.Position.z;
float theta = dot(direction, pos);
input.Position.y = amplitude * sin(theta * freq + time * phase);
float4 worldPosition = mul(input.Position, World);
float4 viewPosition = mul(worldPosition, View);
output.Position = mul(viewPosition, Projection);
float3 inNormal;
inNormal.x = -dWavedx(pos[0], pos[1]);
inNormal.y = 1.0;
inNormal.z = -dWavedz(pos[0], pos[1]);
inNormal = normalize(inNormal);
output.normal = normalize(mul(inNormal, World));
output.View = normalize(float4(EyePosition,1.0) - worldPosition);
output.TexCoords = inTexCoords;
return output;
}
float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
{
float4 norm = float4(input.normal, 1.0);
float4 diffuse = saturate(dot(-lightDirection, norm));
float4 reflect = normalize(2*diffuse*norm-float4(lightDirection,1.0));
float4 specular = pow(saturate(dot(reflect,float4(EyeDirection, 1.0))),256);
float4 baseColor = tex2D(ColoredTextureSampler, input.TexCoords);
float4 finalColor = baseColor * ambientColor * ambientIntensity +
baseColor * diffuseIntensity * diffuseColor * diffuse +
baseColor * SpecularColor*specular;
finalColor.a = 0.2;
return finalColor;
}
technique Technique1
{
pass Pass1
{
// TODO: set renderstates here.
VertexShader = compile vs_2_0 VertexShaderFunction();
PixelShader = compile ps_2_0 PixelShaderFunction();
}
}


I hope that gives you a starting point. Good luck. Edited by timothyjlaird

Share this post


Link to post
Share on other sites

different kinds of water: ocean, lake, ponds
I'm afraid this is a tough call. Ocean water is typically more dynamic than others and the amount of fillrate required to render mandates the use of some other methods. Anyway, when it comes to me the ideal solution is one of the following.

  1. Water as used in Portal2 and Left for Dead. Works best for limited visibility in my opinion. Fine tuning by artist is relatively easy, proven to help for gameplay reasons. Probably good enough for you.
  2. Tiled directional flow. Apparently sufficient for ocean rendering. A step up in quality and processing power.

Share this post


Link to post
Share on other sites

Could you narrow down your requirements a bit more? What are you looking for specifically in terms of reflections? Are you looking for rivers or is that unneccessary?

What are your system requirements in more specificity? Are you looking for 3d waves, or is a flate plane good enough?


I didn't really think about reflections. Maybe yes for lakes, no for ocean? What do games usually have?

Yes, i would like rivers too.

3D waves. Should be easy to do with shaders, right?

Also, interactive water would be nice. Think ships in ocean, foam on shore.

I'm sorry if i'm not giving a lot of helping info, i really have no idea about water rendering.

Share this post


Link to post
Share on other sites
Alright then.

First thing's first, water usually has a reflection in games if it's relatively flat, almost always a planar reflection is used in these cases. Here's a good primer: http://developer.amd.com/media/gpu_assets/ShaderX_RipplingRefractiveAndReflectiveWater.pdf

3d waves can actually get quit complicated, simply because making them look decent can get hard. I'd start with the above first.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!