PDA

View Full Version : GLSL Normals & Parametric Surface


toneburst
10-09-2008, 11:34 AM
I'm trying to calculate usable normals for a parametric mesh surface using the functions below in a Vertex Shader.


uniform float A, B, C, D; // 0 > 1 range

// The parametric mesh function itself
vec4 heartSphere(in vec4 point)
{
/*
Adapted from Mike Williams' equation, found at
http://www.econym.demon.co.uk/isotut/real.htm#heart1
*/

float u = point.x * PI;
float v = point.y * TWOPI;

vec4 outPos;
outPos.x = (cos(u) * sin(v)) - pow(abs(sin(u) * sin(v)), A) * B;
outPos.y = cos(v) * C;
outPos.z = sin(u) * sin(v);
outPos.w = 1.0;

return outPos;
}

// Structure to hold vertex position and normal values
struct posNorm {
vec4 pos;
vec3 norm;
};

// Calculate vertex position and normal
posNorm surface(in vec4 point)
{
// Initialise output variable
posNorm result;
// Calculate vertex position
result.pos = heartSphere(point);
// Calculate normal
float offset = 0.00001;
vec4 tangent = heartSphere(vec4(point.x, point.y + offset, point.z,1.0)) -
heartSphere(vec4(point.x, point.y - offset, point.z,1.0));
vec4 bitangent = heartSphere(vec4(point.x + offset, point.yz,1.0)) -
heartSphere(vec4(point.x - offset, point.yz,1.0));
result.norm = cross(tangent.xyz, bitangent.xyz);

// Return vertex position and normal
return result;
}


I get a heart-shaped mesh, as I should, but the normals are incorrect, being flipped across the top half of the model. Does anyone know if this method of calculating normals is usable for this kind of parametric surface (basically a modulated sphere form), and if so, what I've done wrong?

I'm multiplying the normal by gl_NormalMatrix, then normalizing it before sending it to the Fragment Shader as a vec3 varying.

Here's what it currently looks like:

http://img360.imageshack.us/img360/2941/heartsurfaceflippednormfq5.png

Any advice, anyone?

a|x
http://machinesdontcare.wordpress.com

Reedbeta
10-09-2008, 01:39 PM
Hmm, I don't see anything that would obviously lead to the effect you're seeing. Unless the parameterization somehow breaks down or swaps handedness or something at that boundary.

toneburst
10-10-2008, 03:48 AM
Hi Reedbeta,

thanks for getting back to me.
I don't understand what's going on. If I replace the heart function with a simple parametric sphere function, I get the same effect (ie the normals are flipped on one hemisphere), so it's not an issue specific to the particular parameterization.

Anyway, someone on another list suggested something, which seems to have done the trick (though I still don't understand why it happens in the first place).

I added this to flip some of the normals:

result.norm = (dot(result.norm,result.pos) < 0.0) ? result.norm : -result.norm;

and it now seems to work as expected.

See:
http://img392.imageshack.us/img392/5008/heartsurfaceflippednormbh2.png

Thanks again for getting back to me,

Regards,

a|x
http://machinesdontcare.wordpress.com