That "weak notebook card" is quite a lot faster and theoretically much more awesome than my geForce 7800. That said, I am glad to hear that ATi hardware is still not borked, since I've made a number of changes to things and they're so much more... sensitive.
Anyhow, don't thank me, thank Kloot. I'm just fixing minor crap, is all. He was the one who implemented TBN matrixes in the engine, etc., which made all of this possible, and wrote (and rewrote, and rewrote) the code. I did a few things here and there, but that's just bug-fixes really.
I think this code's about as good as it's going to get. I've tested with cloak, capture, etc., and it all seems to be working.
The CPU costs are not entirely trivial, but cannot really be avoided, and I don't see any good places to optimize. I see maybe 10FPS dropped because of CPU load when I am on a World Builder map. That's ouch-inducing, but not too terrifying.
What will be a little more painful is the last step- getting an alpha-transparency version working that uses full depth sorting, and hopefully a Fresnel shader. In theory, the GLSL side of that is pretty easy- just steal a little bit of jK's code from his airjet shader, call it a day. But I think that that's the final goal here- it would put Spring's unit rendering on-par with the latest game engines.
Map rendering still needs to reach that state as well, but we have most of the code for that, and "merely" need a SMF clone that includes a second texture per tile that is a DDS DXT5, for storing normalmap / heightmaps with, and we can be there in a week or so of messing about. Then maps would finally look as good as anything in a "professional" engine.
And of course this shader can be tweaked for various effects, that I probably don't have time to explore ATM. For example, that extraColor.b channel is still available for tweaking anything that people might want, from specularity to color-shifts based on the normal vectors, for "opalescent" effects, exotic metallic shaders, etc.
But I won't have time to get to that stuff, at least not any time soon- it isn't necessary for P.U.R.E. atm, and I have a lot of content to finish before the next version of P.U.R.E. is done. Heck, I have a lot of content to complete before I can even release screenshots of this new technology outside this place, frankly. I have maybe half of the World Builder stuff done, but that's because so many things share maps.
But most of my units have "normalmaps" that I built using CrazyBump's demo, and they're utter crap- I'll have to hand-paint them instead. Lots of fun, considering that I didn't keep the layers for the "armor plates" intact
Anyhow... progress is progress, I suppose. Several down, a million to go. The really sad part is that is the third time I've had to make a normalmap for the Engineering Team, one of the hardest models in P.U.R.E. because it's a jigsaw of odd shapes... but I threw out the older versions, and had to remake it again. This time I archived the PSD, lol.
@GMN: lol, I was referring to my skin on that one. It was the very first Resistance unit I skinned, remember? It's a mess! I did practically everything I could, to make my life difficult on that one
@SpikedHelmet: when the version with transparency is done, maybe. Don't ask me about fur or stuff like that- somebody else will have to lose their spare time to that.
And I certainly think that Spring's about as modern as engines get, personally. The only things that aren't quite up to par are the pathfinder, which nobody here understands, and the map drawing code, which people are looking at. Fix those two things, and Spring's about as current-tech as it gets, frankly. This is just visual tinsel on a very rich tree, imo. I just wish I had enough time and energy to make use of all of its potentiality. The engine could do things like FPS games, simple shooters, etc., without a great deal of trouble. It just requires programmer time and content wizardry.
@Kloot: can I get a brief writeup on the source code? I'd like to do a ModDB article about this, and give the world the GPL source to this (i.e., "think this is cool? Well how's about the SOURCE!"), but I'm afraid that if I try writing it and touch technical areas, it'll be filled with... Argh-isms, and people will laugh me out of town. I kinda know what I'm doing now, but I still don't have the technical language to talk about it.
Amongst other things, it might be useful to describe, in paragraph or two, how the TBN matrix is derived for Spring objects and how the UnitRendering code works. That stuff is the real genius, and goes well outside my knowledge.
There's nothing more powerful than saying that we did this, and that the source is free for anybody to use, as an argument about why Spring is cool.
Here's a basic tutorial right now, before I get back to work.
Making a normalmap can be done lots of different ways.
I'm going to show you how to do it quickly by hand, which is suitable for RTS models (and a lot faster than tesselating a model and producing a highpoly version, trust me).
Using the code is the easy part.
1. First you need to create a grayscale painting that represents height differences between high and low places on the model. White is highest "out", black is farthest "in". It requires a little imagination at first, but it's not too hard.
Here's my grayscale skin for the "sedan" model, and a shot of it on the model, to give you some context:
Basically, I'm just tracing panel lines and major features like the door handles and the inset windows. Since I already had the skin done, this was all pretty trivial.
When working with fantasy shapes, you have to use your imagination about what's "in" and what's "out". If working with something that needs subtle curves, I strongly recommend using an airbrush technique, like I did with the Chickens- that gets into slightly trickier territory, and it's outside the scope of this article.
2. Now you have a grayscale. Transform it into a normalmap. This can be done with Photoshop, GIMP, xNormal or any number of other tools, these days. I do it in Photoshop, and here are the settings I use:
BTW, if you reverse the "Y", your "in" becomes "out", in the TBN matrix implementation Kloot wrote. Do not mess with "Z".
3. Now you have a normalmap. Wasn't that easy? Time to turn it into something functional.
First, drop the Gadget into your game. I am assuming that you're familiar with how to get Gadgets working in your game (if not, you basically just copy my LuaRules folder to your game, and you're done).
Second, open up the TDF / Lua for your Unit, and if you don't already have customParams defined, then you need to create a section like so (this is the TDF syntax):
The "normalmaps=yes" tells the Gadget that you want this Unit to be used.
The normalmap_name is the filename of the normalmap in the /unittextures folder. You can use a deeper path, though, like "normalmap_name=/normalmaps/Sedan_Gray_NormalMap.dds;", if that's more convenient for you.
Assuming you've done this correctly... you're done! Go check your results:
And... that's it. This whole process is artist-friendly. You just have to do the things you're good at, and you don't have to know how it works.
I'm not sure if it applies, if you're not using parallax mapping (which shader2 does not- it's the thing I had to lose, to get it to work on my hardware).
I'll try it out, and see what happens.
[EDIT]Tried it. It works as described, even with ordinary normalmapping... but... and this is a fairly big "but"... if you don't blur the overlays a bit, you will suffer from noisy, pixelated results. And with low-resolution maps, such as the maps on that sedan (256X256), it tends to do more harm than good, because while the normalmap is "deeper", the things like panel lines are blurrier.
Should work much better with 512 maps, though. Keep in mind, also, that industry-standard practice is that normalmaps are 2X resolution to diffusemaps. Can't do that here, the performance crunch will be really huge, with the sheer number of objects involved, and texture memory will become an issue, fast.
I'll try it on a 512 now, and see how that goes.[/EDIT]
Well I guess its primary advantage is to give nice results on complex surfaces with quite some details (which would be a pain to paint by hand and get things right at the same time). It certainly won't be that effective for e.g. your Sedan where there is pretty much nothing besides color gradients and some few hard lines. Maybe try it for one of Mr. D's TA models...
Plus you of course (just as always) have to experiment with all the things like blur strength each time on an individual basis...
OK, on a 512, if you do not blur it, it works pretty damn well.
Adjust the number of overlays to fit your desired result. One overlay results in roughly twice the "height", so be careful, this isn't a cure-all. To get best results, you'll have to play around with various sections of a model, and adjust the level of the overlay's transparency.
But I think I know why you think one's less cool than the other (well, other than the model itself, which is a matter of taste). Let's readjust that Engineering Team one real quick...
OK, a bit better. Basically, the original map was 2X sized (long story there) and so the heightmap used to derive the normalmap was a bit blurry. That's about as good as it's going to get, short of a complete re-do, which I don't have time for.
What? Fur? Last I checked PURE had no rabid furries in it (uh oh...), so I don't see how its in any way necessary.
And IMO there are a lot more problems with Spring than just pathfinding, drawing and some rendering/performance issues. Dynamic/transformable collision meshes (meh), physics, environment interactability, unit behavioural AI, aforementioned skeletals, front-endability -- a list of individually rather small nuances, but added together compose a hardy set of limitations on bringing Spring to the truely professional level. Spring is still an engine whose features are tailor-made for the limited composure of Total Annihilation gameplay (features which, granted, have been wonderfully and expertly expanded). Many of these features can be done via LUA and so could arguably not be considered engine limitations, but so far no project has had the ability to really engineer a professional-level end product, including, no offense, yours.
That said, with the right expertise and manpower, the Spring engine as it currently is could easily be developed (both engine-wise and LUA additions) to rival and probably exceed the vast majority of professional commercial RTS titles out there. It is features like this proper functioning of normalmapping that really thrust Spring's capabilities forward. So keep it up, people!
Wheeeee. So... tired. Got at least one more hour of work to do, before I rest.
I've gotten the chance to test Shader1 on a geForce 9800GTS.
Performance is about the same as Shader2, and while it doesn't have the specularity control (which I'll add, that's a one-liner) basically it just looks more... subtle. No huge difference. It might be cooler, if I had a huge object with a huge normalmap / depthmap, or stuff with more organic curvature.
Has any ATi user gotten Shader1 to run? I haven't seen any results from ATi hardware indicating it's running, so I am curious to see whether it can be fixed.
Now that I'm on hardware that can actually compile it, I'm willing to try debugging it for ATi. I'll look at the current Infologs as a starting point.
But it really appears that adding parallax mapping is practically free, on modern hardware.
Soo... the final test is to see what things look like, when there are no more ARB-shaded objects in the world...
And the answer is... on a big flat map with a huge object count... 12 FPS, with 500 Units, each with 512 diffuse, texture2, and normal / depthmap, with 8192 shadows, while they performed a basic animation and occasionally used the realtime lighting shader (which turns out to be "almost free" when tested).
It was also interesting to note that the map is totally flat and voidwater (Unpleasantville) and yet performs far worse with all the objects blown away, other than the "commander"... than a smaller, hillier map with water did.
In fact, the difference was a whopping 100 FPS. Chief eater-of-CPU? The Shadow / Reflectivity code, at 43%.
Wait, what? Shadowmapping... what? A giant quad? Reflecting... what? If I don't have a Unit in POV, why is it even rendering a reflective cube?
Kloot, I'm going on vacation in 24 hours. I'll test yer thingy if it exists when I get back. It will certainly help a lot.
I think the other thingy to seriously scrutinize, given the result, is the way the reflection cube gets made. Maybe instead of rendering the entire map... divide it into sectors, use gl_fog to blur it with distance? Or use a virtual camera to take snapshots every 512 XZ, and have nearby Units only use the closest one, and if no Units are within 256... don't even bother? And if the Unit is closer than Z to the camera, then revert to the current code, for a more accurate approach that is less costly?
I mean... seriously... why is the reflection map, which is not something we need perfect accuracy on (I use a 128 cube in P.U.R.E., I force that value, and nobody has ever noticed) eating the vast majority of the CPU?
It ain't the shadows. I turned them off, and gained a whole 20 FPS. With 8192.
I'm going to repeat this test on that smaller, hillier map, see if I can get closer to an honest FPS test. But it's pretty obvious that there are some seriously terrible costs associated with the size of a map, regardless of how much is in the POV, that make a lot of my performance tests irrelevant...
[EDIT] Ok, I found one issue, right away. Up until you hit 4096 shadows, increasing the shadowmap resolution is practically free.
IOW, there's practically zero difference, performance-wise, between 256 shadowmaps and 4096.
At 8192, that magically destroys 60 FPS.
If the terrain geometry is (let's be fairly pessimistic) 10K triangles... this still doesn't make any sense. That should still be pretty cheap on the GPU. So, it's not the GPU. We're losing that much FPS to CPU loading.
So now I'm back to the mystery... if it's CPU loading, then why is a practically blank world causing that much load? And why does the size of the world seem to be causal?
Are we really performing a shadowmap over the entire world geometry, instead of what's nearby? If so, why? I mean, we don't exactly have an abundance of REALLY GIANT MOUNTAIN MAPS that necessitate this... we could probably use a restricted-sector approach. But even assuming all that... surely the world behind the camera, even though it's tessellated the same way as the stuff in front, isn't causing all this load...
Just because 4096 and 2048 both run at 60fps, doesnt mean that they cost just as much, it means vsync is truncating at 60fps adn your not seeing the difference. Forgetting that a 4096 image is 4x the size of a 2048 in gfx memory? People have complained texture memory before.
Why bother with this difference?
Because that difference in processing grunt could be used for new features. Just because you have a budget of $1000 doesn't mean your okay as long as you spend $999.99, what happens when you need something else the next day and you have $0.01? Or when you realize you forgot something at the store?
And if you have vsync turned off and there is no difference, then perhaps there's a bottleneck somewhere and it is not the shadow maps size determining the frame rate, but something else? This is what you should be investigating.
Users browsing this forum: No registered users and 1 guest
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot post attachments in this forum