Does Torque have focus/render to texture?
by Chris \"Hobbiticus\" Weiland · in Torque Game Engine · 01/17/2004 (9:27 pm) · 14 replies
I either need a way to either tell of Torque has focus or a better way of rendering to texture by drawing to screen and reading the pixels back.
The problem I'm having is that when I want to render to texture, if part of the area that I'm rendering to is covered up, the old color data is copied out. Would anyone happen to know of a way of either rendering to texture more reliably or to tell of torque is on top so I can tell it to render at a later time?
EDIT: I might also mention that it has to work on windows and linux (and possibly mac), so platform-independence would be nice.
The problem I'm having is that when I want to render to texture, if part of the area that I'm rendering to is covered up, the old color data is copied out. Would anyone happen to know of a way of either rendering to texture more reliably or to tell of torque is on top so I can tell it to render at a later time?
EDIT: I might also mention that it has to work on windows and linux (and possibly mac), so platform-independence would be nice.
#2
Reading back the framestore is *bad* for performance, especially for larger areas. Although this works and will give you best compatibility a better option is to use the OpenGL extension 'ARB_render_texture'. You'll have to setup this binding yourself within the engine (not something I can type out here).
Using this, you can configure a seperate card-based buffer to which you can render. You can then use this pretty much as you would a texture. The main advantage for this method is that it's *fast* as it doesn't involve transferring data from the card to the computer.
Unfortunatey, this will involve extending the OpenGL extensions but you can follow existing extensions that have been implemented within the code for a clue. I might mention that although I call this an extension, its ARB_ prefix shows that it's now part of the OpenGL core feature set.
- Melv.
01/18/2004 (2:26 am)
Chris,Reading back the framestore is *bad* for performance, especially for larger areas. Although this works and will give you best compatibility a better option is to use the OpenGL extension 'ARB_render_texture'. You'll have to setup this binding yourself within the engine (not something I can type out here).
Using this, you can configure a seperate card-based buffer to which you can render. You can then use this pretty much as you would a texture. The main advantage for this method is that it's *fast* as it doesn't involve transferring data from the card to the computer.
Unfortunatey, this will involve extending the OpenGL extensions but you can follow existing extensions that have been implemented within the code for a clue. I might mention that although I call this an extension, its ARB_ prefix shows that it's now part of the OpenGL core feature set.
- Melv.
#3
That'll at least tell you if youre drawing the full screen rather than a semi obscured version.
Ideally you want to render to texture using an arb extension I guess, but thats not going to work on all platforms I guess.
01/18/2004 (2:27 am)
You could make sure that the update region for the guiCanvas is entirely the size of the screen?That'll at least tell you if youre drawing the full screen rather than a semi obscured version.
Ideally you want to render to texture using an arb extension I guess, but thats not going to work on all platforms I guess.
#4
As it is, I'm not sure most hardware will support render to texture, so depending on the purpose it needs to be queried.
But the ARB extensions are easy enough to use, thank god!
01/18/2004 (2:30 am)
Melv, I dont think ARB actually means its a core feature, more that its an approved feature. It would probably be rolled into the next OGL version, but as far as I am aware ARB features are simply mechanisms to extend features without fouling things up, they arent CORE until the next GL specification makes them mandatory.As it is, I'm not sure most hardware will support render to texture, so depending on the purpose it needs to be queried.
But the ARB extensions are easy enough to use, thank god!
#5
Perhaps I didn't word myself correctly but this is what I meant. Without knowing the audience, it's difficult to be 100% accurate without going into 1000 words. ;)
I meant that being as it's an ARB prefix is a good indication of standard support across multiple vendors. Going from a vendor-specific prefix to EXT is a good indication of multi-vendor support and going from vendor or EXT prefix to ARB means that it is a standard OpenGL extension.
Just to be clear for Chris (from OpenGL.org):
Sorry if you already know all this muck Chris. :)
- Melv.
01/18/2004 (2:46 am)
Phil,Perhaps I didn't word myself correctly but this is what I meant. Without knowing the audience, it's difficult to be 100% accurate without going into 1000 words. ;)
I meant that being as it's an ARB prefix is a good indication of standard support across multiple vendors. Going from a vendor-specific prefix to EXT is a good indication of multi-vendor support and going from vendor or EXT prefix to ARB means that it is a standard OpenGL extension.
Just to be clear for Chris (from OpenGL.org):
Quote:For example, NVIDIA's abbreviation ("NV") is used in defining their proprietary function "glCombinerParameterfvNV()" and their constant "GL_NORMAL_MAP_NV". It may happen that more than one vendor agrees to implement the same extended functionality. In that case, the abbreviation "EXT" is used. It may further happen that the Achitecture Review Board "blesses" the extension. It then becomes known as a "standard extension", and the abbreviation "ARB" is used. The first ARB extension was GL_ARB_multitexture.
Sorry if you already know all this muck Chris. :)
- Melv.
#6
I'm not looking for speed, as I only have to RTT once. The image is then "cached" so I don't have to render all the time. So if speed isn't available, I can live with that.
Also, can I have a buffer of 1024 thru 4096 or maybe bigger? It would be nice to render the entire thing once instead of subdividing it and possibly getting seams.
No problem Melv, I know what you mean. However, you don't have to be overly specific with me because I generally know what I'm doing these days :)
I'll have to research this arb extension...it's not in any of my books.
01/18/2004 (8:55 am)
Okokok...I'm not looking for speed, as I only have to RTT once. The image is then "cached" so I don't have to render all the time. So if speed isn't available, I can live with that.
Also, can I have a buffer of 1024 thru 4096 or maybe bigger? It would be nice to render the entire thing once instead of subdividing it and possibly getting seams.
No problem Melv, I know what you mean. However, you don't have to be overly specific with me because I generally know what I'm doing these days :)
I'll have to research this arb extension...it's not in any of my books.
#7
01/18/2004 (9:14 am)
Hmmm....is this a windows-only extension? It really need to be able to work on other platforms...
#8
nVidia on RTT.
I must admit that the render to texture is one of the nastiest implementations I've seen for an extension e.g. the pbuffer extension stuff.
- Melv.
01/18/2004 (10:10 am)
Chris,nVidia on RTT.
I must admit that the render to texture is one of the nastiest implementations I've seen for an extension e.g. the pbuffer extension stuff.
- Melv.
#9
01/18/2004 (10:24 am)
That appears to be windows only (WGL) - is there a linux/mac version of this? I would really prefer platform independence rather than speed.
#10
Doh!
I must of had a hard day or something, I forgot about the pbuffer wgl stuff! Your best bet may be to either continue to read the buffer or perhaps use copy to texture which should be available in linux. At least the copy to texture will be much higher performance. The downside is that you'll only be able to render power of two sized areas, unless of course you use something like NV_texture_rectangle which is a nVidia specific extension.
I'm probably causing more problems here than you started with so you may want to consider simply using read-pixels. The problem you can encounter here unless you sort out a method within the scene-graph is to have a usable part of the framestore to use.
There would be various ways to do this, one being to add another sort type to the SceneRenderImages that preceeds even the skybox and insert the new SceneRenderImages as part of the objects prepRenderImage call. This method would allow each object to queue RTT renders although it is rather complex to setup.
Another method but not as flexible is to either hardwire or setup a queue for renders prior to traversing the SceneGraph.
Yet another method is to do it as Pat Wilson has done it in the thread link above. He reads the contents of the framestore (for restoration after the render), does the render, reads the result and restores the original framestore. As he agrees, this is *very* costly but you mentioned that this wouldn't be a problem so here's your winner. :)
Hey, these are just ideas floating around my head so sorry for the chaos... ;)
- Melv.
01/18/2004 (10:41 am)
Chris,Doh!
I must of had a hard day or something, I forgot about the pbuffer wgl stuff! Your best bet may be to either continue to read the buffer or perhaps use copy to texture which should be available in linux. At least the copy to texture will be much higher performance. The downside is that you'll only be able to render power of two sized areas, unless of course you use something like NV_texture_rectangle which is a nVidia specific extension.
I'm probably causing more problems here than you started with so you may want to consider simply using read-pixels. The problem you can encounter here unless you sort out a method within the scene-graph is to have a usable part of the framestore to use.
There would be various ways to do this, one being to add another sort type to the SceneRenderImages that preceeds even the skybox and insert the new SceneRenderImages as part of the objects prepRenderImage call. This method would allow each object to queue RTT renders although it is rather complex to setup.
Another method but not as flexible is to either hardwire or setup a queue for renders prior to traversing the SceneGraph.
Yet another method is to do it as Pat Wilson has done it in the thread link above. He reads the contents of the framestore (for restoration after the render), does the render, reads the result and restores the original framestore. As he agrees, this is *very* costly but you mentioned that this wouldn't be a problem so here's your winner. :)
Hey, these are just ideas floating around my head so sorry for the chaos... ;)
- Melv.
#11
1) Right before the playgui is pushed on. At this time, the Canvas is drawing to the FRONT buffer, so the back buffer is free to do whatever I want with it
2) Right before the MAP is pushed on. This would work just fine as you'd be garanteed that torque would have focus because it requires a keypress to get into it. However, the first time you'd do this, there might be a large delay, and large delays are generally bad in online FPS games, so I'd rather render on mission load.
So, having available screenspace without screwing with existing images isn't the problem.
The problem is that if torque doesn't have focus and part of the screen that I'm rendering to is covered up, nothing is able to be written to the framebuffer for some reason. I'm calling glFinish() right before I read from the buffer, so everything should be all prepped and ready to go for a read. So, if this is the case, I get the upper left corner of our loading screen tiled all over the place instead of an actual map (or a combination thereof).
At least if I can figure out a platform-independent (or how to do it for each platform) way of knowing that torque has focus before trying to generate the map, I can avoid the issue for the most part. Last night I hacked in a little thing that listens for the windows messages about focus and caching the last message to know whether or not it had focus, but I would also need to do this for linux (NO clue!) and possibly mac (even less of a clue!).
Any ideas?
01/18/2004 (11:09 am)
Actually, none of that is a problem. The only times I would need to render would be1) Right before the playgui is pushed on. At this time, the Canvas is drawing to the FRONT buffer, so the back buffer is free to do whatever I want with it
2) Right before the MAP is pushed on. This would work just fine as you'd be garanteed that torque would have focus because it requires a keypress to get into it. However, the first time you'd do this, there might be a large delay, and large delays are generally bad in online FPS games, so I'd rather render on mission load.
So, having available screenspace without screwing with existing images isn't the problem.
The problem is that if torque doesn't have focus and part of the screen that I'm rendering to is covered up, nothing is able to be written to the framebuffer for some reason. I'm calling glFinish() right before I read from the buffer, so everything should be all prepped and ready to go for a read. So, if this is the case, I get the upper left corner of our loading screen tiled all over the place instead of an actual map (or a combination thereof).
At least if I can figure out a platform-independent (or how to do it for each platform) way of knowing that torque has focus before trying to generate the map, I can avoid the issue for the most part. Last night I hacked in a little thing that listens for the windows messages about focus and caching the last message to know whether or not it had focus, but I would also need to do this for linux (NO clue!) and possibly mac (even less of a clue!).
Any ideas?
#12
Here's a slow, but cross platform idea. Clear the framebuffer to some color before you render, then read back and make sure you were able to fill the entire window. If so, you're clear to do your RTT operation.
01/18/2004 (11:20 am)
Checking for focus isn't really enough either, since it's possible to have the input focus while an always on top window is drawing on top of torque.Here's a slow, but cross platform idea. Clear the framebuffer to some color before you render, then read back and make sure you were able to fill the entire window. If so, you're clear to do your RTT operation.
#13
01/18/2004 (11:31 am)
That's exactly what I was thinking, but I was having a very hard time implementing it. I would try 2 drawing 2 different colors and reading them back, but I couldn't seem to get that to work right. I probably wasn't drawing in the right place or something.
#14
01/18/2004 (12:17 pm)
In case you're interested, I seem to recall you can go the pbuffer way if you're only targeting Panther on MacOS X (ie 10.3 onward)...
Torque Owner Edward Smith
Silencersoft
http://www.garagegames.com/index.php?sec=mg&mod=resource&page=view&qid=4410