Re: [Plib-devel] Texture and blend modes
Brought to you by:
sjbaker
From: Steve B. <sjb...@ai...> - 2000-08-18 22:34:24
|
"Curtis L. Olson" wrote: > Hmmm, yes, for flightgear, there are a couple things I'd like to see > added to ssg's lazy state evaluator ... What - specifically? > Let me jump in here and say that I'm not exactly 100% pleased with > handling these things via a call back function. The call back has no > way to know the initial state of the element you are interested in > changing. So, how do you reliably restore the value? How do you know > if you need to actually change the state or not? You are back to all > the problems associated with randomly changing state at random points > in your program ... these are the sorts of problems ssgSimpleState was > designed to fix. Well, that's why you have to decide which things to test before EVERY leaf node is drawn - and which to set and restore in callbacks. For things in callbacks, you know the default state because you can set it before calling ssgCullAndDraw and be sure that SSG won't mess with it (unless I have an error). Then you have to set it (unconditionally) to what you want in the pre-Draw and restore it to the default state in post-Draw. Whether it's better to use that mechanism or a lazy evaluation mechanism depends on: * The cost to test whether the state is already what you need MULTIPLIED by the number of leaf nodes that DON'T use that state. Versus: * The cost to redundantly set and unset the state MULTIPLIED by the number of leaf nodes that need that state. When the number of leaf nodes containing the state is small, it's better to use a callback and suffer the cost of switching it redundantly. When the number of leaf nodes containing the state is large, it's worth paying the penalty to check for it in order to save redundant state changes. Now - where that balance lies clearly depends on the application. Take something like glTexEnv. I have probably used it once - on one leaf node once during my entire career. For me at least, this doesn't warrant putting into ssgSimpleState - it's FAR better to put it into a node callback. Look at something like glBindTexture though - and every single leaf node needs to be checked - so it's worth putting into ssgSimpleState. Notice also that with draw callbacks, you can put them higher up in the scene graph - so if you have an entire character in a game that needs some peculiar glBlendFunc (a Ghost for example), then you can put the state change up at the root of that objects scene graph rather than on every leaf node. The problem here is that SSG is used for a lot of things - and my personal choice of what things should or should not make it into ssgSimpleState may not agree with yours...so we should discuss the matter and see where we should compromise. > So I suppose I could hack in my own tracking variables and sort of > parallel what ssgSimpleState is doing ... That's very hard to do because your post-draw callback can't tell whether some other leaf node (without a pre-draw callback) will be drawn next or whether you can safely leave the state at this new (non-standard) setting ready for the next leaf node that needs it. > this leads to either > reimplimenting something very similar to ssgSimpleState... Worse than that. You'd have to apply it to EVERY leaf node. It would be better to derive a new kind of ssgState and either use your own loaders - or walk the scene graph after loading it from disk replacing all the ssgSimpleState's with ssgCurtStates. Yuck. > or coming up with an extention to it that tracks different, less > common elements? Yep. But you absolutely cannot mix ssgSimpleStates with other state management schemes. > Or more likely yields an application specific mess that is more likely > to break things in the future than work. > > IMHO this extra state tracking would be best done inside ssg ... maybe > with an ssgExtendedState class or something? It would be *really* > nice if ssg had the ability to track and control some of these less > popular states. Well, as I've explained, you can't do that because when this ssgExtendedState leaf node finishes rendering, it mustn't leave the extended state elements turned on because a subsequent ssgSimpleState doesn't do the testing to turn it back off again. That's why it's all-or-nothing...and why I don't want to do this. I'd be VERY interested to hear which states you think are common enough to need to be changed lazily and which ones can be set in callbacks. Since you are building a flight sim - and I'm not unfamiliar with the needs of such programs :-) ...I can't imagine what you are changing that is so commonly required. > Blend function changing happens every frame in flight gear so we can > draw the moon with the proper phase against a changing/gradient > sky. :-) Yes - but that's ONE leaf node (probably). You can't possibly justify adding another conditional test before every single one of the 10,000 or so other leaf nodes you are probably drawing just to save...well - nothing actually. You still have to switch to the special blend mode before drawing the moon - and it would be restored again by the very next polygon to be drawn - lazy state evaluation would save you exactly nothing in that case. If you had (say) 100 moons to draw randomly throughout the scene - then I might be pursuaded. This example is a CLASSIC case of why I don't want to put the blendfunc into ssgSimpleState. > > Hence, it's better to suffer the penalty of a costly (non-lazy) > > state change done in an application draw-callback than to burden > > every leaf node with testing for a condition that'll probably never > > come up. > > But using a callback introduces more than just performance penalties. > You also run the risk of leaving the element in some unknown state > that hoses the rest of your program ... No - you just have to turn the blend mode back to 'normal' in the post-draw callback. > and as you well know, these > sorts of global state changes can be hard to debug if you add > something that breaks because of a mistake you made 18 months ago or > any permutation there of ... Indeed. > I'm still trying to eradicate these sorts of problems from FlightGear, > but I end up being forced to put scary stuff back inside of > callbacks... I think that this could be attacked in one of two ways: 1) We could add code for all the rarely used states which would be tested for in one step in ssgState. ie we'd have a "Weird State" flag that ssgSimpleState would test for. If that flag were to be TRUE, then it would do a lot of unconditional state changes and tell the leaf node to call a special restoration function after the user's post-draw callback was called. That adds two more conditionals to every leaf node - but we could perhaps win that back by moving some of the more obscure existing ssgSimpleState lazy elements into the non-lazy code. 2) Documentation. We need to write down precisely which state elements SSG chooses to manage - and which ones the application is responsible for. We also need to write down the default states of those elements. Remember about the 'which item Steve prefers in a list' thing? :-) > I wouldn't be surprised if the simgear sky code breaks (or is broken > by) just about every application that tries to use it for this > specific reason. It has to use call backs to change these less > popular states, and thus by definition doesn't play nice with any > application it may be dropped into. That's certainly an issue. But for *just* the moon, I'd toss in a dirty 'glGet' to find the current blend mode so you can restore it in post-draw. Once per frame isn't going to kill anyone. > > Similarly, glTexEnv doesn't cut it either - I certainly don't want > > to add an extra conditional for every triangle strip for a feature > > that hardly anyone uses! > > Can we have perhaps have an ssgSuperExtendedSimpleState that does > include these extra things for applications that need them? Or > perhaps something similar to ssgSimpleState that tracks all the things > that you don't want to track in ssgSimpleState? Well, as I explained before, it isn't that simple because if ssgHyperExtendedState doesn't clean up the wierd stuff it changed then the next ssgSimpleState that comes along will have to do so. That's an additional cost for every ssgSimpleState which you can't justify unless there are a heck of a lot of ssgHyperExtendedState leaf nodes out there. > Let me propose the following: > > We could add a pointer to an ssgComprehensiveState class inside of > ssgSimpleState. The ssgComprehensiveState would handle all those > states not handled by an ssgSimpleState. > > If this extra pointer is non-null then the system would evaluate the > associated ssgComprehensiveState as well (with the corresponding > performance penalties.) We'd also need the concept of a "default" > comprehensive state. So if you evaulate a simple state and this extra > pointer is NULL, but the previous state's pointer wasn't, you would > diff against the default state first. This way you could recover from > a state that does things like change glTexEnv or sets up a funky blend > function. Well, I *think* that's my (1) above - although maybe not. (1) above is NOT a lazy evaluation scheme...although you could make it so at some cost. The bottom line for me is that this stuff simply isn't common enough to warrant all the work and complexity. I need to be convinced that there are enough nasty things that ssgSimpleState can't handle to make this worthwhile. Right now, I'm very reluctant to add a single line of code to ssgState or ssgLeaf or their descendants because doing so slows down every single SSG application by a measurable amount. Certainly the FlightGear moon doesn't come even close to meeting that criteria since all this work would slow *everyone* down a little - yet providing no speedup at all to FlightGear! To the contrary - it would actually slow FGFS down some too! I grant that something in ssgSimpleState is going to have to change - but the driving force for that change is the growing trend to have multiple texture maps per polygon without using multipass tricks. -- Steve Baker HomeEmail: <sjb...@ai...> WorkEmail: <sj...@li...> HomePage : http://web2.airmail.net/sjbaker1 Projects : http://plib.sourceforge.net http://tuxaqfh.sourceforge.net http://tuxkart.sourceforge.net http://prettypoly.sourceforge.net |