How to render to Texture
Monkey Forums/Monkey Programming/How to render to Texture
| ||
I'd like to save tracks, trails of units, save corpses, blood the floor and stuff like that. Now I let the object remain, however it seems that will only work to a certain extent. Eventually 10 of 1000's of images will need to be rendered, I assume there is a limit here especially on mobile devices? Do I need render to texture to do this? Is there another way? Thanks |
| ||
I would recommend drawing less. Currently there is no render to texture in monkey. There might be a user module for some targets. |
| ||
http://www.monkeycoder.co.nz/Community/posts.php?topic=3130& |
| ||
it would be nice in html5 if i could pull images from my website, then i'd just let php's Glib do all the work |
| ||
I think the standard approach is to only keep a certain number of such 'decorations'. You'll notice in many shooters that bullets leave marks on the wall, but if you keep spraying bullets in one place the old marks will start to disappear. I don't believe there is any advantage rendering to texture for this, even if you can. |
| ||
The advantage would come if you can keep re-rendering the "decorated" image. For example, if you put the whole background into a buffer and just render blood splatters or explosion marks or whatever into that buffer. |
| ||
This is something I've been wrestling with off and on for quite a while now. It seems just about impossible to do this in real time in HTML5, because, and please correct me if I'm wrong, the Image objects are immutable. So any time you want to draw to an image, you have to draw the old image to a separate canvas, make all your additional draw calls to the canvas, create a new Image object with this canvas as its source, THEN wait for the image to load before you can do anything else to it. I've been mulling over an idea in the past couple days that involves caching individual draw calls and only drawing the render target once it's finished loading. But that is a lot of work to appease one target, as the other targets are much more render-target friendly. Anywho. That's my HTML5 rant. I will continue to take jabs at it and maybe I'll have something to show in the coming weeks, who knows. Really, they just need to make the API mo bettah. |
| ||
What level of performance issues are you seeing? I don't use the technique to do much other than cache UI text but a quick test looks usable. Go here, click to switch to rendering from a buffer and then use the spacebar to add decals in random positions. |
| ||
Yeah, that is a good way to do it. The challenge I'm facing is turning that off-screen canvas back into a mojo image without any hiccups. |
| ||
Why do you need it to be a mojo Image instance? |
| ||
Just for ease of use. Right now I'm trying to create a simple DrawImageToImage function using mojo images. As I said, it's a challenge. But I suppose that's the real reason I'm doing it; to see if it can even be done :P |
| ||
to see if it can even be done Only if you hack it. You see, Mark made "surface" private for the Image Class. So the monkey compiler won't touch it from any other monkey routine that you write. You need surface in order to pass from monkey to native code (which could then easily combine images). The only way around this is to use the OpenGL monkey extension LoadImageData. |
| ||
Hmm, I didn't realize the OpenGL module now supports HTML5. Thanks, Adam! You've given my life new direction :P |
| ||
Hi, Ok, I've made a bit of progress on this front lately. I haven't implemented the whole render-to-texture thing, not only because I am concerned about getting it working reliably everywhere (I *have* tried before!) but also because there are issues with how to write arbitrary alpha values (which may or may not need to be pre-multiplied) which may be important depending on what you're doing. Anyway, next release will have a few new commands for reading/writing pixels, ie: 'create a new image...single frame only? Function CreateImage:Image( width,height,flags ) 'read from 'backbuffer'... Function ReadPixels:Void( pixels:Int[],x:Int,y:Int,width:Int,height:Int,arrayOffset:Int=0,arrayPitch:Int=0 ) 'write to image...must be a CreateImage image. Method Image.WritePixels( pixels:Int[],x:Int,y:Int,width:Int,height:Int,arrayOffset:Int=0,arrayPitch:Int=0 ) ...so you can implement 'GrabImage' with something like: Local buf:=new Int[w*h] 'probably want to use a cache ReadPixels buf,0,0,w,h 'read from back buffer img.WritePixels buf,0,0,w,h 'write to image Since the pixels go through an array, you can mess with them on the way, eg: you could implement a 'mask color' etc. Performance seems to be good on all targets, possibly not good enough for realtime 'every frame' image updates, but I guess that depends on your needs. I've had to add an XNA_BACKBUFFER_ACCESS_ENABLED config setting for XNA, as to be able to read the backbuffer you need to do some tricky stuff. This does appear to slow things down a bit, but not massively. This may in future be expanded for use with data buffers (although there's no such thing in XNA yet) but for now I think this approach provides a great deal of flexibility combined with reasonable performance. I may also add WritePixels to back buffer and ReadPixels from image later, but you can sort of fake that with the existing additions already. |
| ||
One way to do this sort of thing is with prerendered images containing a number of static bloodsplats or whatever, which you then set at random rotations and draw two of them on top of each other with transparency. This way, because of the combination of the two different images at different rotations, there are large numbers of possible final images. Lots of bloodsplats in unpredictable configurations. This is obviously a hackaround and not ideal but in many applications I doubt if anyone would even notice. |
| ||
This is great news Mark. Its was one of the biggest things (for me) that's missing from monkey. I look forward to the update :) |
| ||
Thank you Mark, this will be very helpful for fast rendering text. Ok, the building of an "text-image" will need more time at first, but will save a lot of performance during a game. This could also be very helpful for a collision system, or? |
| ||
Hi, > This could also be very helpful for a collision system, or? Actually, I didn't think of that, but yes! You could theoretically draw/grab images and create precise collision data... |
| ||
I agree by the way, it would have helped me (may still help me) on my present project. |
| ||
brilliant render to texture! |
| ||
(sort of) |
| ||
Excellent, my most-wanted addition! |
| ||
haha yeah (sort of) is still good :D |
| ||
Great news! |
| ||
Thanks,Mark! I am waiting for this too! When the update will be available? Sincerely, vbnz. |
| ||
excellent news :) StuC |
| ||
Best news! :) Most wanted feature. So we'll be able to draw direct to alpha channel of image? |
| ||
This is fantastic! It will allow me to port one of my most successful games to Monkey and finally release it on iOS!!!! Can't wait. |
| ||
Great news - this was my most wanted feature! |
| ||
Thanks this is good news! Image.ReadPixels will be a very handy future addition. Will this work on loaded images as well or only on images created with CreateImage? It would be very useful if there was a way to use WritePixels and ReadPixels on either. |
| ||
Will there be a direct load option also, to read into this type of image from a standard graphics format? |
| ||
I am at the same point now. Can we expect a ReadPixels and WritePixels methods on an image created with LoadImage()? |
| ||
I doubt it. It would be nice to have a CreateImageArray:Int[]( filename ) though. [Actually you'd ideally want an ImageArray class that contained width and height as well as an array, though I guess a couple of globals that could be polled after loading would do too.] |
| ||
If the CreateImage function could be passed an array of pixels that would open up a lot of things. For now this stuff seems to assume you want to read everything via ReadPixels. |
| ||
It is in effect passed an array of pixels; it just happens in two steps. I think what you are looking for is a function like ReadPixels, only operating on a loaded Image instead of the back buffer. |
| ||
under the "opengl" module, there is a hidden function called LoadImageData(filename, info[]) that will return a buffer, then you can send the buffer to array to an image.WritePixels(). |
| ||
I think what you are looking for is a function like ReadPixels, only operating on a loaded Image instead of the back buffer. Yes you are right. It would be a very good feature. |
| ||
under the "opengl" module, there is a hidden function called LoadImageData(filename, info[]) that will return a buffer, then you can send the buffer to array to an image.WritePixels(). Thanks, i will look into it. |