开发者

OpenGL: Calculating z-value for 1:1 pixel ratio

开发者 https://www.devze.com 2022-12-17 18:28 出处:网络
I have a 256x256 texture in my view frustum that I need to move to a z-position where the texture is replicated on-screen at ACTUAL size.

I have a 256x256 texture in my view frustum that I need to move to a z-position where the texture is replicated on-screen at ACTUAL size.

What I have so far is:

    const float zForTrueScale = -((itemSize/2) / tanf(DEGREES_TO_RADIANS(fieldOfView/2)) ) * 2;     

where itemSize is the size of my texture in world space (2.0 units). This is to calculate what Z (adjacent) is when itemSize/2 (opposite) is 1.0. I thought this would work.

This formula shows a texture开发者_StackOverflow社区 consistently too small by about 10% no matter what FOV I use.

Thanks

EDIT: I am moving around images in 3D space and need a seamless transition to the correct z-distance. I can't use orthagonal projection, it has to be in a view frustum.


You can do this slightly more easily than messing about with fields of view as the info you need is held directly in the projection matrix.

Thus given your projection matrix will look like this:

xScale     0               0                     0
0        yScale            0                     0
0          0     -(zf + zn)/(zf - zn)  -(2 * zf) / (zf-zn) 
0          0              -1                     0

Where z-Far (zf) and the z-Near (zn), xScale and yScale are known.

To choose the correct Z-Depth we'll start off with making sure w ends up as 1. This way when we do the divide by w it won't change anything.

Fortunately w is very easy to get at. It is simply the negative of the input z. Thus an input of -1 into z will return a w of 1.

We'll assume you are using a resolution of 1024x768 and that the texture you want at the correct scale is 256x256.

We'll also further assume that your rectangle is setup with top left at a position of -1, 1 and bottom right at 1, -1.

So lets plug these in and work out the z.

if we use the following:

-1, 1, -1, 1
1, -1, -1, 1

we will get out something as follows.

1 / xScale, -1 / yScale, someZThatIsn'tImportant, 1
-1 / xScale, 1 / yScale, someZThatIsn'tImportant, 1

The viewport transform transforms those values such that -1, 1 is 0, 0 and 1, -1 is 1024,768

So we can see that works by doing ((x + 1) / 2) * 1024 and ((1 - y) / 2) * 768

So if we assume an xScale of 3/4 and a yScale of 1 we can see that by plugging that in we'll get the following:

For top left:

x = -3/4
=> ((-3/4 + 1) / 2) * 1024
=> 128
y = 1
=> ((1 - 1) / 2) * 768
=> 0

For bottom right:

x = 3/4
=> ((3/4 + 1) / 2) * 1024
=> 896
y = -1
=> ((1 + 1) / 2) * 768
=> 768

You can thus see that we have a 768x768 pixel image centered in the screen. Obviously to get 256x256 we need to get the w to be 3 so that post w divide we have those coordinates a 3rd of the size ((xScale * 1024) / 256 should be equal to (yScale * 768) / 256 to get a square projection.

So if our final coordinates are as follows:

-1, 1, -3, 1
and
1, -1, -3, 1

we will get the following out (after w-divide):

-0.25, 0.333, unimportantZ, 1
and
0.25, -0.333, unimportantZ, 1

Run those through the screen equations above and we get

For top left:

x = -0.25
=> ((-0.25 + 1) / 2) * 1024
=> 384
y = 0.3333
=> ((1 - 0.3333) / 2) * 768
=> 256

For bottom right:

x = 0.25
=> ((0.25 + 1) / 2) * 1024
=> 640
y = -0.333
=> ((1 + 0.33333) / 2) * 768
=> 512

640 - 384 = 256
512 - 256 = 256

Thus we now have the final rect at the correct pixel size...


Without knowing too much about your situation, it's almost certainly easier to push an orthogonal projection onto the projection matrix stack, draw your texture and then pop it off again.


Although it would be slow, you could just use glDrawPixels() and be done with it.

...not if it's performance critical, though!


Is your framebuffer square ?

If not, then you have a horizontal field of view and a vertical one. Are you using the correct one ? Also, how do you know for sure you want it to be 2.0 units in world coordinates ? If your end-goal is to map it to pixels, then you need to take the viewport into account, and work back from that.

I also agree with Pike65 that I don't get where the *2 is coming from.

0

精彩评论

暂无评论...
验证码 换一张
取 消