SlideShare a Scribd company logo
1 of 43
Download to read offline
Quake3 Rendering Engine
Intro to Quake3 rendering
techniques including BSP,
PVS, textures, and
lightmapping
Modified from an original presentation
prepared by Jason Calvert, 2003.
Problem
For our visibility system each leaf will know
which other leafs they can see.
Up until now we’ve used a linked structure to
represent our tree.
Linked structure won't work for our purposes.
If we need to access leaf 7 we want to be able to
access it by leaf[7]. Allows random access.
Linked trees are also problematic when saving
to disk because of pointers.
Indexed Binary Tree
Instead of using a linked tree we will use an
array/index based tree.
We will have arrays of nodes, leafs, polygons,
planes, etc.
Allows random access to leaves.
Tree is easy to save to disk.
Can be stored as Lumps or Chunks.
Using pointers can be really messy.
Easy to read back in.
During the compile process:
Arrays will need to grow dynamically.
Leafy BSP Node Structure
struct BSPNode
{
int front; // index in to node, or leaf array
int back;
int planeNum; // index into plane array
};
A negative value for either front or back indicates a leaf.
If front child index is negative - convert this to a valid index
into the array of leaves by taking:
leafIndex = abs(index value+1)
Quake3 Rendering Basics
All quake3 levels are stored as one big BSP
tree.
Quake3 uses Curved surfaces to descibe some
of it’s scene geometry.
Entities (models) are stored as external md3
files. Some models are embedded in the level
(Triangle soup).
md3 files are compiled .ase files from 3ds max.
Embedded models are stored in the BSP.
Quake3 BSP File Structure
BSP files are binary, non human readable files.
Stored as raw data dumped to a file directly from
arrays.
Very easy to read back in.
Disclaimer – Easy to read in using C or C++
Quake3 BSP File Structure (2)
Quake3 files are stored in lumps.
A lump based file format is similar to a chunk based
file format.
There are 18 lumps total in quake3.
Each lump contains a file offset and a lump length.
Data from each lump is stored in a separate array.
Separate arrays for leaves (Leafs), node (Nodes),
polygon (Surfaces), splitting planes (Planes),
vertices (Vertices), etc…
Quake3 Assignment
Base Assignment:
To render a Quake3 level using the BSP/PVS
combination. Then texture/light it.
Many extras are possible.
Primary concern is speed (20 to 100 frames per
second). No more 80,000 polygon models.
We will use the node, leaf, polygon, plane, pvs,
shader, and lightmap lumps.
We need not be concerned will external entities,
except texture maps.
In the code provided all of this data has been
loaded into data structures for you.
Data Structures
Lets look at the data structures that you
will need to understand.
We will then get back to the rendering
process.
Image
Data Structure Details
Nodes array and front/back index values.
Leafs array
Arrangement into polygons (Surfaces)
Back leaves
PVS addressing
cluster == pvs for a particular leaf
Getting bits for a particular other leaf to check
visibility.
Quake3 Rendering
All level rendering is done using the BSP tree
and the PVS.
First, determine which leaf the camera is in by
passing the camera into the tree and traversing
the tree and classifying the camera location until
the camera reaches a leaf.
Once the location of the camera is known the
PVS can be used to determine what other leaves
this leaf can see and those can be rendered.
Quake 3 Point Classification
Quake3 uses a normal and a distance from the
origin to describe a plane.
Previously, we used a point on the plane and a
normal vector to describe a plane.
This allows the use of the plane equation to
classify a point.
Ax + By + Cz – D = 0
If the unit normal vector of the plane is N and the
point to be classified is P then this becomes:
N dot P – D = 0 for a point on the plane – positive
for points in front – negative for points behind.
Traversal and Classification
Leaf Identification
Instead of a flag Quake 3 uses a negative index
value in front or back to signify a leaf.
Test camera against current nodes plane.
If the camera location is in front of the current
node’s plane:
Check front child index:
If positive: this is the index of the next tree
node – continue traversal and classification.
If negative: the next node index actually
indexes the leaf array.
Traversal and Classification (2)
If front child index is negative - convert this to a
valid index into the array of leaves by taking:
leafIndex = abs(index value+1)
If the camera location is behind the current
node's plane:
Check Back child index
If positive: this is the index of the next tree
node – continue traversal and classification.
If negative: the camera is in solid space.
Traversal Termination
Once we’ve hit a negative node index we know
we’ve found the leaf the camera is in.
We now need to use the PVS information for this
leaf to find out which other leaves this leaf can
see.
The PVS is already built and is included into the
BSP data as a chunk so this information can be
easily looked up.
PVS Structure
Since the PVS is loaded as a lump – it is all
stored in a single large byte array.
Although stored as bytes the PVS is actually a bit
array so it is necessary to pull the correct bit out of
a byte.
Zero run length encoding is not used.
The PVS array is actually a 2D array stored in row
major order within a 1D array.
Each row of the PVS array represents the PVS
data for one leaf and is called a cluster.
PVS Clusters
A cluster stores all of the visibility information for
a particular leaf.
Because Quake3 allows back leaves, and since
only front leaves contain valid visibility data, the
number of leaves will differ from number of
clusters.
A back leaf contains a –1 for it’s cluster value.
The collection of all clusters, one for each front
leaf, represents the potential visibility information
for the entire level.
Cluster Location
Since we know which leaf we’re in the cluster variable
in the current leaf object can be used to calculate the
array index in the PVS where this leaf's data is
located.
The size of each cluster is the same and contains
enough bits to represent the visibility of all front leaves.
So
(clusterValueFromCurrentLeaf *
pvs.bytesPerCluster)
gives the index in the PVS array where the current
leaf's visibility information is located.
Visibility Determination
The camera's location leaf is known and the
cluster for that leaf has been located.
Now for each leaf visible from the camera leaf:
render all polygons in that leaf.
To determine whether a particular leaf is visible
we must find the PVS bit for that leaf in the
camera leaf's PVS cluster.
Since back leaves are allowed and do not have
PVS clusters, the leaf array index can't be used
to find the bit.
Instead use the cluster number in the leaf's entry
in the leaf table.
Visibility Determination (2)
Loop through the leaf array checking for front leafs
(those with a positive cluster number).
When a front leaf is found, its cluster number can be
used to find the correct bit to lookup in this cluster of
the PVS.
To find that bit:
Start at the camera leafs cluster offset.
Find the byte containing the bit that represents the leaf
whose visibility is being checked.
Byte index = cluster number / 8.
Then find the bit within that byte representing that leaf.
Check if the byte has that bit set to one or zero.
Visibility Determination (3)
Must bitwise AND the byte you looked up and the bit
for the leaf we are checking
Either:
byte & (1 << (cluster % 8))
Or byte & (1 << (cluster & 7))
If the value is zero: This leaf is not visible do not do
anything with it.
If the value is one: This leaf is visible, draw this leaf.
Visibility Determination (4)
Example
PVS:
[0] 10101010 [1] 01010101 [2] 00110100
Example: cluster number 20 (10100): byte index = 20/8 =
2 (00010) – so bit for 20 is in pvs[2].
Bit mask =1 << (cluster & 7) = 1 << 10100 & 111 =1<<4 =
1000
pvs[2] & 00001000 = 0 so leaf 20 is not visible
Looking up Surfaces/Polygons
In Quake3 the Surface is used to represent one of
three types of 3D objects. It generalizes polygons.
An array, called LeafFaces, is inserted between the
Leafs and Surfaces arrays.
Used to hold indices into the surface array.
Since Quake3 does not split polygons (the same
polygon goes down both front and back lists),
surfaces/polygons might be used in multiple leaves.
All the surfaces of one leaf are not necessarily in
contiguous parts of the Surfaces array. In
LeafSurfaces all the indices of surfaces in one face
are contiguous.
Looking up Surfaces/Polygons (2)
Leaves never access the surface array directly,
but access surfaces through the LeafFaces
array.
The LeafFaces array allows leaves to store a
starting index and a number of surfaces instead
of a bunch of random indices into the surface
array.
Draw Surface?
Now that we know how to look up a
surface/polygon, we need to know if this surface
has been drawn already.
The reason we need this check is because
quake3 does not split polygons and thus the
same polygon/surface may wind up in many
leaves.
One way to do this is to keep a byte or boolean
array - polygonsRendered.
One entry per surface/polygon initialized to false
and set to true when it is drawn. Use of this
polygons polygonsRendered value will determine
whether or not this polygon is to be drawn again.
Draw Surface? (2)
If a byte array is used, the framenumber of the
current frame can be used to indicate that the
polygon has already been drawn.
Need to setup a frame counter.
Before drawing a surface check the
corresponding byte in the polygonsRendered
array:
Use the same index into polygonsRendered as the
surface index you are using.
Assume an index i to be the index into both arrays. If
the ith polygon has already been drawn, the contents
of polygonsRendered[i] will be equal to the current
framecounter value.
Draw Surface? (3)
Check to see if that value is equal to the counter
variable.
polygonsRendered[I] == framecounter
If it is not:
set polygonsRendered to framecounter.
Render surface
If it is:
This surface has already been drawn, so skip it.
Draw Surface? (4)
Once all surfaces have been drawn this
framecounter must be increased.
Framecounter++
This immediately invalidates all values in
polygonsRendered
This way you do not have to loop through
polygonsRendered and set everything to zero.
Drawing a Leaf
Each leaf object contains a firstLeafSurface index
that references the first LeafFaces entry for this
leaf.
Each leaf object also contains a count of the
number of polygons/surfaces in this leaf called
numLeafSurfaces.
Use firstLeafSurface to access LeafFaces array
Go through numLeafSurfaces entries in LeafFaces.
Use those values to access surfaces array.
Test to see If this surface needs to be drawn.
Draw Surface.
Image
Drawing a Surface:
Surface Types
Indicated in the type field of a Surface
Possible values:
PLANAR – planar polygons
Render as Triangle Fans (GL_TRIANGLE_FANS)
Vertex 1
Vertex 2
Vertex 3
Vertex 4 Vertex 5
Vertex 6
Vertex 7
Vertices are rendered in
this order in OpenGL to
form the fan
Drawing a Surface:
Surface Types (2)
Possible values:
TRIANGLE_SOUP – models
Render as separate Triangles (GL_TRIANGLES)
Each 3 vertices form a separate triangle
PATCH – Bezier surface
These are all quadratic patches – although the
Surface does contain a patchWidth and patchHeight
fields so higher order patches are possible.
Vertices and texture vertices should be gathered
into arrays for rendering using glEvalMesh2.
Drawing a Surface:
Patch Control Point Organization
Notes:
The picture contains an
example of how the control
points are numbered and
how they should be read
into an array for rendering.
1. Nine control points are read
in at a time and then
rendered.
2. The numbers next to each
control point are offsets
from the current surface's
firstVert. Adding the offset
to firstVert gives an index
into the Vertices array.
3. If the rows are not read in
backwards as shown then
the wrong faces are culled.
Texturing
Texturing is used for both surface texturing and
for lighting.
Surface texturing is done with standard image
textures – Quake 3 refers to image textures as
Shaders.
The textures for shaders all reside in external .jpg
or .tga files.
All lighting is done with lightmap textures –
Quake 3 refers to these as Lightmaps.
Lightmap texel values are all contained in the level
BSP file itself.
Texturing: Shaders
Shader texture file names are retrieved from the BSP
file by reading the Shader lump. (Quake3BSP.java:
800)
LoadBSP() maintains a temporary array of Shader
objects called pTextures[ ] that facilitates texture setup.
Shader file names do not have extensions in the BSP file
– those are added by FindTextureExtension ().
OpenGL texture setup is done by the CreateTexture()
method (pixel reading, 1st
texture binding and pixel
reading) and the set of texture id's is stored in the
textures array.
Note that gluBuild2DMipMaps() will ensure that texture
dimensions are always powers of 2 as OpenGL requires.
Texturing: Shader settings
Recommended OpenGL shader texture parameter
settings:
min filter – GL_LINEAR_MIPMAP_NEAREST
mag filter – GL_LINEAR_MIPMAP_LINEAR
shader textures should be set up with mipmaps.
Retrieval of other needed parameters from the
Texture object (tex):
internal and external pixel formats:
tex.getGLFormat().
image height: tex.getImageHeight()
image width: tex.getImageWidth()
reference to pixels: tex.getTextureBuffer().
Texturing: Lightmaps
Lightmap textures are read from the BSP file by reading
the Lightmap lump. (Quake3BSP.java: ~820)
LoadBSP() maintains a temporary array of Lightmap
objects called pLightMaps[ ] that facilitates lightmap
texture setup.
The lightmap constructor actually reads the lightmap
texels into the Lightmap member imageBits [ ].
OpenGL lightmap texture setup is done by the
CreateLightmapTexture() (Quake3BSP.java: 823) method
(including 1st
texture binding) and the set of texture id's is
stored in the lightmaps [ ] array.
If the lightMapNum in the Surface is -1 – that surface has
no lightmap
Texturing: Lightmap settings
Recommended OpenGL lightmap texture parameter
settings:
min filter – GL_LINEAR_MIPMAP_LINEAR
mag filter – GL_LINEAR
lightmap textures should also be set up with mipmaps.
Other needed parameters :
internal and external pixel formats: GL_RGB.
image height: 128
image width: 128
reference to pixels: loaded when the lightmap lump is
read and passed to CreateLightmapTexture as
pImageBits.
Lightmap textures should be applied in the
GL_MODULATE mode.
Note about lightmaps
There are many lightmaps stored within a
lightmap texture.
The textures are all 128 by 128
Lightmaps are typically 16 by 16
So, texture coordinates and lightmap
coordinates may be very different for a surface.
Multi-Texturing
First bind texture map to texture unit zero
gl.glActiveTexture(gl.GL_TEXTURE0);
Then set the shader texture by retrieving the textures
array index given by the shaderNum value in the surface
object.
Then bind lightmap to texture unit one
gl.glActiveTexture(gl.GL_TEXTURE1);
Then set the lightmap texture by retrieving the lightmaps
array index given by the lightmapNum value in the
surface object.
Multi-Texturing:
Texture coordinates
Texture coordinates must be set separately for
each texture unit
gl.glMultiTexCoord(gl.GL_TEXTURE0, u, v);
gl.glMultiTexCoord(gl.GL_TEXTURE1, u, v);
Values for texture coordinates are contained in the
Vertex object as texCoords and lightmapCoords.
Questions???

More Related Content

What's hot

Optimizing the Graphics Pipeline with Compute, GDC 2016
Optimizing the Graphics Pipeline with Compute, GDC 2016Optimizing the Graphics Pipeline with Compute, GDC 2016
Optimizing the Graphics Pipeline with Compute, GDC 2016Graham Wihlidal
 
Crysis Next-Gen Effects (GDC 2008)
Crysis Next-Gen Effects (GDC 2008)Crysis Next-Gen Effects (GDC 2008)
Crysis Next-Gen Effects (GDC 2008)Tiago Sousa
 
Advanced Scenegraph Rendering Pipeline
Advanced Scenegraph Rendering PipelineAdvanced Scenegraph Rendering Pipeline
Advanced Scenegraph Rendering PipelineNarann29
 
A Bizarre Way to do Real-Time Lighting
A Bizarre Way to do Real-Time LightingA Bizarre Way to do Real-Time Lighting
A Bizarre Way to do Real-Time LightingSteven Tovey
 
Secrets of CryENGINE 3 Graphics Technology
Secrets of CryENGINE 3 Graphics TechnologySecrets of CryENGINE 3 Graphics Technology
Secrets of CryENGINE 3 Graphics TechnologyTiago Sousa
 
Unreal Summit 2016 Seoul Lighting the Planetary World of Project A1
Unreal Summit 2016 Seoul Lighting the Planetary World of Project A1Unreal Summit 2016 Seoul Lighting the Planetary World of Project A1
Unreal Summit 2016 Seoul Lighting the Planetary World of Project A1Ki Hyunwoo
 
Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)
Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)
Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)Johan Andersson
 
Advancements in-tiled-rendering
Advancements in-tiled-renderingAdvancements in-tiled-rendering
Advancements in-tiled-renderingmistercteam
 
Five Rendering Ideas from Battlefield 3 & Need For Speed: The Run
Five Rendering Ideas from Battlefield 3 & Need For Speed: The RunFive Rendering Ideas from Battlefield 3 & Need For Speed: The Run
Five Rendering Ideas from Battlefield 3 & Need For Speed: The RunElectronic Arts / DICE
 
Memory Management with Page Folios
Memory Management with Page FoliosMemory Management with Page Folios
Memory Management with Page FoliosAdrian Huang
 
Vertex Shader Tricks by Bill Bilodeau - AMD at GDC14
Vertex Shader Tricks by Bill Bilodeau - AMD at GDC14Vertex Shader Tricks by Bill Bilodeau - AMD at GDC14
Vertex Shader Tricks by Bill Bilodeau - AMD at GDC14AMD Developer Central
 
Anti-Aliasing Methods in CryENGINE 3
Anti-Aliasing Methods in CryENGINE 3Anti-Aliasing Methods in CryENGINE 3
Anti-Aliasing Methods in CryENGINE 3Tiago Sousa
 
Decima Engine: Visibility in Horizon Zero Dawn
Decima Engine: Visibility in Horizon Zero DawnDecima Engine: Visibility in Horizon Zero Dawn
Decima Engine: Visibility in Horizon Zero DawnGuerrilla
 
Frostbite Rendering Architecture and Real-time Procedural Shading & Texturing...
Frostbite Rendering Architecture and Real-time Procedural Shading & Texturing...Frostbite Rendering Architecture and Real-time Procedural Shading & Texturing...
Frostbite Rendering Architecture and Real-time Procedural Shading & Texturing...Johan Andersson
 
Rendering Technologies from Crysis 3 (GDC 2013)
Rendering Technologies from Crysis 3 (GDC 2013)Rendering Technologies from Crysis 3 (GDC 2013)
Rendering Technologies from Crysis 3 (GDC 2013)Tiago Sousa
 
Introduction to Bidirectional Path Tracing (BDPT) & Implementation using Open...
Introduction to Bidirectional Path Tracing (BDPT) & Implementation using Open...Introduction to Bidirectional Path Tracing (BDPT) & Implementation using Open...
Introduction to Bidirectional Path Tracing (BDPT) & Implementation using Open...Takahiro Harada
 
Decompressed vmlinux: linux kernel initialization from page table configurati...
Decompressed vmlinux: linux kernel initialization from page table configurati...Decompressed vmlinux: linux kernel initialization from page table configurati...
Decompressed vmlinux: linux kernel initialization from page table configurati...Adrian Huang
 
The Rendering Technology of Killzone 2
The Rendering Technology of Killzone 2The Rendering Technology of Killzone 2
The Rendering Technology of Killzone 2Guerrilla
 

What's hot (20)

Optimizing the Graphics Pipeline with Compute, GDC 2016
Optimizing the Graphics Pipeline with Compute, GDC 2016Optimizing the Graphics Pipeline with Compute, GDC 2016
Optimizing the Graphics Pipeline with Compute, GDC 2016
 
Crysis Next-Gen Effects (GDC 2008)
Crysis Next-Gen Effects (GDC 2008)Crysis Next-Gen Effects (GDC 2008)
Crysis Next-Gen Effects (GDC 2008)
 
Advanced Scenegraph Rendering Pipeline
Advanced Scenegraph Rendering PipelineAdvanced Scenegraph Rendering Pipeline
Advanced Scenegraph Rendering Pipeline
 
A Bizarre Way to do Real-Time Lighting
A Bizarre Way to do Real-Time LightingA Bizarre Way to do Real-Time Lighting
A Bizarre Way to do Real-Time Lighting
 
Secrets of CryENGINE 3 Graphics Technology
Secrets of CryENGINE 3 Graphics TechnologySecrets of CryENGINE 3 Graphics Technology
Secrets of CryENGINE 3 Graphics Technology
 
Unreal Summit 2016 Seoul Lighting the Planetary World of Project A1
Unreal Summit 2016 Seoul Lighting the Planetary World of Project A1Unreal Summit 2016 Seoul Lighting the Planetary World of Project A1
Unreal Summit 2016 Seoul Lighting the Planetary World of Project A1
 
Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)
Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)
Terrain Rendering in Frostbite using Procedural Shader Splatting (Siggraph 2007)
 
Advancements in-tiled-rendering
Advancements in-tiled-renderingAdvancements in-tiled-rendering
Advancements in-tiled-rendering
 
Five Rendering Ideas from Battlefield 3 & Need For Speed: The Run
Five Rendering Ideas from Battlefield 3 & Need For Speed: The RunFive Rendering Ideas from Battlefield 3 & Need For Speed: The Run
Five Rendering Ideas from Battlefield 3 & Need For Speed: The Run
 
Memory Management with Page Folios
Memory Management with Page FoliosMemory Management with Page Folios
Memory Management with Page Folios
 
Vertex Shader Tricks by Bill Bilodeau - AMD at GDC14
Vertex Shader Tricks by Bill Bilodeau - AMD at GDC14Vertex Shader Tricks by Bill Bilodeau - AMD at GDC14
Vertex Shader Tricks by Bill Bilodeau - AMD at GDC14
 
Anti-Aliasing Methods in CryENGINE 3
Anti-Aliasing Methods in CryENGINE 3Anti-Aliasing Methods in CryENGINE 3
Anti-Aliasing Methods in CryENGINE 3
 
Decima Engine: Visibility in Horizon Zero Dawn
Decima Engine: Visibility in Horizon Zero DawnDecima Engine: Visibility in Horizon Zero Dawn
Decima Engine: Visibility in Horizon Zero Dawn
 
Frostbite Rendering Architecture and Real-time Procedural Shading & Texturing...
Frostbite Rendering Architecture and Real-time Procedural Shading & Texturing...Frostbite Rendering Architecture and Real-time Procedural Shading & Texturing...
Frostbite Rendering Architecture and Real-time Procedural Shading & Texturing...
 
Frostbite on Mobile
Frostbite on MobileFrostbite on Mobile
Frostbite on Mobile
 
DirectX 11 Rendering in Battlefield 3
DirectX 11 Rendering in Battlefield 3DirectX 11 Rendering in Battlefield 3
DirectX 11 Rendering in Battlefield 3
 
Rendering Technologies from Crysis 3 (GDC 2013)
Rendering Technologies from Crysis 3 (GDC 2013)Rendering Technologies from Crysis 3 (GDC 2013)
Rendering Technologies from Crysis 3 (GDC 2013)
 
Introduction to Bidirectional Path Tracing (BDPT) & Implementation using Open...
Introduction to Bidirectional Path Tracing (BDPT) & Implementation using Open...Introduction to Bidirectional Path Tracing (BDPT) & Implementation using Open...
Introduction to Bidirectional Path Tracing (BDPT) & Implementation using Open...
 
Decompressed vmlinux: linux kernel initialization from page table configurati...
Decompressed vmlinux: linux kernel initialization from page table configurati...Decompressed vmlinux: linux kernel initialization from page table configurati...
Decompressed vmlinux: linux kernel initialization from page table configurati...
 
The Rendering Technology of Killzone 2
The Rendering Technology of Killzone 2The Rendering Technology of Killzone 2
The Rendering Technology of Killzone 2
 

Similar to Intro to Quake3 rendering techniques including BSP, PVS, textures, and lightmapping

Terrain AnalysisBackgroundAircraft frequently rely on terrain el.pdf
Terrain AnalysisBackgroundAircraft frequently rely on terrain el.pdfTerrain AnalysisBackgroundAircraft frequently rely on terrain el.pdf
Terrain AnalysisBackgroundAircraft frequently rely on terrain el.pdffeetshoemart
 
CEECNE 210—Statics SSEBE Mechanics Group Arizona State Un.docx
CEECNE 210—Statics SSEBE Mechanics Group Arizona State Un.docxCEECNE 210—Statics SSEBE Mechanics Group Arizona State Un.docx
CEECNE 210—Statics SSEBE Mechanics Group Arizona State Un.docxcravennichole326
 
for sbi so Ds c c++ unix rdbms sql cn os
for sbi so   Ds c c++ unix rdbms sql cn osfor sbi so   Ds c c++ unix rdbms sql cn os
for sbi so Ds c c++ unix rdbms sql cn osalisha230390
 
Program Computing Project 4 builds upon CP3 to develop a program to .docx
Program Computing Project 4 builds upon CP3 to develop a program to .docxProgram Computing Project 4 builds upon CP3 to develop a program to .docx
Program Computing Project 4 builds upon CP3 to develop a program to .docxdessiechisomjj4
 
Data indexing presentation part 2
Data indexing presentation part 2Data indexing presentation part 2
Data indexing presentation part 2Vivek Kantariya
 
Trees in Data Structure
Trees in Data StructureTrees in Data Structure
Trees in Data StructureOm Prakash
 
Ch 1 intriductions
Ch 1 intriductionsCh 1 intriductions
Ch 1 intriductionsirshad17
 
2.3 stem and leaf displays
2.3 stem and leaf displays2.3 stem and leaf displays
2.3 stem and leaf displaysleblance
 
Preparation Data Structures 11 graphs
Preparation Data Structures 11 graphsPreparation Data Structures 11 graphs
Preparation Data Structures 11 graphsAndres Mendez-Vazquez
 
Data Structure Question Bank(2 marks)
Data Structure Question Bank(2 marks)Data Structure Question Bank(2 marks)
Data Structure Question Bank(2 marks)pushpalathakrishnan
 
Trees in data structure
Trees in data structureTrees in data structure
Trees in data structureAnusruti Mitra
 
02 linked list_20160217_jintaekseo
02 linked list_20160217_jintaekseo02 linked list_20160217_jintaekseo
02 linked list_20160217_jintaekseoJinTaek Seo
 
Data Mining: Cluster Analysis
Data Mining: Cluster AnalysisData Mining: Cluster Analysis
Data Mining: Cluster AnalysisSuman Mia
 
An Optimal Approach For Knowledge Protection In Structured Frequent Patterns
An Optimal Approach For Knowledge Protection In Structured Frequent PatternsAn Optimal Approach For Knowledge Protection In Structured Frequent Patterns
An Optimal Approach For Knowledge Protection In Structured Frequent PatternsWaqas Tariq
 

Similar to Intro to Quake3 rendering techniques including BSP, PVS, textures, and lightmapping (20)

Terrain AnalysisBackgroundAircraft frequently rely on terrain el.pdf
Terrain AnalysisBackgroundAircraft frequently rely on terrain el.pdfTerrain AnalysisBackgroundAircraft frequently rely on terrain el.pdf
Terrain AnalysisBackgroundAircraft frequently rely on terrain el.pdf
 
CEECNE 210—Statics SSEBE Mechanics Group Arizona State Un.docx
CEECNE 210—Statics SSEBE Mechanics Group Arizona State Un.docxCEECNE 210—Statics SSEBE Mechanics Group Arizona State Un.docx
CEECNE 210—Statics SSEBE Mechanics Group Arizona State Un.docx
 
Numpy ndarrays.pdf
Numpy ndarrays.pdfNumpy ndarrays.pdf
Numpy ndarrays.pdf
 
for sbi so Ds c c++ unix rdbms sql cn os
for sbi so   Ds c c++ unix rdbms sql cn osfor sbi so   Ds c c++ unix rdbms sql cn os
for sbi so Ds c c++ unix rdbms sql cn os
 
Program Computing Project 4 builds upon CP3 to develop a program to .docx
Program Computing Project 4 builds upon CP3 to develop a program to .docxProgram Computing Project 4 builds upon CP3 to develop a program to .docx
Program Computing Project 4 builds upon CP3 to develop a program to .docx
 
Data indexing presentation part 2
Data indexing presentation part 2Data indexing presentation part 2
Data indexing presentation part 2
 
Trees in Data Structure
Trees in Data StructureTrees in Data Structure
Trees in Data Structure
 
Data Structure
Data StructureData Structure
Data Structure
 
Ch 1 intriductions
Ch 1 intriductionsCh 1 intriductions
Ch 1 intriductions
 
2.3 stem and leaf displays
2.3 stem and leaf displays2.3 stem and leaf displays
2.3 stem and leaf displays
 
Preparation Data Structures 11 graphs
Preparation Data Structures 11 graphsPreparation Data Structures 11 graphs
Preparation Data Structures 11 graphs
 
Data Structure Question Bank(2 marks)
Data Structure Question Bank(2 marks)Data Structure Question Bank(2 marks)
Data Structure Question Bank(2 marks)
 
Trees in data structure
Trees in data structureTrees in data structure
Trees in data structure
 
FractalTreeIndex
FractalTreeIndexFractalTreeIndex
FractalTreeIndex
 
Ch12 Tree
Ch12 TreeCh12 Tree
Ch12 Tree
 
02 linked list_20160217_jintaekseo
02 linked list_20160217_jintaekseo02 linked list_20160217_jintaekseo
02 linked list_20160217_jintaekseo
 
Data Mining: Cluster Analysis
Data Mining: Cluster AnalysisData Mining: Cluster Analysis
Data Mining: Cluster Analysis
 
Grids implementation
Grids implementationGrids implementation
Grids implementation
 
An Optimal Approach For Knowledge Protection In Structured Frequent Patterns
An Optimal Approach For Knowledge Protection In Structured Frequent PatternsAn Optimal Approach For Knowledge Protection In Structured Frequent Patterns
An Optimal Approach For Knowledge Protection In Structured Frequent Patterns
 
PAM.ppt
PAM.pptPAM.ppt
PAM.ppt
 

Intro to Quake3 rendering techniques including BSP, PVS, textures, and lightmapping

  • 1. Quake3 Rendering Engine Intro to Quake3 rendering techniques including BSP, PVS, textures, and lightmapping Modified from an original presentation prepared by Jason Calvert, 2003.
  • 2. Problem For our visibility system each leaf will know which other leafs they can see. Up until now we’ve used a linked structure to represent our tree. Linked structure won't work for our purposes. If we need to access leaf 7 we want to be able to access it by leaf[7]. Allows random access. Linked trees are also problematic when saving to disk because of pointers.
  • 3. Indexed Binary Tree Instead of using a linked tree we will use an array/index based tree. We will have arrays of nodes, leafs, polygons, planes, etc. Allows random access to leaves. Tree is easy to save to disk. Can be stored as Lumps or Chunks. Using pointers can be really messy. Easy to read back in. During the compile process: Arrays will need to grow dynamically.
  • 4. Leafy BSP Node Structure struct BSPNode { int front; // index in to node, or leaf array int back; int planeNum; // index into plane array }; A negative value for either front or back indicates a leaf. If front child index is negative - convert this to a valid index into the array of leaves by taking: leafIndex = abs(index value+1)
  • 5. Quake3 Rendering Basics All quake3 levels are stored as one big BSP tree. Quake3 uses Curved surfaces to descibe some of it’s scene geometry. Entities (models) are stored as external md3 files. Some models are embedded in the level (Triangle soup). md3 files are compiled .ase files from 3ds max. Embedded models are stored in the BSP.
  • 6. Quake3 BSP File Structure BSP files are binary, non human readable files. Stored as raw data dumped to a file directly from arrays. Very easy to read back in. Disclaimer – Easy to read in using C or C++
  • 7. Quake3 BSP File Structure (2) Quake3 files are stored in lumps. A lump based file format is similar to a chunk based file format. There are 18 lumps total in quake3. Each lump contains a file offset and a lump length. Data from each lump is stored in a separate array. Separate arrays for leaves (Leafs), node (Nodes), polygon (Surfaces), splitting planes (Planes), vertices (Vertices), etc…
  • 8. Quake3 Assignment Base Assignment: To render a Quake3 level using the BSP/PVS combination. Then texture/light it. Many extras are possible. Primary concern is speed (20 to 100 frames per second). No more 80,000 polygon models. We will use the node, leaf, polygon, plane, pvs, shader, and lightmap lumps. We need not be concerned will external entities, except texture maps. In the code provided all of this data has been loaded into data structures for you.
  • 9. Data Structures Lets look at the data structures that you will need to understand. We will then get back to the rendering process.
  • 10. Image
  • 11. Data Structure Details Nodes array and front/back index values. Leafs array Arrangement into polygons (Surfaces) Back leaves PVS addressing cluster == pvs for a particular leaf Getting bits for a particular other leaf to check visibility.
  • 12. Quake3 Rendering All level rendering is done using the BSP tree and the PVS. First, determine which leaf the camera is in by passing the camera into the tree and traversing the tree and classifying the camera location until the camera reaches a leaf. Once the location of the camera is known the PVS can be used to determine what other leaves this leaf can see and those can be rendered.
  • 13. Quake 3 Point Classification Quake3 uses a normal and a distance from the origin to describe a plane. Previously, we used a point on the plane and a normal vector to describe a plane. This allows the use of the plane equation to classify a point. Ax + By + Cz – D = 0 If the unit normal vector of the plane is N and the point to be classified is P then this becomes: N dot P – D = 0 for a point on the plane – positive for points in front – negative for points behind.
  • 14. Traversal and Classification Leaf Identification Instead of a flag Quake 3 uses a negative index value in front or back to signify a leaf. Test camera against current nodes plane. If the camera location is in front of the current node’s plane: Check front child index: If positive: this is the index of the next tree node – continue traversal and classification. If negative: the next node index actually indexes the leaf array.
  • 15. Traversal and Classification (2) If front child index is negative - convert this to a valid index into the array of leaves by taking: leafIndex = abs(index value+1) If the camera location is behind the current node's plane: Check Back child index If positive: this is the index of the next tree node – continue traversal and classification. If negative: the camera is in solid space.
  • 16. Traversal Termination Once we’ve hit a negative node index we know we’ve found the leaf the camera is in. We now need to use the PVS information for this leaf to find out which other leaves this leaf can see. The PVS is already built and is included into the BSP data as a chunk so this information can be easily looked up.
  • 17. PVS Structure Since the PVS is loaded as a lump – it is all stored in a single large byte array. Although stored as bytes the PVS is actually a bit array so it is necessary to pull the correct bit out of a byte. Zero run length encoding is not used. The PVS array is actually a 2D array stored in row major order within a 1D array. Each row of the PVS array represents the PVS data for one leaf and is called a cluster.
  • 18. PVS Clusters A cluster stores all of the visibility information for a particular leaf. Because Quake3 allows back leaves, and since only front leaves contain valid visibility data, the number of leaves will differ from number of clusters. A back leaf contains a –1 for it’s cluster value. The collection of all clusters, one for each front leaf, represents the potential visibility information for the entire level.
  • 19. Cluster Location Since we know which leaf we’re in the cluster variable in the current leaf object can be used to calculate the array index in the PVS where this leaf's data is located. The size of each cluster is the same and contains enough bits to represent the visibility of all front leaves. So (clusterValueFromCurrentLeaf * pvs.bytesPerCluster) gives the index in the PVS array where the current leaf's visibility information is located.
  • 20. Visibility Determination The camera's location leaf is known and the cluster for that leaf has been located. Now for each leaf visible from the camera leaf: render all polygons in that leaf. To determine whether a particular leaf is visible we must find the PVS bit for that leaf in the camera leaf's PVS cluster. Since back leaves are allowed and do not have PVS clusters, the leaf array index can't be used to find the bit. Instead use the cluster number in the leaf's entry in the leaf table.
  • 21. Visibility Determination (2) Loop through the leaf array checking for front leafs (those with a positive cluster number). When a front leaf is found, its cluster number can be used to find the correct bit to lookup in this cluster of the PVS. To find that bit: Start at the camera leafs cluster offset. Find the byte containing the bit that represents the leaf whose visibility is being checked. Byte index = cluster number / 8. Then find the bit within that byte representing that leaf. Check if the byte has that bit set to one or zero.
  • 22. Visibility Determination (3) Must bitwise AND the byte you looked up and the bit for the leaf we are checking Either: byte & (1 << (cluster % 8)) Or byte & (1 << (cluster & 7)) If the value is zero: This leaf is not visible do not do anything with it. If the value is one: This leaf is visible, draw this leaf.
  • 23. Visibility Determination (4) Example PVS: [0] 10101010 [1] 01010101 [2] 00110100 Example: cluster number 20 (10100): byte index = 20/8 = 2 (00010) – so bit for 20 is in pvs[2]. Bit mask =1 << (cluster & 7) = 1 << 10100 & 111 =1<<4 = 1000 pvs[2] & 00001000 = 0 so leaf 20 is not visible
  • 24. Looking up Surfaces/Polygons In Quake3 the Surface is used to represent one of three types of 3D objects. It generalizes polygons. An array, called LeafFaces, is inserted between the Leafs and Surfaces arrays. Used to hold indices into the surface array. Since Quake3 does not split polygons (the same polygon goes down both front and back lists), surfaces/polygons might be used in multiple leaves. All the surfaces of one leaf are not necessarily in contiguous parts of the Surfaces array. In LeafSurfaces all the indices of surfaces in one face are contiguous.
  • 25. Looking up Surfaces/Polygons (2) Leaves never access the surface array directly, but access surfaces through the LeafFaces array. The LeafFaces array allows leaves to store a starting index and a number of surfaces instead of a bunch of random indices into the surface array.
  • 26. Draw Surface? Now that we know how to look up a surface/polygon, we need to know if this surface has been drawn already. The reason we need this check is because quake3 does not split polygons and thus the same polygon/surface may wind up in many leaves. One way to do this is to keep a byte or boolean array - polygonsRendered. One entry per surface/polygon initialized to false and set to true when it is drawn. Use of this polygons polygonsRendered value will determine whether or not this polygon is to be drawn again.
  • 27. Draw Surface? (2) If a byte array is used, the framenumber of the current frame can be used to indicate that the polygon has already been drawn. Need to setup a frame counter. Before drawing a surface check the corresponding byte in the polygonsRendered array: Use the same index into polygonsRendered as the surface index you are using. Assume an index i to be the index into both arrays. If the ith polygon has already been drawn, the contents of polygonsRendered[i] will be equal to the current framecounter value.
  • 28. Draw Surface? (3) Check to see if that value is equal to the counter variable. polygonsRendered[I] == framecounter If it is not: set polygonsRendered to framecounter. Render surface If it is: This surface has already been drawn, so skip it.
  • 29. Draw Surface? (4) Once all surfaces have been drawn this framecounter must be increased. Framecounter++ This immediately invalidates all values in polygonsRendered This way you do not have to loop through polygonsRendered and set everything to zero.
  • 30. Drawing a Leaf Each leaf object contains a firstLeafSurface index that references the first LeafFaces entry for this leaf. Each leaf object also contains a count of the number of polygons/surfaces in this leaf called numLeafSurfaces. Use firstLeafSurface to access LeafFaces array Go through numLeafSurfaces entries in LeafFaces. Use those values to access surfaces array. Test to see If this surface needs to be drawn. Draw Surface.
  • 31. Image
  • 32. Drawing a Surface: Surface Types Indicated in the type field of a Surface Possible values: PLANAR – planar polygons Render as Triangle Fans (GL_TRIANGLE_FANS) Vertex 1 Vertex 2 Vertex 3 Vertex 4 Vertex 5 Vertex 6 Vertex 7 Vertices are rendered in this order in OpenGL to form the fan
  • 33. Drawing a Surface: Surface Types (2) Possible values: TRIANGLE_SOUP – models Render as separate Triangles (GL_TRIANGLES) Each 3 vertices form a separate triangle PATCH – Bezier surface These are all quadratic patches – although the Surface does contain a patchWidth and patchHeight fields so higher order patches are possible. Vertices and texture vertices should be gathered into arrays for rendering using glEvalMesh2.
  • 34. Drawing a Surface: Patch Control Point Organization Notes: The picture contains an example of how the control points are numbered and how they should be read into an array for rendering. 1. Nine control points are read in at a time and then rendered. 2. The numbers next to each control point are offsets from the current surface's firstVert. Adding the offset to firstVert gives an index into the Vertices array. 3. If the rows are not read in backwards as shown then the wrong faces are culled.
  • 35. Texturing Texturing is used for both surface texturing and for lighting. Surface texturing is done with standard image textures – Quake 3 refers to image textures as Shaders. The textures for shaders all reside in external .jpg or .tga files. All lighting is done with lightmap textures – Quake 3 refers to these as Lightmaps. Lightmap texel values are all contained in the level BSP file itself.
  • 36. Texturing: Shaders Shader texture file names are retrieved from the BSP file by reading the Shader lump. (Quake3BSP.java: 800) LoadBSP() maintains a temporary array of Shader objects called pTextures[ ] that facilitates texture setup. Shader file names do not have extensions in the BSP file – those are added by FindTextureExtension (). OpenGL texture setup is done by the CreateTexture() method (pixel reading, 1st texture binding and pixel reading) and the set of texture id's is stored in the textures array. Note that gluBuild2DMipMaps() will ensure that texture dimensions are always powers of 2 as OpenGL requires.
  • 37. Texturing: Shader settings Recommended OpenGL shader texture parameter settings: min filter – GL_LINEAR_MIPMAP_NEAREST mag filter – GL_LINEAR_MIPMAP_LINEAR shader textures should be set up with mipmaps. Retrieval of other needed parameters from the Texture object (tex): internal and external pixel formats: tex.getGLFormat(). image height: tex.getImageHeight() image width: tex.getImageWidth() reference to pixels: tex.getTextureBuffer().
  • 38. Texturing: Lightmaps Lightmap textures are read from the BSP file by reading the Lightmap lump. (Quake3BSP.java: ~820) LoadBSP() maintains a temporary array of Lightmap objects called pLightMaps[ ] that facilitates lightmap texture setup. The lightmap constructor actually reads the lightmap texels into the Lightmap member imageBits [ ]. OpenGL lightmap texture setup is done by the CreateLightmapTexture() (Quake3BSP.java: 823) method (including 1st texture binding) and the set of texture id's is stored in the lightmaps [ ] array. If the lightMapNum in the Surface is -1 – that surface has no lightmap
  • 39. Texturing: Lightmap settings Recommended OpenGL lightmap texture parameter settings: min filter – GL_LINEAR_MIPMAP_LINEAR mag filter – GL_LINEAR lightmap textures should also be set up with mipmaps. Other needed parameters : internal and external pixel formats: GL_RGB. image height: 128 image width: 128 reference to pixels: loaded when the lightmap lump is read and passed to CreateLightmapTexture as pImageBits. Lightmap textures should be applied in the GL_MODULATE mode.
  • 40. Note about lightmaps There are many lightmaps stored within a lightmap texture. The textures are all 128 by 128 Lightmaps are typically 16 by 16 So, texture coordinates and lightmap coordinates may be very different for a surface.
  • 41. Multi-Texturing First bind texture map to texture unit zero gl.glActiveTexture(gl.GL_TEXTURE0); Then set the shader texture by retrieving the textures array index given by the shaderNum value in the surface object. Then bind lightmap to texture unit one gl.glActiveTexture(gl.GL_TEXTURE1); Then set the lightmap texture by retrieving the lightmaps array index given by the lightmapNum value in the surface object.
  • 42. Multi-Texturing: Texture coordinates Texture coordinates must be set separately for each texture unit gl.glMultiTexCoord(gl.GL_TEXTURE0, u, v); gl.glMultiTexCoord(gl.GL_TEXTURE1, u, v); Values for texture coordinates are contained in the Vertex object as texCoords and lightmapCoords.