This document discusses building potential visibility sets (PVS) for leaves in a BSP tree using portals. It involves two main steps: 1) generating portals by clipping portal polygons through the BSP tree, keeping only portals that exist in two leaves, and 2) performing anti-penumbra clipping to determine which leaves are visible to each other based on the portals. This builds a binary PVS array that indicates potential visibility between all leaf pairs. Various techniques like bitpacking and zero run-length encoding can greatly reduce the size of this array.
Report
Share
Report
Share
1 of 27
Download to read offline
More Related Content
BSPTreesGameEngines-2
1. BSP Trees in 3D
Game Engines (2)
Shot from Unreal Tournament 2003
Shot From Doom3
Modified from an original presentation
prepared by Jason Calvert, 2003.
Principles of:
Portals and
Potential Visibility Sets (PVS)
2. Intro to PVS
We need to know which other leaves can be seen
from any one leaf.
A PVS is a 2D array of bytes or booleans which
contains all visibility info for each leaf.
Each leaf's visibility information is a single row - one
column for each other leaf. If the 3rd
entry in the row
representing leaf 2 is true then leaf 2 can be seen
from leaf 3.
Thus, this array will tell us which leafs are visible from
any other leaf.
The PVS is non view dependent. It just tells us what
is potentially visible even if it’s outside of the
frustum.
3. Building a PVS
There are two steps to building a PVS.
Portal Generation.
Finding out information about the gaps( doorways)
in our level.
Anti-Penumbra clipping.
Testing which leafs are visible based on the
portals.
4. Portals
A portal is a special polygon that lies on
one splitting plane of the BSP tree.
Some portals will define non-solid
boundaries between adjacent leaves.
A portal between two leaves says that
there is a non-solid boundary between the
leaves and thus,one leaf is potentially
visible from the other.
5. Portal Based Engines
In a strictly portal based engine, portals will be
used in visibility processing between sectors
(subsections of a level).
In these situations visibility is determined at render
time, not from a pre-calculated PVS since visibility is
dependant on camera position.
Only render what can be seen from camera through
a portal. Process runs recursively until no more
portals can be seen through the current portal.
Ideal for mirrors.
Build a frustum from camera to portal and flip it so its
pointed back at you.
6. BSP and Portals
In Leafy BSP trees we will also use portals
for visibility processing, but as a compile
time step.
Portals will be used to construct the PVS for a
level but they will not be used at render time.
Portals will tell us the area of the gaps or
doorways in our level.
7. Building Portals
Some engines force you to place portals by
hand. This requires more work in the level
editor but less time is required to compile
the level (build BSP tree).
We will use our BSP tree with polygon
splitting to build these portals.
Build process is similar to the bsp compile
process.
8. Portal Building Process
Start by building a large polygon at each node in
the BSP tree.
This polygon is a portal that will lie on the node's
splitting plane.
Each portal polygon will receive a unique ID value
that can be used to identify the portal after it ends
up in a leaf node.
Send portal polygon down the tree starting at the
node it is built from.
9. Portal Building Process (2)
As it descends the tree classify the portal
polygon against the current node's plane.
If portal polygon is in front of the splitting plane
and not at a leaf send the portal polygon down
the front of the tree.
If the front is a leaf, this portal polygon is in empty
space and will be potentially used.
If portal polygon is behind the plane and not at a
leaf send the portal down the back of the tree.
If we are at a leaf this portal is in solid space and
can be rejected.
10. Portal Building Process(3)
If the portal polygon is spanning the plane
it must be split.
The front section will go down the front of the
tree, and the back section will go down the
back of the tree.
Each section of the original portal polygon will
receive the unique ID of its parent.
11. Portal Building Process (4)
If the portal polygon is on the splitting
plane of a node (not the starting node):
The portal polygon must be sent down the
front tree first. It may continue to be clipped.
All portal polygons that reach leaves in the
front tree must be grouped and sent down the
back tree.
Many portal polygons will be generated
this whole clipping process. Not all will be
used.
12. Which portals to use?
A portal polygon must exist in two leaves. (like a
doorway).
Recall that each portal polygon has a unique ID –
this allows finding the leaves it ends in.
There is a possibility of having two duplicate portal
polygons in different leaves.
Keep the larger of the two.
If a portal ends up in only one leaf it will be
rejected.
It doesn’t make sense to have a door that doesn’t lead
anywhere.
13. Portal Building Example
A
BE
D
CE2
E1
F
PB
PA PC
PF
PE2
PD
PE1
solid
solid
solid
solid
solid
solid
AFE1
BCE2D
Portals:
P1, P2, P6, P7
Portals:
P1, P3, P4, P5
Portals:
P1 from PB P2 from PA
P3 from PC P4 from PD
P5 from PE2 P6 from PF
P7 from PE1
14. How are Portals Used?
A leaf can see whatever it’s portals can
see.
So, we need to figure out which leaves a
portal can see.
Then each leaf's visibility will be whatever
each portal, contained in the leaf, can see.
15. Anti-Penumbra clipping
Called that because if we were to open a door into a
dark room, we are concerned only with the area that
will be lit.
Since each portal is contained in two leaves we can
determine the neighbors (via the portal) of any given
leaf.
We will assume a data structure or method is
available to determine the cross portal neighbors of
each leaf.
We will also assume that a binary array (PVS array) is
maintained for each leaf that indicates whether that
leaf is visible from the current leaf.
16. Anti-Penumbra Clipping Algorithm
For each leaf:
Mark the current leaf and all its cross-portal neighbors
as visible in the PVS array.
For each portal contained in the leaf build a set of clip
planes to portals in neighbors.
Leaf 3
Leaf 2Leaf 1
Leaf 4 Leaf 5
Leaf 6
1 1 0 0 0 0
PVS Array
17. Anti-Pen. Clipping Alg. (2)
Building Clipping Planes:
Planes extend from one side of the portal in the current
leaf to the opposite side of the portal in the neighbor.
Leaves on the opposite side of neighbor portals are now
also visible.
21
Leaf 3
Leaf 2Leaf 1
Leaf 4 Leaf 5
Leaf 6
1 1 1 0 0 0
PVS Array
18. Valid Clipping planes
Clipping planes are valid if they are built from opposite
sides of each portal.
This means that one portal will be on the front side of
the clipping plane and the other on the back side.
This makes a frustum like shape from one portal to
another.
With a valid set of clipping planes check to see if any
portals lie within them (these portals are now visible).
Leaves which contain visible portals are now also
visible.
Repeat the process recursively using the newly visible
portals until no new portals become visible.
19. Clipping
Thus, Leaf 3 becomes visible through portal 2 and
Leaf 5 becomes visible because portal 4 is visible
between the clipping planes.
Leaves 4 and 6 are not visible – no other portals
become visible by recursing with portal 4.
21
3 4
Leaf 3
Leaf 2Leaf 1
Leaf 4 Leaf 5
5
Leaf 6
1 1 1 0 1 0
PVS Array
20. Drawbacks
We are doing some pretty major
operations.
This process can be slow.
Quake3 levels can take up to a couple of
hours to compile using this process.
21. Total PVS Size
We now have a large byte array which
contains the potential visibility information
for each leaf.
This can be one big array or one array for
each leaf.
If there are N leaves then the array for each
leaf is size N.
The total array size is then N2.
22. Rendering
First find out which leaf the camera is in.
Lookup visibility info in Master PVS array or in
the PVS array for the leaf containing the
camera.
Check bytes to see which other leafs are visible.
If set to 1 leaf is visible, if 0 leaf is not visible.
Render all visible leafs polygons.
Since we lose our depth sorting information we’ll
need to turn on the zbuffer.
23. Tree Traversal
// Find out which leaf the camera is in
void Traverse(vector camerapos)
{
int Node;
while(1) {
switch(ClassifyPoint(camerapos, currNode.plane) {
case Front:
if(currNode.isLeaf) {
Render(currNode.front);
return;
}
currNode = currNode.front;
break;
case Back:
if(currNode.back == -1)
return; // ooops solid space
currNode = currNode.back;
break;
}
}
}
24. Rendering Algorithm
void Render(int camleaf)
{
// assumes PVS is one large array
// get PVS index of camera leaf
long offset = camleaf * numLeafs;
for(int i = 0; i < numLeafs; i++){
if(PVSData[offset+i] == 1)
Render(i); // for now just render
}
}
25. PVS Size Problem
Problem we face with storing an array of
bytes for PVS.
If our level contains 5000 leafs:
PVS will be 5000 * 5000 Bytes or approx 24
MB.
That’s for visibility info alone.
Not counting polygons, textures, etc…
26. Solving the PVS Size Problem
Since the PVS is storing binary (boolean)
information.
We can store this info in a bit instead of a
byte.
This brings our memory requirement down
to around 3 MB
27. Zero Run Length Encoding
Given that most leafs cannot see most other leafs there
will be a lot of zeros in our PVS table.
We can take advantage of this by counting the number
of consecutive zeros and storing that number in the next
byte.
Since a byte can only hold up to 255 that is the most
zeros we can skip using one byte.
This type of encoding can save a large amount of
memory.
Can take the PVS table from MB to KB.