The w coordinate

Hey everyone,

I do not understand what other uses the w coordinate has other than scaling and providing an easy way for the programmer to represent points and vectors. I saw the NVIDIA demo to teach it, but it seems like it is just scaling the triangle around. In 2D space, the w coordinate seems to be a z coordinate. But it only seems like a scaling value in 3D space.

  • Halcyon

Since I wrote that demo, I guess I could field questions on it.

At it’s simplest, you can think of w as an easy way to scale coordinates. This does make for a convenient representation of points at infinity – just set w=0.

But what about when w is negative? Consider when you have the triangle on the screen and you negate every component of, say the red vertex. So

Before: r = (rx, ry, rz, rw)
After: r = (-rx, -ry, -rz, -rw)

(You can do this by hitting the ‘r’ key when the demo first comes up.)

If you think of w as simply a scale factor, then why is the triangle it renders different?

If you look at the 2DH view (by hitting the ‘h’ key) you will see why the triangle is different. If the -w portions of the triangle were rendered (hardware generally only renders the +w portions) you would see the triangle go off to infinity on one side of the screen and return from infinity back to the red vertex on the other side of the screen.

This is a helpful visualization of what Blinn calls the Moebius space.

There’s an interesting optimization of shadow volume rendering that you can do with these “external” triangles. A triangle is called external, if one or more of its vertices have w<0.

Anyone want to guess what the optimization for using external triangles in shadow volume rendering is?

Cass

Anyone want to guess what the optimization for using external triangles in shadow volume rendering is?

I’ll take a stab at it, but you have to promise not to pick on me too bad if I’m wrong . If you had an object that you knew was going to cast a shadow over the majority of your on-screen scene, you could flip the ‘w’ coordinate of any vertices that would normally be extruded away from the light and make an inverse shadow volume. This inverse shadow volume would cover fewer pixels than the regular volume and save you some fill. You’d have to adjust the stencil testing a bit, but otherwise it should work as usual.

Is that close?

– Zeno

Originally posted by cass:
[b]
This is a helpful visualization of what Blinn calls the Moebius space.

[/b]

My projective geometry is not as good as I’d like it to be. Does anyone have any good references (book, website, papers)? I guess a book that assumes first year calculus and linear algebra would probably be the best.

Quick search of library catologue:
Modern projective geometry / by Claude-Alain Faure and Alfred Frölicher. Kluwer Academic Publishers, 2000

Affine and projective geometry / M.K. Bennett. Published New York : Wiley & Sons, c1995.

Anyone have any comments, suggestions?

Originally posted by Zeno:
[b] I’ll take a stab at it, but you have to promise not to pick on me too bad if I’m wrong . If you had an object that you knew was going to cast a shadow over the majority of your on-screen scene, you could flip the ‘w’ coordinate of any vertices that would normally be extruded away from the light and make an inverse shadow volume. This inverse shadow volume would cover fewer pixels than the regular volume and save you some fill. You’d have to adjust the stencil testing a bit, but otherwise it should work as usual.

Is that close?

– Zeno[/b]

I don’t get it. What are you talking about?

Just a guess.
Does it have to with “infinite shadow volumes” ? By setting w = 0 one wouldn´t have to scale the vertices “by hand”, and could therefore save some calculations ?

Jan.

Another guess (for infinite shadow volumes):
Instead of extruding to infinity one might extrude to the (point) light source visiting infinity on the way? This would make it
easier to close the shadow volume.

-boyd

It allows you to draw your shadow volumes as triangles instead of quads. As boyd suggested, you can “extrude” towards the light instead of towards infinity, and because you “go around past infinity”, the results will still look the same.

For simplicity’s sake, I’ll assume that all W coordinates are normally 1. To extrude an edge AB towards infinity, you would normally render this quad:

glVertex4f(Bx, By, Bz, 1);
glVertex4f(Ax, Ay, Az, 1);
glVertex4f(Ax-Lx, Ay-Ly, Az-Lz, 0);
glVertex4f(Bx-Lx, By-Ly, Bz-Lz, 0);

You can use this triangle instead:

glVertex4f(Bx, By, Bz, 1);
glVertex4f(Ax, Ay, Az, 1);
glVertex4f(-Lx, -Ly, -Lz, -1);

I don’t know how much this would save you out there in the real world, but it’s definitely a Cunning Trick.

– Tom

Ahh! That is a very nice trick.
So, do I recall it being mentioned that most drivers ignore ‘external’ triangles? Does that mean they ignore triangles containing verts with a negative W?
Basically, is this ‘trick’ portable to other chipsets/drivers? Is it in the gl spec to deal with them correctly?

This is very interesting. It seems to work on the 9700. If I remember correctly, a line with differing signs for its endpoints ( wc clip coordinate ), would require performing two clipping operations. According to the GL spec, only the wc > 0 is required to be generated ( for this case with differing signs ), so is it correct that it might not work ?

Well, here’s the relevant bit from the spec:

Section 2.11: “Clipping” (page 43):
A line segment or polygon whose vertices have Wc values of differing signs
may generate multiple connected components after clipping. GL implementations
are not required to handle this situation. That is, only the portion of the primitive
that lies in the region of Wc > 0 need be produced by clipping.

It seems that implementations are allowed to discard the Wc < 0 part, but not required to do so. If they generate both parts, of course, the trick will not work.

I don’t know if any such implementations exist, though. I’ve tested it on different GeForces and on the GDI Generic renderer, all of which work fine. It didn’t work on Parhelia, but not because of different clipping behaviour, by the looks of it.

– Tom

I belive that current hardware perform rasterization in homogeneous coordinates, so rasterization of external triangles should be handled correctly.

Well done! One gold star for boyd (for having the right idea), and two for Tom (for understanding and clarifying details)!

As was pointed out, it is not illegal for an OpenGL implementation to rasterize both parts of an external triangle, which would be problematic. In reality, I don’t know of any implementations that actually rasterize wc<0. They’re required to rasterize wc>0 though.

But wait! There are more gold stars to give out. Round 2 questions:


When can’t you use this technique? Why?

Thanks-
Cass

I want a gold star too . I’ll have a shot, you can’t use it with directional lights. Why ? All points would project to a single point and therefor not rendered…

I think…

Edit: That should have been “all triangles project to a single point”

[This message has been edited by PH (edited 02-05-2003).]

Do the shadow volume caps match correctly with the edges of the external triangles? In theory they should, but since the computations are quite different maybe they do not match correctly producings seams (as with the t-juncs).

PH, directional lights would work fine. It’s just the previous method. The w component of the directional light is 0, so you only negate the light direction, and in fact that’s what you usually do with Cass and Kilgard’s method.

An obvious answer would be “when you’re using finite shadow volumes”, but I think PH’s answer might be closer to what you had in mind

Castano: as far as I can tell from my (admittedly rather simple) test app, the two approaches lead to 100% identical output.

– Tom

Well Tom, I cannot test it right now. I’ve an exam tomorrow morning and should be studying instead playing with homogeneous coordinates :stuck_out_tongue:

So, I was just guessing. I though about t-juncs, because when you are extruding a cap triangle with w=0 you place it on infinity, and when you use an external triangle, you have an edge that goes through infinity and commes back to the opposite vertex. So, you really have a t-junc. However, I don’t know if that produces artifacts or not…

You guys are sniffing in the right direction, but nobody’s nailed it with authority yet.