Sei sulla pagina 1di 7

Conservative Visibility Determination for Architectural

Scenes
Boris Reuderink
University of Twente, faculty of EEMCS
b.reuderink(a)student.utwente.nl

ABSTRACT from such a region (often called a cell), the precomputed


In this article I present a conservative visibility determination information can be used to quickly render the scene.
algorithm, particularly suited for interactive walkthroughs in In this paper, a conservative visibility determination algorithm
architectural scenes. This algorithm is able to determine which will be presented, well suited for architectural scenes.
parts of the scene are visible during an interactive real-time
walkthrough. The algorithm consists of an off-line part, which
preprocesses the scene, and an on-line part, which determines 2. PREVIOUS WORK
the potentially visible faces for a given viewpoint. A lot of different algorithms do exist to compute visibility.
The algorithm uses a heuristic, which tries to maximize the Most precompute the potentially visible parts of the scene, and
number of found occluders, to guide the spatial subdivision. store the result in a convenient way. This result is called the
The faces of the cells that intersect the scene after the Potentially Visible Set (PVS) [TS91]. There are far too many
subdivision are used as occluders. visibility determination algorithms to list them all. Some of
them are listed below.
During the interactive walkthrough, the nodes of the scene are
recursively tested against a buffer that stores the occluders of In [HBPF02] the presented algorithm stores the visibility
drawn cells. information for each viewcell as an “Occlusion Maps”, which
are maps with a similar structure to a z-buffer. When the cell is
Keywords rendered, the occlusion map can be used to determine which
Conservative visibility determination, visibility, volumetric, cells are visible.
viewcell, occluder, fusion, computer, graphics, 3D, PVS, Durand et al. describe a method in [DDTP00] in which they
interactive walkthroughs, spatial subdivision, BSP-Tree. project occluders on a projection plane using a so-called
extended projection. This extended projection of an occluder on
1. INTRODUCTION a projection plane with respect to a cell is the intersection of all
Visibility determination is a key requirement in real-time 3D projections from views in the viewcell. From the extended
computer graphics applications. Nowadays, consumer 3D projections a hierarchical depth map is constructed. This map
hardware is able to display lots of geometry. This power is best can be used to determine which cells are visible.
utilized when a conservative visibility determination algorithm These algorithms precompute the potentially visible set for a
is used. A conservative visibility determination algorithm region in space. Another approach is to compute visibility for a
removes geometry from the scene only when it is guaranteed point in space. This has to be done in real-time. An example of
that the geometry is invisible from a certain region in space. such a point-based method is [ZMHH97], in which hierarchical
Conservative visibility determination overestimates the set of occlusion maps are used. This method is less suited for real-
visible polygons. Exact visibility, such as analytic visibility time walkthroughs on consumer hardware, because the CPU
causes too much overhead for real-time interactive needs results form the GPU while rendering.
walkthroughs. An example of analytic visibility algorithm is Another point-based algorithm is portal rendering. The data-
described in [DD02]. structure consists of convex polyhedral meshes, which are
Discrete conservative visibility algorithms do exist, such as the linked together. Visibility is then computed by determining
one proposed in [ZMHH97]. Depending on the hardware that is which parts of the view are transferred to connected cells. See
available these algorithms can work reasonable well, but for example [TS91].
consumer 3D hardware usually isn't optimized for reading back In the next two sections two algorithms are discussed in more
from the hardware, which makes the technique less useful for detail because they contain some limitations the new algorithm
real-time walkthroughs on consumer hardware. tries to solve.
Most interactive walkthroughs precompute the visibility for
regions in space. When the application needs to render a view 2.1 Conservative Volumetric Visibility with
Occluder Fusion
Schaufler, Dorsey, Decoret and Sillion described an algorithm
Permission to make digital or hard copies of all or part of this work for for conservative visibility preprocessing in [SDDS00]. Their
personal or classroom use is granted without fee provided that copies algorithm is designed with real time walkthroughs in mind.
are not made or distributed for profit or commercial advantage and that
copies bear this notice and the full citation on the first page. To copy The algorithm preprocesses the scene, ands stores potentially
otherwise, or republish, to post on servers or to redistribute to lists, visible cells for each viewcell. When the interactive
requires prior specific permission. walkthrough runs, the stored visible cells for the current view-
3rd Twente Student Conference on IT , Enschede June, 2005 cell are drawn. The algorithm uses a volumetric representation
Copyright 2005, University of Twente, Faculty of Electrical of the scene. To find suitable occluders, the scene has to be
Engineering, Mathematics and Computer Science
transformed in a discrete representation. This is done by • Covering when the face is on the border of the child
subdividing the scene into smaller parts using a quadtree (in cell
2D) or an octree (in 3D). Then each voxel (volume pixel, in this
• Incident in all other cases
case a leaf-node of the quad-tree or octree) is classified as
empty, full, or boundary. Boundary voxels are those voxels that
contain a portion of an objects surface. Using the odd-parity All but disjoint faces are stored in the child nodes. The covering
algorithm, the other voxels can be classified as full or empty. faces are used as occluder later on. The subdivision stops when
For each viewcell, the visible cells are computed. Important is there are no suitable splitters left. After this subdivision, rooms
the fusion of occluders. The “shadow” of an occluder is marked are stored in the leaves of the BSP-tree.
as solid, and occluding. Other occluders coinciding with this
volume are merged with the former occluder. Large portions of For these rooms (or cells), the sight lines are computed trough
the scene can be combined into occluding volumes because of portal sequences. To compute these sight lines, first a cell
the spatial subdivision scheme. adjacency graph is generated. Two cells are connected if their
shared boundary (portal) is not completely opaque. For each
Note that this method is not necessarily conservative, despite cell a stab-tree is calculated. Each node of this stab tree
the title of the article. If, for example a bunker is subdivided, a represents a cell that can be seen from the current cell. The
very small window in the bunker can be too small to generate stab-tree contains cells that are potentially visible from the
an empty node. See Figure 1. The interior of the bunker is then current cell. Using this stab-tree, the set of potentially visible
erroneously marked solid. The window will then block sight. polygons can be further restricted. Multiple ways of further
The occurrence of this problem can be limited by a high degree visibility computation are described in the article. The simplest
of subdivision, which will cause high memory usage. Another way is to check for every cell if it is in the view-cone. Better
issue is the use of volumetric occluders. Good occluders do not culling can be achieved if the stab-tree is culled using a depth-
necessarily occupy a large volume of space. A wall, for first search. Cells that are not visible are skipped, including
example, can be a good occluder. In the algorithm of their invisible children. Instead of testing the visibility of the
[SDDS00], the scene has to be subdivided until there are voxels cells, their connective portal can be tested.
that fall completely inside the wall. In [SSDS00] there are no
examples in which these limitations are shown nor are they One step further is to test the visibility of a cell (or portal) using
discussed in the article. the portals of its parents. This is called portal rendering. It is
obvious that better results are achieved at the expense of in
increased computational complexity.

A drawback of this technique is that every polygon in the scene


contributes to the stab-tree. Imagine for example a room with a
window and a bulb hanging on a cable in the centre of the
room. This bulb is not likely to contribute a lot to the visibility
of other rooms. Using the subdivision scheme as presented in
[TS91], this room will generate a lot of connected convex cells.
This results in the need for a lot of memory and an increased
computational complexity.
Note that this algorithm has to be extended to support non-axis-
aligned faces.
After an initial sort of O (n * log n), the selection of a suitable
splitting plane for a cell is linear to the number of faces
contained in the cell, according to [TS91]. Because the search
for a suitable splitter generally occurs twice after a BSP-tree
split, this doesn't scale well with scenes with a high number of
polygons.
Figure 1 - Error in Conservative Volumetric Visibility with
Occluder Fusion
3. OVERVIEW
The algorithm determines which parts of the scene are visible
2.2 Visibility Preprocessing for Interactive from a certain viewpoint. The algorithm consists of two parts, a
Walkthroughs preprocessing part, and a real-time part. The preprocessing can
Seth J. Teller and Carlo H. Sequin present in [TS91] an be done offline. The preprocessing has to be done only once for
algorithm that performs conservative visibility determination. the scene.
Their input data consists only of axis align faces, their The scene is subdivided into smaller boxes. These boxes (or
algorithm is not limited to axis aligned faces. The scene is cells) contain the geometry in their region, and the intersection
subdivided using an axis-aligned BSP-tree. After each split, the of their faces with the scene. These intersections will be used as
contents of the parent node are classified as: occluders.
During an interactive walkthrough, the cell in which the viewer
• Disjoint when the face is not in a child cell is, is located. This cell is drawn, and the occluders on the faces
of this cell are rendered into the visibility buffer. Then the
• Spanning when the face spans the child cell
neighbors of this cell are tested for visibility. Note that due to
the tree structure large groups of cells can be rejected quickly.
If a neighbor is visible, it is drawn, and its occluders are
rendered to the visibility buffer. This process repeats until are
nodes are rejected or drawn, or when the visibility buffer is
completely opaque.
In the next sections the input data, the way the scene is
subdivided, and the way visibility queries are performed are
described.

4. ASSUMPTION ON THE INPUT DATA


For this algorithm, the scene is specified as a collection of
vertices. Each vertex is stored as a tuple, for example in R3 a
vertex is stored as a tuple (x, y, z). See Figure
2.

Figure 3 - Two objects


The input data is assumed to contain objects with correctly
facing triangles. The objects do not contain holes.

5. PREPROCESSING
5.1 Splitting
In order to cull away large portions of the scene when the scene
is rendered, it is necessary to split the scene in smaller parts.
These smaller parts can be drawn independently. In 3D, an
object can be split into two halves using a plane. This process is
drawn in Figure 4.

Figure 2 - Vertices

The planes composing the scene are defined using n vertices in


Rn. In R3 a plane is uniquely defined using 3 vertices (a, b, c).
The normal vector of the triangle coinciding with the plane
determines the front side of the triangle. The normal is is
calculated as follows:

n = (b - a) × (c - a)

In the following pictures a 2D representation is used for the


planes. The normal vector points in the direction from which
the plane is visible. If connected triangles are all facing the
same direction as their neighbors, the space on the backside of
the planes is solid.
In Figure 3 six planes are displayed in 2D. There are two solid Figure 4 - Splitting a triangle
objects, each composed of three planes. These two objects do
intersect; their intersection is still solid.
The horizontal line represents the plane that is used tot split the
object. For each vertex of the object is determined if it is on the
front or the backside of the splitting plane. If an edge is
splitObject(splittingPlane, object) connected to both a vertex on the front and the backside of the
{
Object frontObject, backObject splitting plane, the edge has to be split. Vertex (1, 2) in Figure 4
foreach triangle in object has to be split because the former property holds. A new vertex
{ has to be created at the point where the splitting plane intersects
(front, back) = split(triangle); the edge.
}
frontObject.addTriangles(front); During the splitting of the edges, two new polygons can be
backObject.addTriangles(back); created. In Figure 4 the triangle (1, 2, 3) is split into two
polygons: (1, 4, 5, 3) and (4, 2, 5). If splitting of triangles
return (frontObject, backObject);
} results in polygons, these polygons can be stored as triangles.
The polygon (1, 4, 5, 3) in Figure 3 can be represented using the

Listing 1 splitObject()
two triangles (1, 4, 5) and (1, 5, 3). An outline of this splitting
algorithm is given in Listing 2.
Now it is possible to split triangles using a splitting plane, an
object can be split by splitting all its triangles. All new triangles
on the front side of the splitting plane belong the sub object on
the front side; all triangles on the backside belong to the sub
object on the backside. An outline is given in pseudocode in
Listing 1.
Note that the two half objects are not closed any more.
When an object is split it's intersection with the splitting plane
has to be computed. A case of this problem is shown Figure 5.
The intersection is bounded with the vertices that were created
during splitting. The normal vectors of the planes that go
through the triangles that are split are projected onto the
splitting-hyperplane for each edge on the splitting plane. Now Figure 5 - Split an object using a splitting plane
we have edges lying on the splitting-hyperplane, with a vector
pointing away from the intersecting area. If the intersection is
calculated for multiple objects, their intersection with the
splitting-hyperplane can overlap. This overlap can be removed
5.2 Recursive subdivision
When the preprocessing starts, all we have is one big scene,
using a Boolean operation in 2D. The normals vectors are used
conforming to the rules stated before. For effective culling, the
by the Boolean operation. See for an algorithm [Weiler80]. The
scene will be subdivided into smaller parts. There are different
resulting polygon covers the intersection with the hyperplane.
ways to split the scene, such as octrees and BSP-trees
We now have defined the tool we will use during the process of [FFGH97]. We will use a specialized form of the BSP-tree,
spatial subdivision. namely the axis-aligned BSP-tree. An axis-aligned BSP-tree
(AABSP-tree from now on) is a regular BSP-tree, but the
splitting planes are guaranteed to be axis-aligned. This
splitTriangle(triangle, plane) limitation makes it possible to optimize the calculations. Later
{
Polygon front, back;
we will see this it has other implications, which will become
foreach Edge e in triangle beneficial.
{ An AABSP-tree was chosen instead of a BSP-tree because in an
if(onBack(e.v1) && onBack(e.v2))
back.add(e); architectural scene the large occluders are likely to be axis-
if(onFront(e.v1) && onFront(e.v2)) aligned too. A normal BSP-tree allows all orientations for
front.add(e); splitting planes, which complicates the heuristic for selecting a
else splitting plane.
{
Edge se = intersection(plane, e); An octree is axis aligned, but it subdivides space into eight
if(onBack(e.v1)) equal parts. This results in a lot of unnecessary splits.
{
back.add(Edge(e.v1, se)); The AABSP-tree of the scene is calculated recursively. First, a
front.add(Edge(se, e.v2)); splitting-plane has to be determined. When we start, we have no
}
information besides the volume of the scene. We select a
else
{ splitting-plane perpendicular to the largest dimension of the
front.add(Edge(e.v1, se)); scene, so the subspaces we will end up with will not become to
back.add(Edge(se, e.v2)); irregular.
}
} The whole scene is split using this splitting-plane. The
} intersection of the scene with splitting plane is calculated, and
return (front, back); stored along with the splitting-plane. Now we have two halve
}
scenes, defined by a splitting-plane. For each halve, the process
Listing 2 splitTriangle() is repeated. See Figure 6. First, the scene is split using a vertical
hyperplane. The red part of the splitting plane represents the
intersection of the splitting plane with the scene. The left
subspace is further subdivided; the right sub space is simple
enough to remain as it is. The splitting of the left subspace
generates another splitting plane, and an associated intersection.
The upper part of the left subspace is then subdivided again.
Figure 7 - Sudvision in a more complex scene

When a scene like the one in Figure 7 is subdivided, it


generates a BSP-Tree. See Figure 8. Each subspace that was
spit contains two children, one representing the subspace on the
Figure 6 - Recursive subdivision front side of the splitting plane, and one on the backside of the
splitting plane. The process of recursively splitting and storing
intersecting areas has to be completed before visibility queries
In Figure 6, it can be seen that the splitting planes do not have can be performed in real-time. It is advisable to perform these
to divide space into equal parts. The location of the splitting calculations offline.
planes is chosen using a heuristic that tries to maximize the area
the new intersection covers. For architectural scenes, where
most walls are aligned with the coordinate system, the location 6. VISIBILITY QUERIES
of the new splitting plane can be calculated using the center of Now the scene is subdivided, conservative visibility queries can
gravity of the adjacent splitting planes. When there are more be performed. A visibility query determines which parts of the
areas of intersection on a splitting plane, the center of gravity scene are visible from a certain point. In real time
closest to the center should be considered. So the process of walkthroughs, these calculations have to be performed every
selecting a splitting plane is as follows: frame.
• Select the largest dimension of the subspace as the
normal of the splitting plane.
6.1 Traversing the tree
First we have to determine in which subspace the viewer is.
• Find the areas of intersection on the enclosing faces. Some or all parts of this subspace are always visible. The
Exclude those that contain a corner of the cell. subspace the viewer is in can be determined by walking down
• Calculate the center of gravity for each area of the BSP-Tree. For each node that is visited, we take the
intersection. splitting plane and check on which side the viewer is. The next
node that is visited is the node representing the subspace that is
• Select the center of gravity that produces the most on the same side as the viewer is. When a node has no children,
balanced cut and create a splitting plane through that it is the leaf that contains the subspace in which the viewer is.
point using the earlier determined normal. If no This is the first visible subspace, which can be rendered
centers are found, create a splitting plane in the immediately.
middle. If overlapping intersections are found, split
through them.
Using this heuristic, we can subdivide the scene in a way that is
likely to produce splitting planes inside solid spaces, for
example inside axis-aligned walls.
The subdivision has to be stopped at a certain point. When the
volume of a subspace becomes smaller than a predefined
threshold, it will not be divided. If a subspace is empty, there is
no point in further subdivision. So empty subspaces shall not be
subdivided either.
In Figure 7 a more complex scene is shown, which is
subdivided using the described algorithm. It can be seen the
algorithm is able to find good axis-aligned occluders using few
subdivisions. The wall that is not axis-aligned doesn't create a
very useful occluder.

Figure 8 - The BSP-tree assiciated with the scene


be determined using this buffer. Such a visibility-buffer must
provide a fast way to insert new polygons, and a fast way to
visQuery(Tree t, Viewer v, Buffer b) determine the visibility of subspaces. Any kind of buffer can be
{ used if it can provide such interface. Possible candidates are:
Vector result;
if(t is not a leaf) • A Coverage buffer (C-Buffer)
{
if(t.onFrontSide(v)) • A Quadtree
{
result+= visQuery(t.front, v, b); • A Z-Buffer (possibly the one on the graphics card)
if(isVisible(t.back, b) In the next sections, these buffers are evaluated.
result+= visQuery(t.back, v, b);
}
else
{ 6.2.1 The Coverage buffer
result+= visQuery(t.back, v, b); The coverage buffer [Kmet99] is a buffer that stores the ranges
if(isVisible(t.front, b)
result+= visQuery(t.front, v, b); on a scan-line that is currently covered. A list of nodes
} containing a start index and end-index is stored for each
} covered span. For a whole coverage buffer, for each scan-line
else // t is a leaf such a list is required. See Listing 4.
{
renderVisbility(t, b); When a triangle is inserted, it has to be converted to scan-lines.
result.add(t); This can be done using a the scan-line conversion as presented
}
in [FFGH97]. For each scan-line, we now have a range covered
return result;
} by the new triangle, and a list of ranges of earlier inserted
triangles. The new scan-line is the result of old scan-line
isVisible(Tree t, Buffer b) merged with the range of the new triangle.
{
//Checks if a node is visible To test if a triangle is visible, the same conversion to scan lines
.. is used. To test if a triangle is visible, the same conversion to
} scan lines is used. If a subsequent insertion would change the
renderVisibility(Tree t, Buffer b) coverage buffer, the triangle is visible.
{
//Adds intersecting areas to b
.. Screen: Buffer:
}
1 2 3 4 5 6 7 8 9 10
. . . . . . . . . . []
Listing 3 visQuery() . . . . . . . . . . []
. . . . . x . . . . [6, 6]
. . . . x x x . . . [5, 7]
. . . x x x x x . . [4, 8]
. . x x x x x x x . [3, 9]
. . . . . . x x x x [7, 10]
All the faces that enclose the subspace can contain intersections . . . . . . . . . . []
. . . . . . . . . . []
with the geometry of the scene. If such a face contains an
intersection, this intersection is rendered to a temporarily
buffer. More information about this buffer will be given later
on. Listing 4 - Coverage buffer
Now the subspace is rendered, and its visibility information is
stored in the buffer, the neighbor of this node is considered.
First, the bounding box of the neighboring subspace is checked 6.2.2 Quadtree
against the temporarily buffer for visibility. If it is completely In order to use spatial coherence, a quad-tree structure could be
invisible, it can be skipped. Otherwise, the neighbor has to be used to speed up visibility queries. A quad tree is hierarchical
handled. If the neighbor is a leaf, this leaf is also visible, and its structure, which divides a 2D space into 4 equal parts. See
occluding areas can be added to the temporarily buffer. If the [Samet84]. In our case, this quadtree subdivides a buffer in
neighbor is not a leaf, its children should be handled in the which we store coverage information. In order to support non-
same way as the neighbor. When the neighbor has been square displays, tiles of quadtrees can be used. Triangles need
handled, we take its parent and proceed. An outline for this to be inserted into the quadtree. The process is analog to the
algorithm in pseudo code can be found in Listing 3. When the process of inserting a triangle into a coverage buffer. An
algorithm is finished, it returns the nodes that are not fully algorithm can be found in [FFGH97]. If the tree doesn't change
covered by the intersecting areas found during preprocessing. If after an insertion, the triangle was not visible.
nothing is occluded, the whole BSP-Tree is visited. Otherwise,
one or more sub-trees are skipped, whose sizes are dependent of To speed up calculations, the leaves of the quadtrees could store
the amount of occlusion. groups of 8x8 pixels. Using 64-bit binary operations the
visibility queries can be calculated efficiently. See for more
information [Greene96].
6.2 Visibility Buffer
When the BSP-Tree is traversed, every visible node stores its
opaque sides in a buffer. The visibility of subsequent nodes can
6.2.3 Z-Buffer Another limitation is that the algorithm cannot take advantage
The z-buffer stores the depth information for every pixel of curved surfaces in its current form. The use of other
[FFGH97]. The format in which the depth-information is stored representations for occluders can be investigated in order to
can vary, in order to minimize precision errors. The z-buffer is create an occluder if a curved surface splits a cell.
often implemented in hardware. If the hardware supports fast
queries on the z-buffer, it can be used for visibility queries.
In order to speed up calculations, a hierarchical z-buffer can be 7.1 REFERENCES
used. The structure of a hierarchical z-buffer is similar to a
quadtree. A hierarchical z-buffer can quickly reject triangles [Samet84] Samet H, The quadtree and related data structures,
based on their depth-values [GKM93]. Computing Surveys, Vol. 16, No. 2, June 1984
[FFGH97] Foley J, van Dam A, Feiner S, Hughes J, Computer
Graphics: Principles and Practice, 2nd ed. in C
7. CONCLUSIONS AND FUTURE WORK Addison-Wesley, ISBN 0-201-84840-6, 1997
In this paper a conservative visibility determination algorithm is
[Weiler80] Weiler K, Polygon comparison using a graph
presented, well suited for dense environments with lots of solids
representation, ACM SIGGRAPH Computer
spaces, or less dense environments with axis-aligned walls.
Graphics, Volume 14, Issue3, July 1980, 10-18
The algorithm is relatively simple, and doesn't rely on special
[Kmet99] Harmless Aglorithms,
3D hardware capabilities. The algorithm can be implemented
using a combination of different robust existing techniques. http://www.flipcode.com/harmless/issue01.htm,
This algorithm serves as an example for a class of visibility accessed May 2005
determination algorithms. Different existing techniques can be [Greene96] Greene N, Hierarchical Polygon Tiling with
used independently for different parts of the algorithm. Coverage Masks, International Conference on
Due to time restrictions a prototype could not be finished. Computer Graphics and Interactive Techniques, ISBN
Therefore, it is difficult draw conclusions about the algorithmic 0-89791-746-4, 65-74
complexity, as the average case complexity depends heavily on [GKM93] Greene N, Kass M, Miller G, Hierarchical Z-buffer
the type of the scene. Worst case (where the whole scene has to visibility, International Conference on Computer
be drawn) and optimal case (where only one cell has to be Graphics and Interactive Techniques, ISBN 0-89791-
drawn) complexity do not give insight in the performance of 601, 1993, 231-238
real scenes.
[SDDS00] Gernot Schaufler, Julie Dorsey, Xavier Decoret
Before other improvements could be made, first a prototype François X. Sillion, Conservative Volumetric
should be finished. The results of this prototype could be Visibility with Occluder Fusion, International
evaluated, and the results of [TS91] and [SSDS00] should be Conference on Computer Graphics and Interactive
compared with the results of the prototype. Techniques, ISBN 1-58113-208-5, 2000, p229-238
Different visibility buffers can be evaluated. Results may vary [HBPF02] Wei Hua, Hujun Bao, Qunsheng Peng, A.R. Forest,
depending on the scene, the destination resolution etc. The The Global Occlusion Map, A New Occlusion
splitting heuristics can be improved. For example, intersections Culling Aproach, VRST'02, November, 2002.
with an area below a certain threshold can be ignored. Or a
utility value could be calculated for each intersection, [DDTP00] Frédo Durand, George Drettakis , Joëlle Thollot,
depending on distance from the median cut, its size etc. Claude Puech, Conservative Visibility Preprocessing
using Extended Projections, SIGGRAPH 2000, 2000
The algorithm as presented is limited to axis-aligned occluders.
This means that angled walls will only partially contribute to [ZMHH97] Hansong Zhang, Dinesh Manocha, Tom Hudson,
good occluders. An area of research can be the investigation if Kenneth E. Hoff III, Visibility Culling using
analysis of the normal vectors of the faces inside the cell could Hierarchical Occlusion Maps, SIGGRAPH 1997,
lead to the selection of additional useful occluders located 1997
inside the cell. Those additional occluders should then be able
to take advantage of rotated walls.

Potrebbero piacerti anche