Jump to content
  • Advertisement
Sign in to follow this  
niazware

Ocean effect

This topic is 4501 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

hi friends I'm going to implement an ocean effect (from nvidia site) which seems somehow intricated, it's as follows:
float4x4 worldMatrix : World < string UIWidget = "none";>;	        // World or Model matrix
float4x4 wvpMatrix : WorldViewProjection < string UIWidget = "none";>;	// Model*View*Projection
float4x4 worldViewMatrix : WorldView < string UIWidget = "none";>;
float4x4 viewInverseMatrix : ViewIT < string UIWidget = "none";>;

float time : Time < string UIWidget = "none"; >;
float ptime < string UIWidget = "none"; >;

texture normalMap : Normal
<
	string Name = "waves2.dds";
	string TextureType = "2D";
>;

texture cubeMap : Environment
<
	string Name = "CloudyHillsCubemap2.dds";
	string TextureType = "Cube";
>;

sampler2D normalMapSampler = sampler_state
{
	Texture = <normalMap>;
#if 1
	// this is a trick from Halo - use point sampling for sparkles
	MagFilter = Linear;	
	MinFilter = Point;
	MipFilter = None;
#else
	MagFilter = Linear;	
	MinFilter = Linear;
	MipFilter = Linear;
#endif
    AddressU = Wrap;
    AddressV = Wrap;
};

samplerCUBE envMapSampler = sampler_state
{
	Texture = <cubeMap>;
	MinFilter = Linear;
	MagFilter = Linear;
	MipFilter = Linear;
        AddressU = Wrap;
        AddressV = Wrap;
};

float bumpHeight
<
	string UIWidget = "slider";
	float UIMin = 0.0; float UIMax = 2.0; float UIStep = 0.01;
	string UIName = "Bump Height";
> = 0.5;

float2 textureScale
<
    string UIName = "Texture scale";
> = { 8.0, 4.0 };

float2 bumpSpeed
<
    string UIName = "Bumpmap translation speed";
> = { -0.01, 0.0 };

float fresnelBias
<
    string UIName = "Fresnel bias";
	string UIWidget = "slider";
	float UIMin = 0.0; float UIMax = 1.0; float UIStep = 0.01;
> = 0.1;

float fresnelPower
<
    string UIName = "Fresnel exponent";
	string UIWidget = "slider";
	float UIMin = 1.0; float UIMax = 10.0; float UIStep = 0.01;
> = 4.0;

float hdrMultiplier
<
    string UIName = "HDR multiplier";
	string UIWidget = "slider";
	float UIMin = 0.0; float UIMax = 100.0; float UIStep = 0.01;
> = 4.0;

float4 deepColor : Diffuse
<
    string UIName = "Deep water color";
> = {0.0f, 0.1f, 0.2f, 1.0f};

float4 shallowColor : Diffuse
<
    string UIName = "Shallow water color";
> = {0.0f, 0.6f, 0.7f, 1.0f};

float4 reflectionColor : Specular
<
    string UIName = "Reflection color";
> = {0.9f, 1.0f, 0.45f, 1.0f};

// these are redundant, but makes the ui easier:
float reflectionAmount
<
    string UIName = "Reflection amount";
	string UIWidget = "slider";    
	float UIMin = 0.0; float UIMax = 2.0; float UIStep = 0.01;    
> = 0.2f;

float waterAmount
<
    string UIName = "Water color amount";
	string UIWidget = "slider";    
	float UIMin = 0.0; float UIMax = 2.0; float UIStep = 0.01;    
> = 0.6f;

float waveAmp
<
    string UIName = "Wave amplitude";
	string UIWidget = "slider";
	float UIMin = 0.0; float UIMax = 10.0; float UIStep = 0.1;
> = 0.2;

float waveFreq
<
    string UIName = "Wave frequency";
	string UIWidget = "slider";
	float UIMin = 0.0; float UIMax = 1.0; float UIStep = 0.001;
> = 1.;



struct a2v {
	float4 Position : POSITION;   // in object space
	float2 TexCoord : TEXCOORD0;
	float3 Tangent  : TEXCOORD1;
	float3 Binormal : TEXCOORD2;
	float3 Normal   : NORMAL;
};

struct v2f {
	float4 Position  : POSITION;  // in clip space
	float2 TexCoord  : TEXCOORD0;
	float3 TexCoord1 : TEXCOORD1; // first row of the 3x3 transform from tangent to cube space
	float3 TexCoord2 : TEXCOORD2; // second row of the 3x3 transform from tangent to cube space
	float3 TexCoord3 : TEXCOORD3; // third row of the 3x3 transform from tangent to cube space

	float2 bumpCoord0 : TEXCOORD4;
	float2 bumpCoord1 : TEXCOORD5;
	float2 bumpCoord2 : TEXCOORD6;
	
	float3 eyeVector  : TEXCOORD7;
};

// wave functions

struct Wave {
  float freq;  // 2*PI / wavelength
  float amp;   // amplitude
  float phase; // speed * 2*PI / wavelength
  float2 dir;
};

#define NWAVES 2
Wave wave[NWAVES] = {
	{ 1.0, 1.0, 0.5, float2(-1, 0) },
	{ 2.0, 0.5, 1.3, float2(-0.7, 0.7) }	
};

float evaluateWave(Wave w, float2 pos, float t)
{
  return w.amp * sin( dot(w.dir, pos) * w.freq + t  * w.phase );
}

// derivative of wave function
float evaluateWaveDeriv(Wave w, float2 pos, float t)
{
//  return w.amp * 1.0 ; //sin( /*dot(w.dir, pos) * w.freq +*/ t /* * w.phase */);
  return w.freq * w.amp * cos( dot(w.dir, pos)*w.freq + t * w.phase );
}

// sharp wave functions
float evaluateWaveSharp(Wave w, float2 pos, float t, float k)
{
  return w.amp * pow(sin( dot(w.dir, pos)*w.freq + t*w.phase)* 0.5 + 0.5 , k);
}

float evaluateWaveDerivSharp(Wave w, float2 pos, float t, float k)
{
  return k*w.freq*w.amp * pow(sin( dot(w.dir, pos)*w.freq + t*w.phase)* 0.5 + 0.5 , k - 1) * cos( dot(w.dir, pos)*w.freq + t*w.phase);
}

v2f BumpReflectWaveVS(a2v IN,
					  uniform float4x4 WorldViewProj,
					  uniform float4x4 World,
					  uniform float4x4 ViewIT,
					  uniform float BumpScale,
					  uniform float2 textureScale,
					  uniform float2 bumpSpeed,
					  uniform float time,
					  uniform float waveFreq,
					  uniform float waveAmp
                	  )
{
	v2f OUT;
// time = ptime;
// time = time / 20;

    wave[0].freq = waveFreq;
    wave[0].amp = waveAmp;

    wave[1].freq = waveFreq*2.0;
    wave[1].amp = waveAmp*0.5;

    float4 P = IN.Position;
	// sum waves	
	P.y = 0.0;
	float ddx = 0.0, ddy = 0.0;
   for(int i=0; i<NWAVES; i++) {
    	P.y += evaluateWave(wave, P.xz, time);
//    	float deriv = evaluateWaveDerivSharp(wave, P.xz, time, 0.01);
    	float deriv = evaluateWaveDeriv(wave, P.xz, time);
    	ddx += deriv * wave.dir.x;
    	ddy += deriv * wave.dir.y;
    }

	// compute tangent basis
        float3 B = float3(1, ddx, 0);
        float3 T = float3(0, ddy, 1);
        float3 N = float3(-ddx, 1, -ddy);

	OUT.Position = mul(P, WorldViewProj);
	
	// pass texture coordinates for fetching the normal map
	OUT.TexCoord.xy = IN.TexCoord*textureScale;

	time = fmod(time, 100.0);
	OUT.bumpCoord0.xy = IN.TexCoord*textureScale + time*bumpSpeed;
	OUT.bumpCoord1.xy = IN.TexCoord*textureScale*1.0 + time*bumpSpeed*4.0;
	OUT.bumpCoord2.xy = IN.TexCoord*textureScale*2.0 + time*bumpSpeed*8.0;

	// compute the 3x3 tranform from tangent space to object space
	float3x3 objToTangentSpace;
	// first rows are the tangent and binormal scaled by the bump scale
	objToTangentSpace[0] = BumpScale * normalize(T);
	objToTangentSpace[1] = BumpScale * normalize(B);
	objToTangentSpace[2] = normalize(N);

	OUT.TexCoord1.xyz = mul(objToTangentSpace, World[0].xyz);
	OUT.TexCoord2.xyz = mul(objToTangentSpace, World[1].xyz);
	OUT.TexCoord3.xyz = mul(objToTangentSpace, World[2].xyz);

	// compute the eye vector (going from shaded point to eye) in cube space
	float4 worldPos = mul(P, World);
	OUT.eyeVector = ViewIT[3] - worldPos; // view inv. transpose contains eye position in world space in last row
	return OUT;
}


// Pixel Shaders

float4 BumpReflectPS20(v2f IN,
					   uniform sampler2D NormalMap,
					   uniform samplerCUBE EnvironmentMap) : COLOR
{
	// fetch the bump normal from the normal map
	float4 N = tex2D(NormalMap, IN.TexCoord.xy)*2.0 - 1.0;
	
	float3x3 m; // tangent to world matrix
	m[0] = IN.TexCoord1;
	m[1] = IN.TexCoord2;
	m[2] = IN.TexCoord3;
	float3 Nw = mul(m, N.xyz);
	
//	float3 E = float3(IN.TexCoord1.w, IN.TexCoord2.w, IN.TexCoord3.w);
	float3 E = IN.eyeVector;
    float3 R = reflect(-E, Nw);

	return texCUBE(EnvironmentMap, R);
}

float4 OceanPS20(v2f IN,
				 uniform sampler2D NormalMap,
				 uniform samplerCUBE EnvironmentMap,
				 uniform half4 deepColor,
				 uniform half4 shallowColor,
				 uniform half4 reflectionColor,
				 uniform half4 reflectionAmount,
				 uniform half4 waterAmount,
				 uniform half fresnelPower,
				 uniform half fresnelBias,
				 uniform half hdrMultiplier
				 ) : COLOR
{
	// sum normal maps
    half4 t0 = tex2D(NormalMap, IN.bumpCoord0.xy)*2.0-1.0;
    half4 t1 = tex2D(NormalMap, IN.bumpCoord1.xy)*2.0-1.0;
    half4 t2 = tex2D(NormalMap, IN.bumpCoord2.xy)*2.0-1.0;
    half3 N = t0.xyz + t1.xyz + t2.xyz;
//    half3 N = t1.xyz;

    half3x3 m; // tangent to world matrix
    m[0] = IN.TexCoord1;
    m[1] = IN.TexCoord2;
    m[2] = IN.TexCoord3;
    half3 Nw = mul(m, N.xyz);
    Nw = normalize(Nw);

	// reflection
    float3 E = normalize(IN.eyeVector);
    half3 R = reflect(-E, Nw);

    half4 reflection = texCUBE(EnvironmentMap, R);
    // hdr effect (multiplier in alpha channel)
    reflection.rgb *= (1.0 + reflection.a*hdrMultiplier);

	// fresnel - could use 1D tex lookup for this
    half facing = 1.0 - max(dot(E, Nw), 0);
    half fresnel = fresnelBias + (1.0-fresnelBias)*pow(facing, fresnelPower);

    half4 waterColor = lerp(deepColor, shallowColor, facing);

    float4 newcol = waterColor*waterAmount + reflection*reflectionColor*reflectionAmount*fresnel;
    newcol.a=0.9;
    return newcol;
}

technique PS20
{
	pass p0
	{
		VertexShader = compile vs_2_0 BumpReflectWaveVS(wvpMatrix, worldMatrix, viewInverseMatrix,
                                                        bumpHeight, textureScale, bumpSpeed, time,
                                                        waveFreq, waveAmp);
		
		Zenable = true;
		ZWriteEnable = true;
		CullMode = None;

//		PixelShader = compile ps_2_0 BumpReflectPS20(normalMapSampler, envMapSampler);
		PixelShader = compile ps_2_0 OceanPS20(normalMapSampler, envMapSampler,
                                               deepColor, shallowColor, reflectionColor, reflectionAmount, waterAmount,
                                               fresnelPower, fresnelBias, hdrMultiplier);
	}
}
what's UIWidget? what kind of data should I pass to this effect? can I work it with my d3d 9 app? what kind of Decleration should I use for it? how should I set textures, matrices and other values? I've seen it work great in a simple demo in DarkBASIC engine, and there wasn't any kind of parameter passed to it, does it work with default params? I've worked with effects and shader files, but this one is a bit strange, please guide me in the way of using this really nice effect. thanks in advance EDIT: Please use [source] tags for large blocks of code... [Edited by - jollyjeffers on May 31, 2006 7:39:21 AM]

Share this post


Link to post
Share on other sites
Advertisement
You might want to look up "DirectX Standard Annotations and Semantics" in the SDK documentation. The various "UI.." parts seem to be a SAS-like (but not quite) set of annotations. Presumably these are compatable with some Nvidia framework (e.g. FXComposer).

If you're not hooking this up to a GUI (e.g. your program provides all the settings, not the user) then you can probably ignore the majority of the annotations in that effect.

By the looks of things it provides defaults for all the uniform variables, so you should be able to use it as-is straight from the technique.

Try it and see! As long as you check for any/every error message and return code you should be able to isolate any problem spots. If you can't fix them then post back and ask us...

Jack

Share this post


Link to post
Share on other sites
hi

thanks jack for your answer, I've tested this effect on a plane (as my ocean) but surprisingly there's nothing rendered on the screen, I got no errors during effect creation.
how can I detect default values in the shader? what about the declaration? (POS, COORD0, COORD1, COORD2, NORM) is this correct, I should just create it and render my plane using this effect? It should be great, what may be the possible reasons for this problem (i.e. there's nothing rendered)?

thanks again

Share this post


Link to post
Share on other sites
hi again
I've another question, and it's about textures and setting them, is there any need to create and set textures in code? two textures (waves2.dds & CloudyHillsCubemap2.dds) have been called in this effect, should I create them in code? should I set them? what should I do to change the default values? effect->SetValue? what kind of values should I set.

please help me, thanks

Share this post


Link to post
Share on other sites
Quote:
Original post by niazware
hi again
I've another question, and it's about textures and setting them, is there any need to create and set textures in code? two textures (waves2.dds & CloudyHillsCubemap2.dds) have been called in this effect, should I create them in code? should I set them? what should I do to change the default values? effect->SetValue? what kind of values should I set.

please help me, thanks


Yes. You should use the SetTexture method of the effect. The texture filenames in the sahder are just for the shader tools/to show you what they should be.

I normally remove all the extra export 'junk' :).

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!