Render to Texture
BlitzMax Forums/BlitzMax Programming/Render to Texture
| ||
Source code: Render 2 Texture Hi all, As a result of a request for a 'render to texture' feature for BlitzMax I've made an initial effort just to get the ball rolling to see how it develops. Consider this an early alpha test just to get some initial feedback on if it works for your setup, and if you like the code that you need to write to get it working, or if anything drastic needs to be changed etc then to know at this stage would be better to know now than later. The main goals behind this effort are... 1. Create a unified single command set to allow creating and rendering to a texture for the GLMax2D, D3D9Max2D and D3D11Max2D graphics drivers. This is to aid keeping the underlying technique as transparent to the user as possible. D3D7Max2D is considered too old for todays current hardware so there will be little interest in writing code for this driver. Other drivers, for example the SDL driver for MaxNG, will be considered when the time arises. 2. The command set should be as small as possible, down to some simple create and use functions. The less the coder does means it will be easier and less confusing to use. 3. Operate seemlessly with all of the current Max2D drawing commands with as little impact on any code changes as possible. 4. Work with both the legacy BlitzMax compiler and Bruceys MaxNG compiler. Current development will be using the legacy compiler before writing the code for the MaxNG compiler. There are some module tweaks that I know will be needed for this to be finalised but just for now I'll save them for later. I'd prefer at this early stage for people not to mess with modules just yet and they are only a small tweaks, but do have a major impact on functionality. As it is things are working on my set up but YMMV. Issues that will be fixed with the module updates are... 1. 2. 3. So all in if you wouldn't mind having an initial play that would great just to see how things are initially. Cheers! ps In the source code there are some example files. These are little demo apps just to get something up and running on screen. Feel free to change the Max2DDriver to see if its initially working on your setup. All feedback is very welcome. |
| ||
A working 'render to texture' in Blitzmax has existed for almost a decade btw. Searching the forums and code archives will yield working versions. |
| ||
There existed solutions but they were only OGL or DX...with different commsndsets and no interchangeability Also it is good to have this done by someone who did a dx11 mod... Will try to test the code tomorrow when at my computer again. Bye Ron |
| ||
Yes, I should have outlined the main reasons behind why this little project popped up, thanks Derron. I've edited the first post accordingly. |
| ||
Here is a another simple sample:Strict Import "renderimage.bmx" SetGraphicsDriver GLMax2DDriver() 'SetGraphicsDriver D3D9Max2DDriver() Local gc:TGraphics = Graphics(800, 600) SetBlend AlphaBlend Local rt:TRenderImage = CreateRenderImage(gc, 800, 600) SetRenderImage(rt) Cls SetRenderImage(Null) MidHandleImage(rt) local currentRotation:int = 0 While Not KeyDown(KEY_ESCAPE) ' render into the texture SetRenderImage(rt) SetRotation currentRotation SetScale 0.90, 0.90 DrawImage(rt, GraphicsWidth()/2, GraphicsHeight()/2) currentRotation = (currentRotation + 5) mod 360 SetScale 1.0, 1.0 SetRotation 0 DrawOval(0,0, 10,10) ' switch back to render to the original backbuffer SetRenderImage(Null) Cls SetColor 255,255,255 DrawImage(rt, GraphicsWidth()/2, GraphicsHeight()/2) DrawText "Render 2 texture: " + GetGraphicsDriver().ToString(), 0, 0 Flip Wend End PS: wonder why your DrawImage(rt), MouseX(), MouseY() works (see main.bmx) ... I mean the closing bracket after "(rt". Maybe "DW" could come up with some nice samples (as he enjoys the single-buffer-approaches). bye Ron |
| ||
PS: wonder why your DrawImage(rt), MouseX(), MouseY() works (see main.bmx) ... I mean the closing bracket after "(rt". That's actually a typo and should have been DrawImage(rt, MouseX(), MouseY()) I'm in a transitional period of putting parenthesis around the outer function parameters for all functions, not the individual parameters themselves but in the same way as a C language variant requires them. The reason it works in that each of the parameters are expressions so (rt) is just a normal expression. All blitz languages have the feature of only requiring the outer most parenthesis when you want the value returned from the function, if you don't want the return value then you don't need them. In this case it works according to that feature. |
| ||
Regarding DX7 Is it that much "work" or just a slight lazyness (its weekend!)? Just asking because DX7 is an "official module" of BlitzMax. So if one wants to "support" DX7 they could not just use that r2t. But I assume this would be the same for some kind of generic "shader support" (which is another "wish" - for some effects many casual games have - like blurred/desaturated backgrounds when a menu is open). So if no means no ... I will accept that ;-) bye Ron |
| ||
So if no means no ... I will accept that ;-) Heh, It's open source feel free to implement Dx7 if you want to and we'll include it in but yeah I personally can't be bothered to support it at this time due to a number of reasons. I never say 'never' though :D A similar style of functions for a unified shader set could be created in due course. |
| ||
Seeing this does not really look similar to yours. Maybe DX7 needs a bit more "done" to make it work. According to that gamasutra article there are multiple ways to achieve that render-to-texture functionality with DX7. I dumbfully thought of an easy transition (replacing D3D9*** with D3D7***) ... but hey if that was so easy, you would already have done it :-) bye Ron |
| ||
What's your thoughts on handling this scenario? The Dx9 render targets need to be destroyed and recreated when transitioning using alt-tab when in fullscreen mode. The problem is that any data that's in a render texture will be lost when the texture is destroyed. The destruction and recreation code is done and automatic but what's on my mind is handling any existing texture data. So I was thinking of having these 2 options 1. to have a callback function that will allow the coder to put texture data back into the image if they want any specific data in it at that time of the transition. 2. have a convenience function that when called would take a 'snapshot' of the current texture data, this would be used to automatically recreate the texture so that it survives the destruction and reconstruction phase. A side effect of this would require another function if a coder then wanted to change their mind and send the texture to option 1. The 'snapshot' feature may turn out slow and may not be suitable for every frame due to the nature of pulling data from the gpu being an inherently slow process anyway. What's your thoughts on this? EDIT As it happens I think I have a way to handle this completely automatically so that the texture survives the transition every time... time for some sleep though. |
| ||
Re Scenario If you talk about the multiple approaches: I would try to use the most simple one even if it wont work on all HW. @ Destroying textures How do you intend to inform each texture about the "onDestroy" and "onRecreate" (or similar? Shouldn't this need some kind of event system or "texture manager" which knows every texture? Without that I can only imagine a "if myG <> GetGraphics() then RecreateMyself()"-approach. bye Ron |
| ||
.double post |
| ||
@Texture management One of the reasons I created the TRenderImageContext was in case any kind of regular 'boiler-plate' code crept in, which it did almost immediately. It also serves as a nice place for texture management :O) I've updated the repo to include the dx9 render-texture persistance through the alt-tab scenario. If you wouldn't mind testing when you get some time, that would be cool. Cheers. Still more to do for dx11 :p |
| ||
I've upped the modifications required for dx11 to the repo in my sig. I noticed that in your example you're binding a render target and then rendering the texture of the render target into itself. I know that this is a No-No in Dx11 and will not work. |
| ||
Also just upped a fix to allow changing graphics drivers while the code is running. |
| ||
@ drawing rt into rt How to tackle this then? How to have something like that "Mirror in a mirror in a mirror ..." thing? With defeault you have to copy an image first because you else modify the source when writing to the target. Another classic approach (single buffer) is Draw - grabpixmap - draw grabbed Flip Draw ... PS: did not have had time for DX9-tests, preparing next main-release of my game and some users brought up "need!!!"-features ;-) bye Ron |
| ||
How to tackle this then? You would normally have 2 textures. The one that you want to render, and the one that you want to render into, except that don't clear the render-texture between frames? |
| ||
But this would add another draw each loop (the one of the "non-render-target-texture")?! switchActiveTex(tex1, tex2) drawOnActiveTex( inactiveTex ) drawOnActiveTex( the added stuff ) flip Hmm, that should work. Glad I would use it more for bringing together "components" of an composite image (eg. skinnable GUI-widgets) . Wonder where DW is once we need him to test this properly with his effect-demos :-) bye Ron |
| ||
You can swap the textures between two renders (the one to happen and the one to render to) CurT = T1; T1 = T2; T2=CurT Render on T1 buffer with T2 drawn inside CurT = T1; T1 = T2; T2=CurT Render on T1 buffer with T2 drawn inside etc ... You'll maybe notice the current frame showing the previous frame so it may feel laggy or not. |
| ||
Glad I would use it more for bringing together "components" of an composite image That's the main idea behind it with the ability to do that in the main loop if you choose to. 'render-to-texture' came about initially for reasons such as rendering a scene into car mirrors, rendering a video to a texture that's used for a tv screen, viewing through a 'warp portal' and other fun stuff :o) There will always be 1 extra draw call to draw the texture itself after rendering into it. |
| ||
Hello. Yep, I'm still here. With questions - always. :) I just need a simple example, preferably, without calling a library. I have the working code for the example HERE: http://www.blitzbasic.com/Community/posts.php?topic=107224 Which is almost perfect. I just need to be able to have BLACK $000000 show through as transparent instead of opaque as it is now, and anything brighter than $000000 such as $010101 to show as black opaque. If I can get someone to make a fix in the code 107224 to do that, then that will be fine for me, answers my question, and opens up the easy ability to write directly to TIMAGES as screen objects. |