The D3D11 port is pretty close to complete. Here's what's left to do:
gl_texturemode
Right now I'm just forcing 4x anisotropic filtering at startup, but I want to get this done fully, even if it's not really a critical feature. It seems like it should be easy enough.
gl_flashblend 1 mode
AKA the alternative to dynamic lights - draw a shaded ball around each light. Not really a big deal as a key feature of this port is GPU updating of dynamic lights, but all the same, it seems like it might be fun as there are a number of possible ways of doing it that are worth exploring.
r_shadows 1
I can reuse a lot of code from MDL drawing here; DirectQ just caches all the relevant info needed to redraw shadows at the correct frame and position (which, because it uses static vertex buffers, is very little) so something similar seems the right way to go. Might be fun. At some point in time a shadow volumes inplementation using the geometry shader for volume extrusion might be an interesting experiment.
r_wateralpha
GLQuake only applies alpha to worldmodel water surfaces, so that's probably the approach I'm going to take; I don't want to complicate things too much by setting up a full alpha sorting scheme - it is only an experimental engine after all.
r_mirroralpha
Won't be done. Suck it down, bitches.
Some notes on items of interest in what was done so far
Brushmodel surfaces
Using the GPU for dynamic lightmapping was a primary motivation for beginning this port. I already had something similar done in an experimental D3D9 build, but there were some D3D11 features I wanted to at least try. On balance it's slower than the D3D9 version in simple scenes but faster than it (sometimes much faster) in more complex scenes, which seems like the right way to be.
I played around with drawing surfaces using individual draw calls and triangle strips with restart indexes, but in the end went for a simple indexed triangle list which still provides the best performance. Draw call overhead in D3D11 is so low that the overhead of building indexes dynamically may well come close to balancing things out. An eventual goal is to experiment some with stream out for building surfaces, which is another objective of this port.
Cutting down on dynamic light update checks was an interesting problem and using bitwise operators in my shaders to replicate the functionality of surf->dlightbits required shader model 4. In SM3 indexing into the constants registers from a pixel shader was a baaaaaaaaaaaaad idea so I used texture lookups to retrieve dynamic light positions and colours; in SM4 using the registers is actually faster. In both, vertex texture fetch came in handy for doing a pre-check.
I also experimented a little with sending each triangle through a geometry shader to cut the pre-check (and many of the calculations associated with it) to a third, but the overhead of adding a GS stage here outweighed any benefit so I dropped it.
Screenshots
These took me ages to figure out how to do, but ended up being really easy and quite elegant. Definitely nicer than the D3D9 version, but nothing compares to good old glReadPixels...
2D GUI Stuff
This was the first thing I did because I just wanted to get some quick and easy output on the screen, and I may have made a bit of a mess in doing so. I'll probably revisit the code. This uses indexed triangle lists too, but I'd like to have some code that uses strips with restart, so I may well port it over to that - I'm not going to be too concerned if it runs a mite slower as the purpose of this engine is to have a sample codebase to draw from in the future.
Video startup
I just locked the mode to 1024 x 768 windowed and didn't bother with anything else. The intention was to have something that worked, not a fully-featured port. At some point in time I'm going to need to go back and do proper video mode enumeration and selection, and I also want to play with mode changes in D3D11, but now is not that time.
Textures
Textures were confusing. The code to load one is a little more verbose than I would have liked, and it's unclear which combinations of flags are valid for any given texture. Once written they load - and reload - quickly enough, and I timedemo bigass1 at maybe 550fps.
It was completely unclear (and seemed to be documented absolutely nowhere) exactly which slots in a -SetShaderResources call map to which textures declared in shader code, so I ended up explicitly specifying texture registers in some of my shaders.
Particles
The second thing I ported because I was itching to do them with a geometry shader. I had actually tried this using OpenGL in the RMQ engine before, but it didn't work out too well. This time around the only problem was that I just couldn't get the GS to output 4 verts in a tristrip properly, so I had to end up using 6 verts in 2 separate tris instead.
Thoughts on Direct3D 11 Itself
I like it a lot, despite much of what was odd about it, and am looking forward to porting DirectQ for real when the time for Release 2.0.0 comes around (dunno when that will be yet; best guess at the moment is second half of this year at the earliest).
Important to remember that here I'm using the D3D11 API on D3D10 class hardware, so full D3D11 will not be a requirement.
Some functionality from previous versions is still there, some is changed slightly, and some is missing altogether. I don't miss the fixed pipeline or drawing from system memory arrays - they sucked - but more minor niggles, such as the verbosity of object creation code, a seeming inability to update a subrect of a texture, and a lack of clarity in the NO_OVERWRITE/DISCARD pattern do exist which will probably need a slight rethinking of how I go about some things.
Overall - it's been fun.
No comments:
Post a Comment