Jump to content
  • Advertisement
Sign in to follow this  
bengaltgrs

Calculating view frustums in portal rendering system

This topic is 4522 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

I am attempting to write a portal rendering system and I think I have it figured out for the most part, except for when it comes to calculating a new view frustum for each portal. As an example of what I am trying to do, observe this picture. I can find the begining frustum by simply calling this:
D3DXMATRIX ViewProj;
D3DXMatrixMultiply(&ViewProj, &View, &Proj);

//Near Plane
Planes[0].a = ViewProj._14 + ViewProj._13;
Planes[0].b = ViewProj._24 + ViewProj._23;
Planes[0].c = ViewProj._34 + ViewProj._33;
Planes[0].d = ViewProj._44 + ViewProj._43;
D3DXPlaneNormalize(&Planes[0], &Planes[0]);

//Far Plane
Planes[1].a = ViewProj._14 - ViewProj._13;
Planes[1].b = ViewProj._24 - ViewProj._23;
Planes[1].c = ViewProj._34 - ViewProj._33;
Planes[1].d = ViewProj._44 - ViewProj._43;
D3DXPlaneNormalize(&Planes[1], &Planes[1]);

//Left Plane
Planes[2].a = ViewProj._14 + ViewProj._11;
Planes[2].b = ViewProj._24 + ViewProj._21;
Planes[2].c = ViewProj._34 + ViewProj._31;
Planes[2].d = ViewProj._44 + ViewProj._41;
D3DXPlaneNormalize(&Planes[2], &Planes[2]);

//Right Plane
Planes[3].a = ViewProj._14 - ViewProj._11;
Planes[3].b = ViewProj._24 - ViewProj._21;
Planes[3].c = ViewProj._34 - ViewProj._31;
Planes[3].d = ViewProj._44 - ViewProj._41;
D3DXPlaneNormalize(&Planes[3], &Planes[3]);

//Top Plane
Planes[4].a = ViewProj._14 - ViewProj._12;
Planes[4].b = ViewProj._24 - ViewProj._22;
Planes[4].c = ViewProj._34 - ViewProj._32;
Planes[4].d = ViewProj._44 - ViewProj._42;
D3DXPlaneNormalize(&Planes[4], &Planes[4]);

//Bottom Plane
Planes[5].a = ViewProj._14 + ViewProj._12;
Planes[5].b = ViewProj._24 + ViewProj._22;
Planes[5].c = ViewProj._34 + ViewProj._32;
Planes[5].d = ViewProj._44 + ViewProj._42;
D3DXPlaneNormalize(&Planes[5], &Planes[5]);


The area I am having trouble with is creating the new view frustum for each portal. How would I go about using the current view frustum and a quad (set of four points representing the portal) to create a new view frustum? Thank you in advance, -Chris

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by bengaltgrs
The area I am having trouble with is creating the new view frustum for each portal. How would I go about using the current view frustum and a quad (set of four points representing the portal) to create a new view frustum?
I haven't written a portal engine myself, so this is not from experience, but here's one way you might go about it...

The portal needn't necessarily be a quad; it can be any convex polygon. The first step is to clip the portal to the frustum. This involves clipping it in succession against each plane of the frustum. For this you'll need a good polygon-to-plane clipping function (it can take a little work to make such a function robust).

Once the portal is clipped to the frustum, you have a new convex polygon. The new volume is then built from the near and far planes of the original frustum, and additional planes formed from the camera position and each edge of the portal.

This is a 'brute force' approach, but could probably be optimized in various ways, such as by exploiting coherency and clipping information.

Share this post


Link to post
Share on other sites
I was actually planning on setting it up so that each portal would have to be a quad, just to make it the programming part of it a little easier for me. The clipping of polygons out of the frustum I had already written actually, I just wasn't sure how to compute a new frustum given the current view and the portal quad. I did just realize however, that for each of the six planes that make up the view frustum, I can use the two points of the portal that are parallel with the plane in question (i.e. the two top points to find the top plane of the frustum) and project one point from the camera position to find a third point. From there I can call D3DXPlaneFromPoints which takes the three points and creates the needed plane.

Thank you again for the replies,
-Chris

Share this post


Link to post
Share on other sites
ok here's my ide for doing it (tested and works wihout problems)
it gives you 4 clip planes equivalent to finding screen space bounding
rectangle of your portal and recalculating 4 planes

1. extract original planes of view frustum from matrices
2. clip your portal polygon (can be any convex polygon) to clipping frustum
(ignoring near and far planes)
3. for each vertex of clipped polygon calculate distances to pairs of clip planes (horizontal and vertical) and calculate t=d1/(d1+d2)
4. find min/max t
5. use min/max t to interpolate equations of planes flipping one of them depending what plane do you want to calculate
for example.

so if you take 2 clip planes( left and right)
and want to calculate new left and right for given portal
you find min/max and then

new_left=old_left*(1-tmin)-old_right*tmin;
new_right=-old_left*(1-tmax)+old_right*tmax;

same for top/bottom

Share this post


Link to post
Share on other sites
Linear interpolation does sound like a pretty fast way of doing it, but how would I get the min/max values? Would I get the screen space coordiantes of the points of the quad and use those?

Thanks,
-Chris

Share this post


Link to post
Share on other sites
no you don't use screen space at all. that's whole idea.
for each vertex you calculate distances to 2 planes
and calculate t=d1/(d1+d2) where for example
d1 is distance to left and d2 to right plane (or top bottom)
and you select smalest and largest 't' for your portal polygon
and use it for interpolation.
it's all done in world space.

Share this post


Link to post
Share on other sites
So as it turns out, the very first method I came up with is the one that works, I just never fully tested it to make sure. Using this method requires that the shape of the portal be a rectangle, but the rectangle can be moved or rotated in any way, and still work fine. Here is the code to create a new view frustum from a rectangle:


D3DXVECTOR3 Points[4];
Points[0] = D3DXVECTOR3(0.0f, 1.0f, -2.0f);
Points[1] = D3DXVECTOR3(0.0f, 4.0f, -2.0f);
Points[2] = D3DXVECTOR3(0.0f, 4.0f, 2.0f);
Points[3] = D3DXVECTOR3(0.0f, 1.0f, 2.0f);

D3DXPLANE Plane[6];
D3DXVECTOR3 ProjPoint;
D3DXVECTOR3 Dir;
float FarClipDist = 150.0f;

//Near plane
D3DXPlaneFromPointNormal(&Plane[0], &ActiveCamera->Position, &ActiveCamera->LookVector);

//Far plane
D3DXPlaneFromPointNormal(&Plane[1], &(ActiveCamera->Position + (FarClipDist * ActiveCamera->LookVector)), &(-ActiveCamera->LookVector));

//Left plane
Dir = Points[0] - ActiveCamera->Position;
D3DXVec3Normalize(&Dir, &Dir);
ProjPoint = Points[0] + Dir;
D3DXPlaneFromPoints(&Plane[2], &Points[0], &ProjPoint, &Points[1]);

//Right plane
Dir = Points[2] - ActiveCamera->Position;
D3DXVec3Normalize(&Dir, &Dir);
ProjPoint = Points[2] + Dir;
D3DXPlaneFromPoints(&Plane[3], &Points[2], &ProjPoint, &Points[3]);

//Top plane
Dir = Points[1] - ActiveCamera->Position;
D3DXVec3Normalize(&Dir, &Dir);
ProjPoint = Points[1] + Dir;
D3DXPlaneFromPoints(&Plane[4], &Points[1], &ProjPoint, &Points[2]);

//Bottom plane
Dir = Points[3] - ActiveCamera->Position;
D3DXVec3Normalize(&Dir, &Dir);
ProjPoint = Points[3] + Dir;
D3DXPlaneFromPoints(&Plane[5], &Points[3], &ProjPoint, &Points[0]);



I do have one final question about portal rendering. My portal rendering is setup to frutum check all of the objects inside the room it is rendering including the walls/floor/ceiling. Obviously there will be times when only a very small section of a wall will be visible through the portal, but since part of it is visible, the whole thing will be rendered. This will cause the game to render much more than it needs to, which I am obviously trying to limit. So my question is, and keep in mind I am using DirectX, would it be a good idea to use user clip planes? This way, it would be garunteed that the only pixels that get rendered are the ones visible through the portal. The game is rendered entirely in HLSL shaders, and uses PS 2.0 extensively right now, but I intend to allow for a PS 1.1 option. I know the lowest card with PS 1.1 support is the GeForce3, but what I do not know is if it is capable of supporting 6 user clip planes. Also, since the portal rendering will cut out most of what is not in view, would it be faster to just not use clipping planes at all?

Thanks,
-Chris

Share this post


Link to post
Share on other sites
The way i use to do that is using scissor test. First u project the portal verts on screen (2D space), and then find a rectangle that fits it. So u enable scissor test, and use this rect as it parameter (glScissor(x,y,width,height), then only this region is rendered.
Hope this helps!

Jorge Adriano Luna

Share this post


Link to post
Share on other sites
Having a perfect portal system (zero overdraw) on modern GPU's is a waste of CPU resources and will be sub-optimal.

Using a sloppy-portal system such as described is surely the way to go these days. Yes you will have overdraw. No you probably can't do much better in regards to performance.

Overdraw isnt the big killer it used to be and portal engines by their nature render near geometry before far geometry: So the GPU is able to ignore lots of overdraw before the requests propagate to the fragment shader (so its not going to kill your fill rate)

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!