W divide confusion

The Partridge Family were neither partridges nor a family. Discuss.
Post Reply
damoos
Posts: 14
Joined: September 21st, 2019, 6:35 pm

W divide confusion

Post by damoos » November 27th, 2019, 2:20 am

Ok, I've asked this poorly before, but I'll give it another stab.

Here is what I think to be correct:

After the projection transform, my x and y have been scaled to NDC space, where coordinates on the view plane are from -1 to 1 in x and y

Further, z coordinates are scaled to where , after a w divide, will also be in NDC space. In other words, if I get this right, Z is not yet in a 0 to 1 scale, while x and y are in -1 to 1 already at this point, just lacking perspective scaling.

Finally, the original Z is stored in W.

Here's my question. My understanding is that to do the perspective divide, I would now divide everything by W. My hangup is that, W contains the ORIGINAL z coordinate, which hasn't been scaled at all. This doesn't seem right to me. I feel I'm missing a step. Results on screen seem to confirm something isn't right. Up to this point, I had been simply dividing my world space coordinates by z, and all worked well. Looking over chilli's code, I can't seem to find where we differ, although at that point in the tutorial he's using shaders, which makes the code not as intuitive to follow as my own much simpler code.

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: W divide confusion

Post by albinopapa » November 27th, 2019, 6:24 am

Perhaps it would be easier for someone to help if you shared your code, either as a ZIP/RAR file or as a link to git repository.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

albinopapa
Posts: 4373
Joined: February 28th, 2013, 3:23 am
Location: Oklahoma, United States

Re: W divide confusion

Post by albinopapa » November 27th, 2019, 7:26 pm

In a perspective projection, the Z coordinate is scaled to NDC coordinates. It's a percentage of the range from near to far clipping planes. In DirectX at least, it's biased so that there is a larger disparity between vertices closer to the near clipping plan than there is in vertices closer to the far clipping plane.

Image

Look at row 3 and row 4, column 3. There is a bit of math done to change the Z to fit NDC coordinates. The W as you said, is just the original Z.

The transform of the vertex position is done, then you divide the result by W ( the original Z ) and you get the perspective projected position.

Code: Select all

	constexpr auto sw = 800.f;
	constexpr auto sh = 600.f;
	constexpr auto zn = 1.f;
	constexpr auto zf = 1000.f;

	constexpr auto zRange = zf - zn;
	constexpr auto znDouble = 2.f * zn;
	constexpr Matrix m = {
			znDouble / sw,			 0.f,					  0.f, 0.f,
					  0.f, znDouble / sh,			  		  0.f, 0.f,
					  0.f,			 0.f,			  zf / zRange, 1.f,
					  0.f,			 0.f,	( -zf * zn ) / zRange, 0.f
	};
	constexpr Vec4 v = { 10.f, 10.f, 10.f, 1.f };
	constexpr auto ndc_result = m * v;
	constexpr auto persp_result = ndc_result / ndc_result.w;
Using this code above, I get something like this:

Code: Select all

	constexpr auto sw = 800.f;
	constexpr auto sh = 600.f;
	constexpr auto zn = 1.f;
	constexpr auto zf = 1000.f;

	constexpr Matrix m = {
		.0025, 0.f, 0.f, 0.f,
		0.f, .0033, 0.f, 0.f,
		0.f, 0.f, 1.001, 1.f,
		0.f, 0.f, -1.001, 0.f
	};
	constexpr Vec4 v = { 10.f, 10.f, 10.f, 1.f };
	ndc_result = m * v = { .025, .033, 9.009, 10 }
	persp_result = ndc_result / ndc_result.w = { .0025, .0033, .9009, 1 }
The perspective matrix here doesn't take into account FOV, just with and height of the screen.

Basically, I'm showing that the Z is transformed before the divide by W.
If you think paging some data from disk into RAM is slow, try paging it into a simian cerebrum over a pair of optical nerves. - gameprogrammingpatterns.com

Post Reply