Recently I decided to dig into portal renderers and start to build my own, inspired by this excellent write-up of BUILD. This is currently work in progress, no guarantee it will turn into a full game but thought it was interesting enough to share.
I used a lot of stuff from other projects
From Caped Feline Arena
- Player movement
- Floor and sky casting
- Palette functions
From Cab Ride
I also revisited Lodev's raycasting articles, specifically the code to render sprites without fisheye distortion as they behave similarly to the ends of the walls.
- New features including
- Variable height sectors!
- Distance based lighting!
- Large performance gains!
- Island sectors!
- This is all thanks for being a bit smarter about how many walls to cast each ray for
- After flooding portals, the walls of each sector are grouped into subgroups (referred to in BUILD terminology as 'bunches')
- The bunches are ordered near-far (thanks to traversing the portal graph)
- Island sectors get inserted before other bunches an enclosing sector (this would cause glitches with concave sectors, out of scope for now)
- Walls within a bunch are ordered near-far, and projected into screen space, where they are further chopped down, grouped by walls that touch at one end
- Portals take account of differences in sector height - this allows for doorways/overhangs
- A very simple buffer keeps track of which x coordinates have had a wall drawn, to prevent overdraw of walls
- Rays are cast for the walls nearest bunch (from the lowest to highest x coordinate). If a hit is recorded, the 'x buffer' is updated, so no further drawing happens - that coordinate is now occluded
- Palette is set for each vertical slice of wall, based on distance from the camera
- At the moment it relies on casting a ray for every column of the screen to determine which walls to draw
- One wall per column at the moment
- Casting a ray traverses a subset of potentially visible walls
- Potentially visible walls are calculated by traversing the portals in the world structure, starting with the 'sector' the player/camera currently occupies
- World is represented by sectors, which hold references to a set of walls that border the sector
- A portal is a wall shared by two sectors
- Traversing the world tests which walls of a sector are in front of the camera, if any wall is a portal, it is currently discarded and the connected sector is visited, up to a hard limit of 10
- The current sector of the player/camera (or starting sector for rendering) is determined by casting a ray to the left and the number of intersections with walls is counted. Even means outside the sector (and connected sectors are tested), odd means within the sector. A short description of this is found in the 'Inside a concave polygon' of the BUILD write-up
- The world is created when the cart starts and builds a model of how sectors are connected to each other
- tline() is used for floor and sky
- No collision detection currently
- Arrow keys - move around
- X - toggle map view (off by default)
- C/Z - strafe
Next up??? Maybe?
- More performance
- Sector based floor textures
- Collision detection
- / 'Island' sectors for columns
- Basic level editor
@freds72 - not 100% sure yet about different floor and ceiling heights (making all of this up as I go along/read). Next bit I'm reading up on is occlusion arrays which will help with this. I'm expecting I will have to ditch the 'raycaster' bit of this soon as I think it will make this difficult.
re: Convex polgons - not yet. Concave sectors give odd results, I think due to the order of checking a ray colliding with walls.
[Please log in to post a comment]