Re: [Plib-devel] Texture and blend modes
Brought to you by:
sjbaker
From: Curtis L. O. <cu...@in...> - 2000-08-19 16:22:03
|
Steve Baker writes: > > Hmmm, yes, for flightgear, there are a couple things I'd like to see > > added to ssg's lazy state evaluator ... > > What - specifically? Here are the additional things that the flight gear sky needs to control: - GL_DEPTH_TEST (enable/disable) - GL_FOG (enable/disable) We don't change the fog function, and the fog parameters are global, but this might change somewhat if we want to impliment some sort of extra "punch through" for lights - glBlendFunc() > 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. This is all true from a pure performance perspective. Perhaps I should just give up on the idea of building a completely drop in sky that will work with any ssg friendly application. > 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. What I'm arguing for is some sort ssg mechanism that helps the user do this robustly ... > 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. I'm not opposed to leaving ssgSimpleState essentially as it is, I'm just wishing that ssg provided some mechanism to thelp the application robustly handle management of some of these less common states. > > 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. Exactly why it would be nice to have some sort of ssg mechanism to assist with this. > Worse than that. You'd have to apply it to EVERY leaf node. You could impliment a state management extension scheme at the cost of one extra check per node. If this check indicates there is extra state info for this node (or the previous node), then you branch off and do all the extra work to handle it. Or in the case that the current node has no extra state info, but the previous node did, you would have to do extra work to restore all the changed items to their default state. > Yep. But you absolutely cannot mix ssgSimpleStates with other > state management schemes. I'd argue that you could (as described above) at the cost of one extra check per node. > 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. You could keep an extra variable around ... something like: bool last_node_had_extended_state; If you process a node with extended state you set this to false. If you process a node without extended state (but this variable is true) then you do the extra work of restoring the less common states to their defaults, then you set this variable to false. > 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. I think we are approaching this from different mind sets. You are talking in terms of performance and commonly used states. I am talking in terms of developing robust applications that have some sensible, reliable scheme to manage all the state changes needed by the application. It's critical for an application with the scope and number of participant such as flightgear, that we get a handle on *all* the state changes and do it in a consistant, robust manner. Mixing and matching schemes points you straight down the road to disaster. FlightGear has been dancing on the edge throughout it's entire existance. I'm searching for a way to resolve these issues. As it is, I keep having to go back and try to figure out which global state change in one part of the code is messing up the rest of the code. This is hard, it is frustrating, it is time consuming, and each time I have to do it I hate the mess even worse. I want a nice, well thought out, robust way to deal with this. The most sensible place to start with this (I believe) is inside ssg. > 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. ... and it is a CLASSIC case of why ssg needs some mechanism to handle these state changes. What if I want to drop the FlightGear sky module into some application that doesn't use the default blend function? Now my sky will break that application, and perhaps do it in a non-obvious way. These global state screw ups can suck up huge amounts of debugging time for large complex applications where lots of people have their fingers in the pie. Yes, we can (and do) make do with what we have. We find work arounds, we debug the state screw ups ... until the next time someone needs to change or use one of these uncommon states at which point we are plunged right back into the front end of this whole process of figuring out why our rendering is all screwed up (again). > No - you just have to turn the blend mode back to 'normal' in the > post-draw callback. Which you can't do in the case of my sky code because it doesn't necessarily know what "normal" is for the host application. > 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 don't think we can just document away all the difficulties here. I prefer the approach I described above which is similar to your (1) but only costs one extra test per node ... until you hit something that uses the extended state mechanism. But you, the application writer, understand that you maybe trading some performance for a reliable extended state handling scheme. But in the case of flightgear, this will only happen on a couple nodes per frame so the actual perfomance cost will be minimal. > 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. Is this really true? I've never tried it glGet() in the primary render loop. I'd imagine for current PC consumer cards or Mesa based drivers this would be fast, but what about higher end system? What about disrupting the render pipeline? This sounds ugly. :-) > 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. Well, it's only one test per node, well more like one if statement: if ( ssgHyperExtendedState != null || ssgLastStateWasHyperExtended ) { // process ssgHyperExtenedState } processing a null ssgHyperExtendedState would be defined as restoring (anything that was previously changed) back to ssg defaults. > 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. And I will argue that it is *important* enough for building *robust* applications that we do need some mechanism to assist the application in reliably managing these less used states. > 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. I have no idea how many hours I've spent trying to chase down state problems in flight gear. To be fair, some of these have been due to my own stupidity or lack of understanding of opengl, some of this has been do to Mesa bugs, but much of this could be saved (or prevented in the future) by adding some mechanism to help manage these state changes robustly. Most of the arguments that led you to develop ssgSimpleState should apply here to extended states as well. Certainly performance is a consideration, but so is code robustness and code maintainability for larger projects. Maybe your typical game is hacked together in a year or so and has a shelf life of a couple of months ... a few dirty tricks here or there isn't going to hurt anyone, and even if it does, six months down the line no one will care. But FlightGear is a *long* term application ... any hack we do now will come back to bite us later. I've seen it happen many times already. > 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 would honestly pay that price if it meant we gained a sensible way to deal with all our state headaches. Sooner or later, (actually just sooner) the flightgear project is going to need some good mechanism to deal with these less common state changes. It will have to either go into the FlightGear code, the SimGear code, or the ssg code. I vote for putting it into ssg, but perhaps I'll have to settle for some other place if that's not possible. Curt. -- Curtis Olson Human Factors Research Lab Flight Gear Project Twin Cities cu...@hf... cu...@fl... Minnesota http://www.menet.umn.edu/~curt http://www.flightgear.org |