• Create Account

Need scary sound effects or creepy audio loops for your next horror-themed game? Check out Highscore Vol.3 - The Horror Edition in our marketplace. 50 sounds and 10 loops for only \$9.99!

# Using partial derivatives to light circular waves

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

18 replies to this topic

### #1Hseptic  Members   -  Reputation: 146

Like
0Likes
Like

Posted 02 June 2012 - 07:50 PM

I'm doing an exercise in a book that asks to add ambient, diffuse and specular lighting to an existing demo that animates circular waves over a basic flat grid. My attempt as it stands doesn't seem to work as expected though. Instead of looking circular in tune with the waves themselves, my lighting has a strange moire like pattern to it. I've forgotten most of my calculus, but fortunately the book's exercise spoon feeds me the formula for computing the partial derivatives neccessary for calcuating the vertex normals. The way I understand it, once I compute the partial derivatives, I simply plug them into the tangent vectors u and v and take the cross product to get my vertex normal.

// CHAPTER 10 10.12 EXERCISE 6

uniform extern float4x4 gWorld;
uniform extern float4x4 gWorldInverseTranspose;
uniform extern float4x4 gWVP;
uniform extern float gTime;
uniform extern float4 gAmbientMtrl;
uniform extern float4 gAmbientLight;
uniform extern float4 gDiffuseMtrl;
uniform extern float4 gDiffuseLight;
uniform extern float4 gSpecularMtrl;
uniform extern float4 gSpecularLight;
uniform extern float  gSpecularPower;
uniform extern float3 gLightVecW;
uniform extern float3 gEyePosW;
struct OutputVS
{
float4 posH  : POSITION0;
float3 normalW : TEXCOORD0;
float3 posW  : TEXCOORD1;
};
// Amplitudes
static float a[3] = {0.8f, 0.2f, 0.1};

// Angular wave numbers.
static float k[3] = {1.0, 8.0f, 10.0f};

// Angular frequency.
static float w[3] = {1.0f, 8.0f, 0.6f};

// Phase shifts.
static float p[3] = {0.0f, 1.0f, 2.0f};
{
// Distance of vertex from source of waves (which we set
// as the origin of the local space).
float d = sqrt(x*x + z*z);

// Sum the waves.
float sum = 0.0f;
for(int i = 0; i < 2; ++i)
sum += a[i]*sin(k[i]*d - gTime*w[i] + p[i]);

return sum;
}
void Partials(float x, float z, out float dhOverdx, out float dhOverdz)
{
float d = sqrt(x*x + z*z);
dhOverdx = 0.0f;
dhOverdz = 0.0f;
for(int i = 0; i < 3; ++i)
{
dhOverdx += (a[i]*k[i]*x*cos(k[i]*d - gTime*w[i] + p[i]))/d;
dhOverdz += (a[i]*k[i]*z*cos(k[i]*d - gTime*w[i] + p[i]))/d;
}
}
OutputVS ColorVS(float3 posL : POSITION0, float3 normalL : NORMAL0)
{
// Zero out our output.
OutputVS outVS = (OutputVS)0;

// Get the height of the vertex--the height is given by
// summing sine waves.

// calc normal
float derivx;
float derivz;
Partials(posL.x, posL.z, derivx, derivz);

float3 v = float3 (1, derivx, 0);
float3 u = float3 (0, derivz, 1);
normalL = cross(u, v);
// Transform normal to world space.
outVS.normalW = mul(float4(normalL, 0.0f), gWorldInverseTranspose).xyz;
outVS.normalW = normalize(outVS.normalW);
// Transform vertex position to world space.
outVS.posW  = mul(float4(posL, 1.0f), gWorld).xyz;
// Transform to homogeneous clip space.
outVS.posH = mul(float4(posL, 1.0f), gWVP);

// Done--return the output.
return outVS;
}
float4 ColorPS(float3 normalW : TEXCOORD0, float3 posW : TEXCOORD1) : COLOR
{
normalW = normalize(normalW);
// Compute the vector from the vertex to the eye position.
float3 toEye = normalize(gEyePosW - posW);

// Compute the reflection vector.
float3 r = reflect(-gLightVecW, normalW);
// Determine how much (if any) specular light makes it into the eye.
float t  = pow(max(dot(r, toEye), 0.0f), gSpecularPower);
// Determine the diffuse light intensity that strikes the vertex.
float s = max(dot(gLightVecW, normalW), 0.0f);

// Compute the ambient, diffuse and specular terms separatly.
float3 spec = t*(gSpecularMtrl*gSpecularLight).rgb;
float3 diffuse = s*(gDiffuseMtrl*gDiffuseLight).rgb;
float3 ambient = gAmbientMtrl*gAmbientLight;
return float4(ambient + diffuse + spec, gDiffuseMtrl.a);
}
technique LightedWaveTech
{
pass P0
{
// Specify the vertex and pixel shader associated with this pass.
}
}


What am I doing wrong?

### #2Hseptic  Members   -  Reputation: 146

Like
0Likes
Like

Posted 05 June 2012 - 02:28 PM

Please note, this is not homework. I'm simply studying this on my own for fun. So, can anyone help me?

### #3taby  Members   -  Reputation: 285

Like
0Likes
Like

Posted 05 June 2012 - 02:44 PM

If you can post the entire code in a ZIP file and let me know which SDK I need to compile it, I'd be happy to try.

### #4apatriarca  Crossbones+   -  Reputation: 1283

Like
0Likes
Like

Posted 06 June 2012 - 04:46 AM

Hi, your normal calculation seem correct to me, maybe you are doing something wrong in the pixel shader when calculating the lighting? Can you post some code or executable we can try? What you exactly mean by "a strange moire like pattern". Can you show an image of the result?

### #5Hseptic  Members   -  Reputation: 146

Like
0Likes
Like

Posted 06 June 2012 - 01:04 PM

Here's my project and a screenshot attached. I'm using June 2010 DirectX SDK 9.29.1962

### #6taby  Members   -  Reputation: 285

Like
0Likes
Like

Posted 06 June 2012 - 02:43 PM

I see that it's almost right, but it's like one or two axes are being mixed up in the calculation somewhere.

I'm downloading the SDK right now and will play around tonight, if no one else fixes it first.

### #7taby  Members   -  Reputation: 285

Like
0Likes
Like

Posted 06 June 2012 - 04:45 PM

Is there any chance that you exclude any PCB files in the ZIP file? Apologies. Not sure why the download is failing.

### #8Bacterius  Crossbones+   -  Reputation: 5579

Like
0Likes
Like

Posted 06 June 2012 - 05:51 PM

Confirmed, download loops at 9.8MB for me, seems to be broken. Did you upload it fully before posting? Don't know why this happens...

"The best comment is a deleted comment."

### #9Hseptic  Members   -  Reputation: 146

Like
0Likes
Like

Posted 06 June 2012 - 07:01 PM

I couldn't find any files with extension pcb, though I removed a file that was taking way too much space. I'm re-uploading it here.

Edited by Hseptic, 06 June 2012 - 07:08 PM.

### #10Hseptic  Members   -  Reputation: 146

Like
0Likes
Like

Posted 06 June 2012 - 07:08 PM

Whoops! I only have 5.17MB of space left to upload. Therefore, I cannot post the sdf file that I removed. Why am I only allowed a certain amount of upload space? I'm sorry.

### #11taby  Members   -  Reputation: 285

Like
0Likes
Like

Posted 06 June 2012 - 08:28 PM

You could always create a Google Code account, create a new project, then put the ZIP file in your Downloads. Lots of space.

### #12apatriarca  Crossbones+   -  Reputation: 1283

Like
0Likes
Like

Posted 07 June 2012 - 08:15 AM

I succeeded in downloading your program, but I'm unable to run (I suggest to link with the static libraries or distribute the required dlls..) and compile it since I do not have Visual Studio on this PC. I will try on the other computer later. Can you modify your shader to show the normals as color and post an image? It may help understanding if the error is in the normal generation or somewhere else.

### #13Hseptic  Members   -  Reputation: 146

Like
0Likes
Like

Posted 07 June 2012 - 10:20 AM

How do I link the libraries or distribute the dlls, and get them to you? Also, how to I make the normals visible and colorize them?

### #14apatriarca  Crossbones+   -  Reputation: 1283

Like
0Likes
Like

Posted 07 June 2012 - 10:46 AM

You can change the project settings to use static libraries instead of dynamic ones (dlls). To show the normals as color you can simply return the normal in the pixel shader, i.e.
return float4(normalW, 1.0);


### #15apatriarca  Crossbones+   -  Reputation: 1283

Like
0Likes
Like

Posted 07 June 2012 - 01:18 PM

I have successfully tried your program in another computer. The strange effect is clearly given by the normals. The strange pattern is indeed also visible when showing the normals instead of the result of the light calculation. If we limit the calculation to a single sine wave*, the normals and lighting seem correct. The math formulation is also correct. Thus, I think the strange effect is actually correct in general and the pattern is probably motivated by the interaction of the different waves at different amplitudes, angular velocities and phases.

When you calculate the y-component of the position you are using only two waves instead of three as in the derivative.

* I suggest to see the second and third waves in isolation. These waves clearly follows the pattern you are seeing. The number of vertices is probably too low to show the correct result. You can try to use more polygons or implement some form of displacement mapping.

Edited by apatriarca, 07 June 2012 - 01:26 PM.

### #16Xashmi  Members   -  Reputation: 115

Like
0Likes
Like

Posted 07 June 2012 - 01:33 PM

An artifact from using higher wave numbers than can be represented by the mesh perhaps?

### #17taby  Members   -  Reputation: 285

Like
0Likes
Like

Posted 07 June 2012 - 02:43 PM

Is the flaw basically isotropic? No.

### #18apatriarca  Crossbones+   -  Reputation: 1283

Like
0Likes
Like

Posted 07 June 2012 - 03:19 PM

You are right, it isn't isotropic but the vertices aren't arranged in a circular fashion and the light "agree" with the geometry (look at the border of the mesh for example). I think that may motivate the non-isotropic behaviour.

### #19taby  Members   -  Reputation: 285

Like
1Likes
Like

Posted 07 June 2012 - 09:43 PM

I realize this. I'm merely using the basic sample that comes with the D3D SDK to compare. It still looks like crap, but at least it's isotropic crap.

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

PARTNERS