Jump to content
  • Advertisement
Sign in to follow this  

Portal Rendering Loop

This topic is 2930 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 have read some articles about portal rendering - unfortunately, it seems there are only a few on the web.

From what i have understand i have build some code.

It would be nice if someone could review my main loop for object culling / rendering.

Short description of the code: I render the current sector (the one the viewpos is in), then iterate over each portal, clip them against the current view frustum and build a reduced view frustum from those. Finally, i render the adjacent sector, which should recursively render all sectors until all visible ones are drawn.

Is this procedure correct or are there some flaws in my code?

Thanks in adavance,

void ZSector::render(const CVector3 &currPos, CFrustum &viewFrustum)
if (_tagged) return;

_tagged = true;


// Render the current sector

std::vector<CPolygon*>::iterator pPoly = _polyList.begin();

for ( ; pPoly != _polyList.end(); ++pPoly)

for (std::vector<ZPortal*>::iterator p = _portalList.begin();
p != _portalList.end(); ++p)
CPolygon clippedPortal = (*p)->_poly;

// If the portal is not within the current view frustum, ignore it

if (!viewFrustum.poly_visible(clippedPortal)) continue;

// Clip the portal against each plane of our view frustum

for (int plane = 0; plane < viewFrustum._nPlanes; plane++)
CPolygon result[2];

if (SplitPolygon(clippedPortal, viewFrustum._planes[plane], result))
clippedPortal = result[0];

// Check for invalid portals

if (clippedPortal._nVerts < 3) continue;

// Remember the near and far plane

CPlane farPlane = viewFrustum._planes[viewFrustum._nPlanes-2];
CPlane nearPlane = viewFrustum._planes[viewFrustum._nPlanes-1];

viewFrustum._nPlanes = 0;

// Build the reduced view frustum from the
// new portal

for (int i = 0; i < clippedPortal._nVerts; i++)
CVertex v1 = clippedPortal._verts;
CVertex v2 = clippedPortal._verts[i+1];

if (i == clippedPortal._nVerts - 1)
v2 = clippedPortal._verts[0];

CVector3 sideNormal;

sideNormal.Cross(v2, v1);

viewFrustum._planes._normal = sideNormal;
viewFrustum._planes._d = 0.0;


// Reset the near and far plane

viewFrustum._planes[viewFrustum._nPlanes++] = farPlane;
viewFrustum._planes[viewFrustum._nPlanes++] = nearPlane;

// Call adjacent sector

if ((*p)->_adjacent)
(*p)->_adjacent->render(currPos, viewFrustum);

Share this post

Link to post
Share on other sites
some notes from my side:

1. _tagged tags the room on first touch, what would happen if several portals would lead to the same room? e.g. if you had several windows/corridors connecting two rooms? you shall probably rather tag your meshes or polys than whole rooms.

2. you render all polys in a room, you shall take advantage of your current portal-frustum and cull what is invisible. (usually I'd recommend not to go one by one poly, but to use index/vertex buffers and draw it all in one go)

3. not sure bout that, but it seems like you're forwarding always the same near/far plane, you shall use the portal plane as your near plane, that way you also don't need to fear an endless recursion (even without tagging), as you continue to push the nearplane forward.

maybe not fully related to your question, but in general it would be of advantage if your code would be self explaining, avoid magic that needs comments, e.g.

if (clippedPortal.IsInvalid()) continue;

CPlane farPlane = viewFrustum._planes[viewFrustum.NEAR];
CPlane nearPlane = viewFrustum._planes[viewFrustum.FAR];

while NEAR/FAR could be enums 0/1 or you add a accessor function to viewFrustum like Near() and Far(), it's not just about readability of that view lines, imagin someone else wants to access the nearplane of your frustum, he'd need to see for some source code that is already doing this magic to figure out how to do it. then you might change your frustum class behaviour and if you don't know someone relies on it, you might break something without knowing it. if you work without magic, it can ease maintaining and readability.

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.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!