|
201
|
Developer / Technical / Re: Too many lights on a starship! (XNA, shaders)
|
on: February 25, 2009, 12:46:33 AM
|
Has anyone ever seen a technique where you precompute the light angles per, oh, 1'x1'x1' cube across the map? It seems like it would be expensive to figure out what values you should use to light your mesh if you recomputed all the time.
I actually do this in my engine as my only source of lighting for dynamic objects. It works fine for my purposes, but would generally be better used just for a directional ambient term like they do in Source. It lacks the fidelity to provide realistic specular highlights (because you don't have an actual light vector, just the sum of light on the cardinal axes), and it's static. The nice thing about it is that I can use infinite lights at no extra cost (but they're all static and resolved down to the irradiance volumes). I'm curious about precomputing light on the walls at the cost of texture memory... Could someone explain that better, or link it? Do you make a copy of each wall's texture whenever the lights change, and do a slow procedure to calculate it properly and then save a copy per wall face? That sounds reasonable...
The classical example is Quake 1's lightmaps, where you have a low resolution grayscale texture for each face, multiplied on top of the diffuse texture to create shadows. (Actually, you'd pack a whole bunch of these into large lightmap atlases.) There's no directional information there, though, so they don't play real nice with normal mapped surfaces. That's where Source's "radiosity normal maps" come in--they're basically just lightmaps computed relative to three basis vectors instead of to the surface normal. (In my engine, I do the same thing but for vertex lighting instead of lightmaps.) One solution I've seen that allows dynamic light values (but not positions) is to encode the lightmap with the contributions of the most relevant lights (e.g., four lights on the RGBA channels). Then the value of the lights (color and/or intensity) can be changed and passed into the shader and multiplied by the lightmap value on the appropriate channel. I haven't implemented this myself, but it seems like a clever solution if you need to be able to turn lights on and off in an otherwise static scene. I thought that the Source ambient cubes were sampled just as cubemaps, using the normal of the model and just looking up with something like a texCUBE() HLSL intrinsic. So then spherical harmonics are not needed.
1x1 cubemaps are a decent analogy for how irradiance volumes work, but that's not actually how they're implemented in the shader. I guess it could be done that way, but the texture sample would probably be slower than this: float4 LightCube[6]; float4 GetCubeLight( float3 InNormal ) { float3 NormalSquared = InNormal * InNormal; int3 IsNegative = InNormal < 0.0f; return NormalSquared.x * LightCube[ IsNegative.x ] + NormalSquared.y * LightCube[ IsNegative.y + 2 ] + NormalSquared.z * LightCube[ IsNegative.z + 4 ]; }
|
|
|
|
|
204
|
Community / Cockpit Competition / Re: Cockpit Crash 1984 [FINISHED]
|
on: February 22, 2009, 01:22:05 PM
|
|
Thanks for the comments, guys. I added strafing, a minimap, and some simple particles, and I inverted the power-ups so they have more distinct silhouettes from enemies.
The lack of strafing was actually intentional, because it's a tank game, but eh, it's more fun this way.
|
|
|
|
|
205
|
Community / Cockpit Competition / Re: Cockpit Crash 1984 [FINISHED]
|
on: February 22, 2009, 12:21:47 AM
|
It is interesting and educational to code your own 3D raster engine (meaning: no OpenGL OR Direct3D, just pixels)
Yeah, totally. That's something I've wanted to do for years now, but it's kind of an exercise without a purpose beyond itself, so I haven't made time for it yet. Maybe I'll find an excuse to do it for a future compo. Getting this "vextor" engine running was fairly trivial, because I already had a 3D math library, a text mode interface, and a Bresenham function for drawing nice lines. Doing proper triangle rasterization with texturing and whatnot would be a meatier challenge.
|
|
|
|
|
210
|
Developer / Technical / Re: Loading a map, agnostic or XNA
|
on: February 20, 2009, 05:29:15 PM
|
I just Googled and found this, dunno if it's any good: http://www.codeplex.com/q3libxna/The BSP file format is also readily available if you want to roll your own loader. I've done it for Quake 1 maps, and my understanding is that it's somewhat easier for Quake 3. Trying to make sense of the uncompiled .map would be extremely slow and difficult. It stores brushes as sets of planes, as you pointed out, so you'd have to clip them and build the faces yourself. That's a lot of work and a big hit at runtime--there's a reason maps are compiled offline and shipped as .bsp. I understand your argument for just loading a poly soup--the complexity of a BSP tree is significant and mostly unnecessary if you're making simple boxy worlds. On the other hand, it will be a huge benefit to the performance of both your rendering and collision code if you use some form of spatial subdivision, especially as you build larger and more complex maps. There's no reason you can't just load up a .bsp file and render it all at once, either (the structure of a BSP tree and the precomputed visibility set can improve rendering performance, but that doesn't preclude rendering the whole thing as a poly soup if you want to).
|
|
|
|
|
211
|
Developer / Technical / Re: Do Trilinear/Anisotropic filtering and pixel art combine well?
|
on: February 19, 2009, 05:41:19 PM
|
Not sure in what way you want it evaluated. I mean, it'll be filtered, and pixel art is all about looking sharp and crisp, so no, it wouldn't work well? But then, some people like playing SNES roms with filtering, which I think is blasphemy. To each his own. But it might look something like this, anyway (hotlinked!): 
|
|
|
|
|
212
|
Developer / Technical / Re: The bashful, dopey, sleepy, sneezy, and doc programmer room
|
on: February 17, 2009, 10:36:55 PM
|
|
Back in school, I was sleeping poorly and taking Benadryl for allergies (almost was a sneezy programmer, but this story is about being a sleepy programmer). We had these three-hour-long lecture/practical classes where we'd be given something to implement and the instructor would provide a brief look at his example code on the project to guide us before we began our own implementations. On this particular day, we were implementing game timers (using QueryPerformanceFrequency/Counter on Windows) and I was extremely medicated and tired. I was trying to copy down the instructor's notes before he hid them and struggling to even keep my eyes open at the same time. After a few minutes of this battle, I looked up at what I had written. I wish I could remember it exactly, because it was hilarious, but what I do recall is that was definitely not code. I had apparently just started typing a kind of drug-addled stream of consciousness interpretation of the task at hand and had ended up mixing nonsensical English sentences with fragments of C++ syntax. The realization of it jolted me awake, but it still took me a while to find the meaningful elements in the mess and figure out what I had meant to write. Good times.
|
|
|
|
|
213
|
Player / General / Re: Blender
|
on: February 14, 2009, 08:54:17 PM
|
|
Yeah, Blender is great. I guess the interface is unusual, but not being familiar with the more established 3D packages meant I didn't have to break any old habits to get used to it. I don't use the game engine, but I do use Blender as my level design tool--just place empty objects and throw some properties on them (with its very game-oriented key-value property pairs) and I've got entities placed in a world. Writing an exporter with Python wasn't too difficult, either.
|
|
|
|
|
214
|
Community / Tutorials / Re: Approaching a MMO
|
on: February 12, 2009, 06:02:05 PM
|
I am not making an MMO I am day dreaming about making an MMO.  loadVars essentially calls a webpage with the arguments you want to pass in as part of the web address then reads the contents of the page back into flash. I have had some success making close to real-time multiplayer (ie dynamically updating scoreboard). However I am not sure if this is the path to follow for taking the next step into multiplayer. Performance issues aside, the bigger issue I'm seeing is that you'd have to write your server-side game logic as a PHP script or something, and there would be no current state beyond what was stored in the database. I don't know a whole lot about MMO server design, but I assume there's an active world state to handle transient things like combat actions, and that the database is there to maintain permanent changes to the world like player statistics.
|
|
|
|
|
215
|
Player / General / Re: Need advice dealing with work problems
|
on: February 12, 2009, 09:35:27 AM
|
I was in a similar situation at a previous job, albeit in a less critical role. But I was working regular 11-12 hour days, eating lunch at my desk, and dealing with a lot of stress and anxiety but not getting to do any interesting work. And I got chewed out by my boss for going home half an hour early one day (in an email CC'd all the way up to the president of the company, no less). I put up with it for the duration of the development cycle because it paid well and it wasn't terrible all things considered (I mean, they kept the fridge well stocked with energy drinks  ), but a better opportunity came along right as we were wrapping up that project, so I leapt at it. Now I am happy as a clam. I'm working on fun and challenging tasks, I'm appreciated and respected by my leads (who I also totally appreciate and respect), I work reasonable hours and only stay late when I want because I want to, and if I'm eating lunch at my desk, it's probably because I'm playing a quick match of Left 4 Dead with my coworkers.
|
|
|
|
|
216
|
Player / General / Re: The indie gamer vidya card poll
|
on: February 11, 2009, 01:57:28 PM
|
geforce 6800 and I hate it because I will never get to play Dark Messiah on it.
It doesn't necessarily run well, but Dark Messiah's supposed to be playable on a 6800. I played it on a 6800 Go, even. (In fact, wasn't the Source engine backwards compatible to DX7-era cards?) Shame the game wasn't all I wanted it to be, but it sure did look gorgeous.
|
|
|
|
|
217
|
Developer / Technical / Re: The grumpy old programmer room
|
on: February 11, 2009, 09:51:16 AM
|
|
IDE frustration is the worst. I had to use CodeWarrior on a recent project, with no prior experience in it and years with VS. I didn't know the hotkeys, I couldn't ever remember how to do simple things like search in all files, and the floating windows everywhere just offended me. I'm sure I'd get used to it eventually, but it was madness to switch to from VS.
The fact that CodeWarrior projects are non-diffable binaries actually does seem like a horrible flaw, though.
|
|
|
|
|
218
|
Player / General / Re: The indie gamer vidya card poll
|
on: February 10, 2009, 10:48:53 AM
|
Good bump; I missed this the first time around and it's something I've been curious about. I'm developing on a GeForce 6800 Go (laptop card) and have been worried that most indie gamers actually have even older machines than I do. Looks like that's not the case as much as I thought. They're not specific to indie gamers, but the Unity and Steam surveys are great sources of gamer hardware statistics. Unity skews more low-end than Steam, which doesn't surprise me. UNITY: Web Player Hardware StatisticsSteam Hardware Survey
|
|
|
|
|
219
|
Developer / Technical / Re: The happy programmer room
|
on: February 07, 2009, 11:41:58 PM
|
|
Today I am a happy programmer because I improved my memory allocation and got a substantial performance gain from it.
Way, way back in the early days of this project, I wrote a custom allocator/memory manager, mostly to get some more useful debug statistics for catching memory leaks, and just because I could and it seemed like a fun and interesting challenge. It was a pretty basic, minimal design: first-fit algorithm with a single linked list of blocks. It's stable and useful for debugging, but it's significantly slower than the default CRT allocator. Slow enough that I began to suspect it was my primary performance bottleneck. So I switched it off, and sure enough, my frame rate doubled.
So I could have just abandoned my custom allocator and used the default. My engine is largely feature complete and I don't expect to run into any really nasty memory issues. But then I thought about why my allocator was slower and realized a previously hidden benefit of having a custom memory manager. Because I knew its exact implementation, I could arrange my memory in such a way as to be optimal for the allocator.
The reason my allocator was so slow was that it has to traverse the linked list to find a free block of the desired size for every allocation. As the project has grown, that list has become relatively large (~20k allocated blocks). In order to improve performance, I needed to reduce the size of that list. So I moved a few systems with lots of total allocations and/or lots of allocations per frame to separate memory arenas. I gave particles, config vars, and strings their own separate allocators, which stops them cluttering up the main block list and makes them faster internally.
But the performance was still lagging behind the default allocator, and I remembered something I'd realized months ago and then completely forgotten about. All the game's subsystems and the static elements of the world are loaded in first, which means they sit at the front of the block list. That means that every subsequent allocation is going to have to iterate over those blocks and will never find a free block in there, because that stuff is basically static. All I had to do was use a separate allocator while initializing the game and loading worlds, and then the main allocator was a blank slate for runtime. Now my memory performance is at least on par with the default allocator's, and more importantly, memory allocation is no longer a bottleneck.
I guess the surface lesson here is to trust the default allocator. The deeper lesson I learned is that if I'm going to re-implement something, to actually take advantage of what it offers beyond the default.
|
|
|
|
|
220
|
Developer / Design / Re: What to make.
|
on: February 07, 2009, 12:36:06 AM
|
|
Shmups are good miniprojects. The fundamentals can easily be done in a week if you've got any sort of framework (graphics, input, and collision tests, mainly) to start from.
You could also implement a smaller part of a whole game as a miniproject. I once wrote a tile-based A* pathfinder in about and week and then developed it over the following week into a little stealth game where you had to sneak past a guard in a maze to steal treasure.
Physics demos are good, too. Make a sandbox where you can connect point masses with springs. The math isn't too difficult and it's a lot of fun to build spongy shapes and bounce them around the screen.
|
|
|
|
|