Saturday, June 23, 2007

Hardware occlusion culling, Art path

Pics out of the way first this time.

http://www.blackrayne.net/27/fs_shot0015.jpg

Shot of my current test map. Just wanted to get the tri counts up to test the room system out. This is part of a map containing two towers like this.

http://www.blackrayne.net/27/maxscene_watertest.png

The red geometry is the visible scene mesh, the purple and green cylenders are "room hulls" for visiblity culling. 6 rooms total.

Work continues on updating quake3 into a more modern engine...


Theres no water

After getting the fragment shader code and new T&L style surface management code in, I wanted to see about going and doing HalfLife 2 style water. The basic premise for reflective/refractive water is you sample two specially crafted renders of your scene into a pixel shader, with the lions share of hard work being the actual setup and render of the two extra scene renders per frame you're required to do.

First you need to mask off and draw just whatever is going on underneath the water for the (faked) underwater refraction drawing.

Then you have to draw a mirror view of the scene for the waters reflection plane with the underwater stuff masked out.

I got as far as producing a test map for this with an encapsulating brush defining the boundary between the two areas (under water and not) when I realised that the work I was putting into this one special water case was largely following work I could have been doing to create a new visibility determination scheme...

New vis was already on the Big Wish List of things we needed to see about; Q3's PVS system looks great on paper, but in practice and with q3map2, you're really praying for things to work right once you're bringing out the hint brushes to get a larger map performing well.

So thats what I've spent my spare time for the last two weeks reinventing, and only just now can get back to seeing about doing something about that water.

New Vis

Anyway, regarding the new vis; The system I came up with has made the mappers happy - Mappers build their map out of an arbitary soup of meshes with no consideration for sealing or portals, and then mark in how the vis is supposed to work.

The mapper breaks the level down into cullable "rooms" using a closed mesh to zone off what triangles belong to the room. The engine then uses a combination of AABB checks, logic, and hardware occlusion tests to build the scene up at render time.

http://www.blackrayne.net/27/vis_system.GIF

This mspaint job was done up when I was first thinking about how to do this. It's still mostly accurate except I quickly scrapped the idea of bounding rooms with brshes and went with meshes instead.

The room system has a couple of rules:
1) Rooms can nest within other rooms (encouraged!)
2) Rooms can't intersect other rooms ( so A can sit within B, but A can't sit half in, half out of B)
3) Room Meshes have to be closed and 2 manifold.

I'm very proud of this scheme. I know I'm late to the party with hardware occlusion tests for vis, but it took a bit of thinking for a way to come up with a method that wasn't just another portal placement nightmare.

Building zones is a little bit of work for the mapper but the payoff is huge - it's ALL they have to do, no portals or other hinting.. so it completely thumps portal schemes in terms of set up; mappers don't have to worry about sealing every orifce of their room with portals and antiportals, it's just "voodoo magic" once the rooms are marked in.

Unlike portals-only, it also adapts extremely well to doing large outdoors areas like terrain with buildings on it, because
A) everything in the scene blocks vis for near-free (plants, hills, trees, buildings, etc)
B) rooms can be used around open geomety, like a statue on a hillside can be placed into a room, even though it's mostly air.
C) the mapper doesn't have to provide portals to fill in all the windows and doors on buildings.. the per pixel occlusion takes care of it provided theres a room inside to be culled out.

So in terms of rendering things are still pretty similar to a portal engine. The scene graph is traversed from front to back, starting in the current room and working further away. Where it differs is each room is hardware occlusion tested against whats already been rendered, and it ( and its children ) can be culled. In a metaphorical sense, every drawn/closed pixel is an antiportal, and every open pixel is a portal.

In practice it means that you can break a map like casa up into about a dozen rooms and get far more accurate and robust culling then q3 ever managed. Things like L shaped hallways and other "Pray it works" setups just work implicity now.

Erk late, will probably edit this again later.

Saturday, June 2, 2007

First Entry

(Images of my current project, it was supposed to go down the bottom but the image editor for this blog is beyond my mortal skills )

And some cubemap based specular. Cubemaps pretty craptastic but it sure makes things look bumpy and wet. Programmer art ftw.

Comparison shot of No Bump Vs Bump, q3/urban terror 4.0 :)






Radiosity Lighting on its own.

Plain old bumpmapping * Diffuse

Frozen Sand and HL2

The team has been musing around the idea of starting another project, preferably something nice and commercial.
We prototyped out a fairly advanced (gameplay wise) FPS project in way back 2004.. but great code won't even raise an eyebrow if your game looks like its from the q3 era art wise...

It was easier for us to attract the coding and mapping talent we needed to put together a prototype then gathering the concept/chararacter/animators you need to make something particularly flashy... a fps project breaks down to roughly 20% code, 80% art so I don't really blame the publishers for wanting the art-talent there up front.
Gathering a group of artists capable of producing assets at the level required is nigh on impossible for a $0 team mostly known for modding q3... So looking on jealously at the art-talent the half-life 2 mod teams were able to attract, we decided that perhaps Hl2 wouldn't be a bad platform to work (and pimp) from. Start a mod, gather the artists who want to play with the shiney toys, eventually nudge a (much less ambitious, but much prettier) demo together.
Anyways.. the point of all that is that I spent about 4 days inside of the halflife 2 mod SDK.. (specifically hl2:dm) and I wasn't terribly impressed with what I found. I ported the urban terror player physics over to hl2:dm so we could all jump in and have a multiplayer game comparing things like the hit detection and lag compensation to what we have under q3.. and frankly q3 won. Hl2's renderer beats q3 silly, obviously, but theres alot to be said for q3's network model.
Hl2's entitys vibrate and shakes around like a washing machine at times, and not to be too blunt but it still feels like q1 with a boob job. The 30 minute full-recompile times for the sdk didn't turn me on too much either.
Hl2's map editor is still mostly brush based, too.

Frozen Sand and Quake 3

Anyways.. I've been unoffically maintaining q3map2 for about a year now (q3map2_fs, quake 3's map compiler), and have an entire sdk worth of code we've invented for urban terror and mx. So we decided it'd be worth our while to port most of the candy from hl2's renderer over to quake 3, and see about updating q3 to 2007 status.

After some research, the specific sore points for us with unmodified q3:
* Lack of scaling. After about 40,000 visible tris, performance starts dropping off nonlinearly.
* Mapping from 3dsmax/maya. We've attempted this a few times, but the hacks we do to get things colliding kill it (collision brushes generated from triangle soup).
* Pixel Shader Candy: No Bloom, No Bumpmaps, No Specular, No pretty water like hl2.
* Md3 Model Format's pretty poor compared to skeletal/ragdoll systems/ Entity Physics/Vehicles

So yeah.. to address each of those points in turn:

Quake 3 And T&L, Surface Merging

Quake3 maps don't scale nicely because it's mostly CPU bound. The hardware it was targeted for was pre T&L (think TNT2 and 3DFx) so good batching habits and rabidly avoiding state changes didn't really exist like it does now. So, I added a new "static" surface type whos geometry all sits inside a big fat Vertex Buffer Object allocated at load time. It hijacks its source data from the Lightmap lit surfaces in the map that arnt using any fancy shaders.. and collapses them together into single draw calls as much as possible.

Ut4_casa started with about 10,000 individual draw calls for the simple lightmapped surfaces, which was about 75% of the total geometry. After collapsing them, it was about 700 calls. Lightmaps are keeping the surface merging process from completely obliterating the Visiblity Culling - by stopping it merging the entire map into single big drawcalls. So it's still working but there's much less agressive culling going on.

It yeilded an average 25-50% increase in framerate anyway :)

We went from being able to throughput about 1.8 million tris per second on my modest 9800 pro/amd3000, to about 2.4-4.0 million depending on the existing urban terror 4.0 map. Special test maps built to be more batch friendly (denser closer packed geometry using fewer shaders, few fancy non-batchable surfaces) scale well into the 6mil+ range. Win.

Mapping from 3dsmax/maya

Hybrid brush/model build maps are just gross - the artists are pushing hard for single-modeling software package based mapping - but even after the updates I've made to q3map2 building an entire map in max for q3 is currently futile.
The lighting compiler is up to the job now (yay smoothing groups and various lighting fixes), but "Autoclip" generated brushes based on map triangles are just a bad idea, and doesn't scale well at all.
The fix will be to move over to some raw tri based collision in-engine, but it's still only a note on my todo list.
Pixel Shader Candy

I've implemented Hl2's radiosity bumpmap solution (courtesy the ati/valve papers on the subject) so now q3 has that.

* Updated q3map2_fs to output 3 basis-normal modifed sets of lightmaps via the -radbump switch
* Updated q3 to load those, various new openGl extensions, and normal maps for diffuse surfaces.
* Draw it with a GLSL compiled vertex/fragment shader, with radiosity bumpmapping and fresnel/cubemap specular.

Highsea (Mike) has been invaluable in getting this working, as this is techically my first ever experience with openGL/glsl - and talk about diving in the deep end. It's not that dissimilar to dx 8/9 which I've done shader work with before.. although I found the d3d documentation to be a good deal more centralized/organized, specifically with creation and setup lifecycle of these fancy new objects. My closet admiration for MS's dev products continues.
I have my crappy test-box rooms out with normalmap generated bumpy/specular goodness working in q3 now... still lots of things to go. Alpha cutouts, generated cubemaps for specular, water and bloom on my todo list next.
Thats it for now, the image uploader/editor for this blog is annoying me.