View Full Version : Portal engine/editor
Well, I had an interesting idea that I will share with you. Rather than cutting the room/cell into many convex pieces especially the wall that shares a portal with the next room/cell, I thought that instead creating a hole this way why not use the stencil buffer and mask off the portal and then render from front to back using the zbuffer?
Now I wonder if anyone tried this already and if yes is there a possibility for pixel inaccuracy occuring so that there will be holes between the portals?
I rather not go through the csg or bsp cutting of the walls although if I did the cutting it would still be done as a preprocess. Besides the convex pieces would have to be triangulated at preprocess anyway.
I'm going to go ahead and code this up anyway just to see if it's at all possible http://www.opengl.org/discussion_boards/ubb/smile.gif Any info would be welcome. Thanks.
While something like that should work, you
would be rendering more than you have to.
You'd have to render EVERYTHING in front of
the viewer to make sure nothing was missed,
which is potentially a lot.
You don't even need the stencil buffer to
mask off the portals, because the Z buffer
will do it all for you anyway.
The reason to use portals, and BSPs or some
other spatial sort within each volume, is so
your engine can more easily (or accurately)
determine what makes sense to try to render,
and what is definitely not visible.
I might not been clear about what I was trying to say so I will explain myself better.
I will make a cube room/cell. I will also make another cube room. Then I will place one room next to (touching but not intersecting) the other room. Imagine now that room A is larger room and room B is a smaller room. In fact the B room is located in the middle of the east wall of room A. Like a hole in a wall but instead you don't see any walls or room B since it's only touching room A and isn't intersecting it.
All wall normals are pointing inwards toward center of the rooms. When standing outside the room looking in the walls are transparent because of back face culling.
So now we have room A that can't see into room B and vice versa. Normally at this point we would cut the wall of room A that is common with one of the walls of room B so that the wall A be separated into 4 face fragments leaving an empty face in the middle where the wall of room B was. Because the adjacent wall of room B is back faced culled we would see into room B but once in room B we couldn't see into room A because that wall of room B is not cut nor thrown out.
I want to avoid cutting wall or room A by faces of room B if I can, so I propose not to cut wall A at all but instead designate the adjoining wall of room B to be a special portal polygon that will not be drawn when in room B and will be used to mask off area of the wall in room A which would otherwise be cut up.
I will impose some relationship on the adjoining walls.
Now the rendering stage. I first locate the room the viewer is stationed in let's say it's room A. I draw everything in room A except the big wall that should lead us to next room B. That wall will be specially drawn using the stencil buffer and using the data structure I get the adjoining face i.e. the portal polygon to use as a mask.
I draw the big wall of room A but since it's partially masked off by the portal poly I will see into the room B. I then adjust the view frustum to the portal poly and clip the new portals of room B if any and construct new portal polys that will mask off the next walls in room B just like the big wall in room A.
I then draw the contents of room B using zbuffer as not to overdraw the pixels of room A. I will use the frustum to limit the number of cells needed to draw just like in any ordinary portal engine, I guess.
All I'm trying to do is not cut up the walls in order to create holes in them. I fail to see how the zbuffer could help in this situation. I thought back faced polys (in case of the portal wall of room B) are rejected before doing z compares on them. I will use hardware backface culling so transforming the portal poly will be necessary.
I don't know if I can explain myself better but I will try if you ask for it. This could turn into an interesting discussion so if anyone wants to continue please post your thoughts here. Thanks.
12-11-2000, 04:18 AM
Not all cards support stencil buffers. They should be used for optional effects, not the core rendering of the engine. But just because you break up a wall of Room A doesn't mean you have to split the room into several smaller sectors. One way to do it is to have a variable, IsBroken or whatever, for each face of each room. If a face is broken up, IsBroken = true, and you have a list of triangles that you render instead of that one whole face. So, the wall you described would be rendered using 8 triangles instead of two, but Room A is still just one sector. This is more efficient than messing with stencil buffers.
[This message has been edited by CGameProgrammer (edited 12-11-2000).]
I'm sure when my engine will be done everyone will be using NV50 and 5Ghz cpu http://www.opengl.org/discussion_boards/ubb/smile.gif
Right now some Ati and 3dfx voodoo 3000 and below don't use stencil buffers but all newer cards do, even my old permedia2 has a one bit/one plane stencil buffer.
So the question right now borders on efficiency. It can be argued that using a stencil buffer would be slower than the actual splitting and I don't know about that because I haven't coded it yet. You can also argue that splitting walls leads to inefficient design and creates too many triangles.
I think the real question here is "Does the use of the stencil buffer lead to cracks between the portals?" I will soon know since I'm coding it right now. I just wanted to know if anyone has done this before and can share his experiences with me.
But just because you break up a wall of Room A doesn't mean you have to split the room into several smaller sectors. One way to do it is to have a variable, IsBroken or whatever, for each face of each room. If a face is broken up, IsBroken = true, and you have a list of triangles that you render instead of that one whole face. So, the wall you described would be rendered using 8 triangles instead of two, but Room A is still just one sector.
Again, I don't think people understand me so I will explain once more http://www.opengl.org/discussion_boards/ubb/wink.gif
I "DO NOT" WANT TO SPLIT THE FACE THAT WILL SHARE PORTAL OF THE ADJACENT ROOM IN ANY WAY IN ANY SHAPE OR FORM.
Now the question comes to mind how will you be able to look into the next room when in fact all the faces in the current room are opaque? Easy, use the wall of the adjacent room as a portal poly and make a stencil mask out of it then render the wall of room A that shares the portal with room B using this mask so when done the entire wall will be drawn except for that masked off section which will now allow you to see into the next room.
Have you heard of using the stencil buffer to do CSG? It's almost the same thing except I keep the cell/room polys as one sector and using portal technigue I will eventually use the frustum culling to limit the processing/drawing of adjacent cells by clipping the future portals with the frustum making the portals smaller and smaller. Each portal will have adjacency graph with the cells that are adjacent with this portal.
Sure I could use a leafy bsp tree to store the cell polygons and perhaps be lucky coming up with an algo that allows me to cut only one wall instead of all the walls in the cell but still this is cutting thus creating many extra polygons that wouldn't needed to be created in the first place if I used the stencil buffer.
If I had a leafy bsp this is how I would proceed:
1)Take one face of room B and use it to cut room A into two 3D cubes.
2)Take the next face of room B create a plane out of it like in step 1 and cut only ONE of the two cubes of room A that were created in step 1. Now we have three 3D cubes of room A. (Please see Genesis3D if you don't understand how this is done.)
3)Take the third face of room B and again cut up the only ONE cube of room A and again and again until we have four cubes of room A leaving a hole in the adjacent wall of room A with room B.
Do you see that this process is lengthy and leads to many cuts. I could also limit this to only cutting of the adjacent wall of room A and not the whole room but I havent' evaluated the algo yet for its stability. So the best we can do is cut up one wall of room A into four pieces(convex) i.e. 8 triangles. Why go through all this when we can mask off only a small portion of the wall i.e. the portal poly and draw the entire wall even not bother to change the texture coordinates at all. You see the advantage? Whew http://www.opengl.org/discussion_boards/ubb/smile.gif What do you guys think?
I suppose that will work. However, you also
have to store, for the "portal" polygons,
which rooms they are portals for (i e for
the B wall in your example, store "A").
Else you'll have the problem that some area
in B connected to C might ALSO show up as a
portal for A.
However, this solution cost you a lot of fill
rate and some host side special casing, and
the only win is not having to split the wall
in A. Perhaps you have great reasons for not
splitting the wall in A, but it seems to me
that the extra poly cost is very low compared
to the fill rate and other issues with the
solution you're suggesting.
Ahhhh http://www.opengl.org/discussion_boards/ubb/smile.gif Finally, someone understands me. Bgl you've raised a very good point which I've been trying to discuss here. Is this stencil technique too slow/inefficient (as compared to bsp) and inaccurate?
With the bsp tree we can quickly draw the cut up faces and do some pvs check to see whether we should render other cells.
With pure portal technique we have to clip portals against frustum which determines our pvs. Cells are already split so drawing speed should be the same for portal based engine as well as bsp engine.
With stencil technique drawing of each wall except the special portal/adjacent wall is the same as in bsp and normal portal engine. Same with the pvs except of the overhead of making the stencil mask and then drawing the wall that's adjacent to the portal wall.
The advantages of stencil technique are:
1)No face splits except for portal polys which will be clipped by frustum planes. So no lengthy bsp type preprocessing.
2)No recomputation of texture coordinates is necessary because the whole wall will be rendered even though we want a hole in the middle, that will be achieved with stencil mask.
3)No CSG editor needed since no intersections will be made. The walls will be touching each other but not penetrating like so:
One wall (the west one) of room B will be portal polygon while all walls of roomA are normal opaque walls.
There could be an automatic or manual portal placement in the editor like so:
8888888888888888| * |
8888888888888888| * |
8888888888888888| * |<--- Portal cell
8888888888888888| * |
The portal cell would tell the editor which two portals are adjacent and more importantly which wall of the two cell should be used as a portal poly. During rendering we draw all walls of cell A based on pvs possibly all walls of cell B, the portal wall is backfaced culled so is visible from cellA after we use the portal mask on the wall of cell A.
Seems to me like I keep going and going http://www.opengl.org/discussion_boards/ubb/smile.gif but for a simple portal engine this could be quite a neat technique. Ofcourse there will be a character/object editor included so that you could populate the cells of your world even could make the cells metal like in RedFaction(???) engine and then do csg only on objects contained in the cell. What I really like about portal engines is the ability to think in abstract form creating cells like c++ classes or objects. We can remove the cell if we want and it would not break rest of the level, so it seems http://www.opengl.org/discussion_boards/ubb/smile.gif Portals seem like a much better way then bsp where the entire world is one static solid. Granted even in portal engine you can't just create cells and place them anywhere since they could intersect existing cells, but perhaps create an elevator cell that goes up and down which could be easily seen and provisions made to leave a vertical room for the elevator to go to all in the editor. Hmmm... Well, I will code this up and see if the stencil technique works or not. If not no biggie http://www.opengl.org/discussion_boards/ubb/smile.gif
[This message has been edited by JD (edited 12-11-2000).]
[This message has been edited by JD (edited 12-11-2000).]
I should have known better than do ascii art http://www.opengl.org/discussion_boards/ubb/smile.gif Anyway, just move the asterics(*) to the right to line them up and you'll get the picture, I hope http://www.opengl.org/discussion_boards/ubb/wink.gif
You still have the problem of having to
know which room you are rendering for, and
which portals connect to which rooms, and
only stencil out the appropriate connections.
If B's east wall was a portal into the C
room, you wouldn't want that to be masked out
when rendering A.
One nice thing about BSP is that you can
use it for collission detection and physics
much easier than many other methods. I don't
see how you could do that with your method,
so you'll probably need to keep some state
separately to implement physics.
Yeah, you're probably right. I'm dead tired today to do any more thinking. All this time I've been messing with the editor code trying to create cubes like the wildtangent's one you know, draw the face in one 2D window then for height go to other 2D window and record the height, then construct the faces and plane project faces onto 2D views and draw into 3D view while trying to figure out a way to make this fast.
I will return to this stencil thingy once I have the editor producing cells and portals. In fact I will make several various bsp engines and plug them into the editor to see which is faster, should be fun. Thanks for your info and interest.
Powered by vBulletin® Version 4.2.3 Copyright © 2017 vBulletin Solutions, Inc. All rights reserved.