Jump to content
  • Advertisement
Sign in to follow this  

vertex shader normal generation

This topic is 3320 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. im using a vertex shader to generate different shapes (in this case a sphere) and trying to compute the normals aswell. what im doing is passing a grid mesh of size 100x100 (the plane coordinates are from 0.0 to 1.0) and in the shader i use the vertices to generate a sphere by this function:
float3 getSpherePoint( float u, float v )
{
	float x = cos(v) * sin(u);
	float y = sin(v) * sin(u);
	float z = cos(u);
	return float3( x, y, z );
}
the vertex shader follows:
vertexOutput VS_GoochySpecular( in vertexInput IN )
{
    vertexOutput OUT = (vertexOutput)0;

	float step = (1/100.0); // one step

        float u = (IN.position.x) * TWOPI;
        float v = (IN.position.y) * PI;

	float3 pos = getSpherePoint( u, v );

	// Compute tangents and normals
	float3 tangent = getSpherePoint( u-(step/2), v ) - getSpherePoint( u+(step/2), v );
	float3 bitangent = getSpherePoint( u, v-(step/2) ) - getSpherePoint( u, v+(step/2) );
	
	float3 normal = normalize( cross( tangent, bitangent ) );

	// scale sphere
	pos *= a;
	
    float4 Po = float4( pos, 1 );
    OUT.position = mul( worldViewProj, Po ); 
    float3 worldpos = mul(matWorld, Po).xyz;	// in "world" coordinates
    float3 viewpos = mul(matView, float4(worldpos,1.0)).xyz;	// in "view" coordinates
    OUT.worldPos = worldpos;

    OUT.normal = normalize( mul((float3x3)matViewIT, normal) );
    float3 L = viewL - (viewpos.xyz*lightPos.w);
    OUT.lightVec = L;

    OUT.viewVec = normalize( float3(matViewIT[0].w, matViewIT[1].w, matViewIT[2].w) - viewpos.xyz);


    return OUT;
}
the problem is that the bottom hemisphere of the sphere has the lighting inverted. i have disabled face culling. when enabled i can see the normals are inverted. my question is why everything below y=0 inverts ? check this shot: Free Image Hosting at www.ImageShack.us best regards,

Share this post


Link to post
Share on other sites
Advertisement
Your getSpherePoint assumes u between 0 and PI and v between 0 and 2*PI.
Also, you don't have to compute a tangent vector and a bitangent vector to compute the normal of a sphere. The normal is simply getSpherePoint.

Share this post


Link to post
Share on other sites
thank you. i was so blind i didnt even see that.

as for the normals thing, im trying to find a way to compute vertex normals for distorted objects that can be generated at the vertex shader.

im not sure if this method will work. im hoping it does. would you know anything about that ?

Share this post


Link to post
Share on other sites
The method will work, but there's a better way to do it if you can.
Instead of sampling your function 5 times (once for position, 2 for the tangent and 2 for the bitangent), you can compute the normal by
n = cross(df/du, df/dv) (up to normalization),
where df/du and df/dv are the partial derivatives of your function (e.g. getSpherePoint) by u and v, resp.
In your example,
df/du = ( cos(v)*cos(u), sin(v)*cos(u), -sin(u) )
df/dv = ( -sin(v)*sin(u), cos(v)*sin(u), 0 ),
so that
n = ( sin(u)*sin(u)*cos(v), sin(u)*sin(u)*sin(v), (cos(v)*cos(v) + sin(v)*sin(v))*cos(u)*sin(u) )
n = sin(u) * (cos(v) * sin(u), sin(u)*sin(v), cos(u))
n = sin(u) * getSpherePoint(u,v)
This even works for stuff like Perlin noise (which comes in very handy).

- Lutz

Share this post


Link to post
Share on other sites
hi lutz, i dont get that much on that derivative stuff.
are you telling me that

normal = sin(u) * getSpherePoint( u, v );

would give me correct normals for sphere mesh generated, and for perlin noise aswell ?

it looks too simple too me =)

Share this post


Link to post
Share on other sites
No, that was just an example to illustrate how it works. I used this example to verify what we already knew - that the normal direction for a sphere matches the direction to the point on the sphere. This way we could check that the calculations are correct.

In general, the normal direction is different from the direction to the point on the surface. For other objects like ellipsoids or Perlin noise you'll get other results. But the general way to compute the normal is the same. Let's say you write Perlin noise as function pos = f(u,v). Then the normal is given by normalize(cross(dfdu(u,v), dudv(u,v))), where you'll have to compute the partial derivatives dfdu and dfdv yourself.

Share this post


Link to post
Share on other sites
ok so it all depends on the formula. for example i am using a distorted version of a sphere formula here now:

float3 getSpherePoint( float u, float v )
{
// 0 <= u <= PI, 0 <= v <= TWOPI

float x = cos(v) * sin(u) + sin(20*u+count.x) * 0.075;
float y = sin(v) * sin(u) + cos(10*u+count.x) * 0.075;
float z = cos(u);

//r += sin(0.25*x * count.x + time + phase.x) * amount.x;
//r += cos(u*count.y + phase.y) * amount.y;

// multiply by radius
return float3( x*r, y*r, z*r );
}

i did not understand anything on the way you calculate the dfdu/dfdv. i would like to know if is there a general way to compute it for different functions, no matter what they are, ellipse, sphere, cone, perlin, etc

if its not, how would i compute it myself as you said? what would u recommend i should read/do to get myself working this out.

thanks

Share this post


Link to post
Share on other sites
Computing derivatives is done by applying some simple rules to general functions. I can't explain that in this post, it's nothing you can learn in one hour. If you really want to, I recommend you grab a book about calculus and learn how to do it.

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.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!