N00b Question about drawing on images.

BlitzMax Forums/BlitzMax Beginners Area/N00b Question about drawing on images.

Grey Alien(Posted 2006) [#1]
OK the answer is probably something to do with PixMaps or Indiepath's Render to Texture module.

Basically in BlitzPLus you could create an image and point all drawing commands at it with SetBuffer, then you could draw on the image. You could then point back to the backbuffer with SetBuffer BackBuffer() and then draw your new image anywhere you wanted.

How do I do this in BlitzMax please? You can't draw and draw fonts (DrawText) onto anything except the backbuffer can you? I don't want to make custom PixMap drawing routines. Am I supposed to draw on the backbuffer anyway, then grab what I want into an image, and cls the backbuffer so it never gets flipped?

It's just that grab image for say a full-screen 800x600 image takes ages, around 200-300ms. This is an unacceptable pause. See imagine you want to draw your screen onto an image so you can then show that image shrinking away or spinning or whatever. Having a 300ms delay after a user clicks a button while the code draws the screen and calls grab image is just rubbish.

Any ideas? Thanks.


ImaginaryHuman(Posted 2006) [#2]
Well, it's a commonly asked question. If you just want to spin or shrink what's drawn, at least in GL you can set up the projection matrix to draw everything rotated and zoomed on the fly. Not sure about DX.

If you're trying to do other things like grab text etc, basically you will have to draw it and grab it. I'm not sure what process grabimage uses, whether it turns it into a pixmap first then uploads. In GL using glCopyTexSubImage2D() seems to be hardware accelerated on my iMac at least and can grab a whole screen into a texture and redraw the texture without dropping below 60fps.

Otherwise you'd have to look into using actual rendering to textures, pbuffers, etc.

Why would you want to draw text to a buffer, grab it, then draw it again? Why not just draw it once where it needs to go?


Grey Alien(Posted 2006) [#3]
Yes, I guess I could draw it all where it needs to go rotated and scaled etc, it's just that all my drawing code for that screen would need to be special etc. It just seems easier to draw onto a single image and then just manipulate that with 3D card commands instead, but not iff the initial grabbing is slow...


bradford6(Posted 2006) [#4]
what you ned to decide is:
1. how much of this can be pre-processed. If you are displaying a fixed image/text you can do it in an image editor and just display that
2. can you divide the screen into "change zones", where you grab and change only the sections that actually change.

full screen grabs are slow no matter how you cut it. your job as a programmer is to figure out a faster approach to get the desired result.

one idea is to use a "background" image tat never changes and a foreground image that moves. I'll knock up something later


ImaginaryHuman(Posted 2006) [#5]
You dont need to grab the whole screen, you only need to grab the area that you want to update, and you copy it to a pre-existing texture that was created with Null as the pointer to the data. You call glTexImage2D() to set up the texture space, then subsequent calls to glCopyTexSubImage2d() will copy only the rectangle you want into the existing pre-allocated texture memory. This is the fastest method supported in gl 1.2. Any other technique you'll have to use extensions. If you are using GrabImage, that's probably grabbing the entire display, plus it may be putting it into a pixmap first and reuploading it as an image. (maybe not).

I am curious what will be behind the text that you render, that makes you think you'll need to draw it and then grab it. Can't you just upload the text as an image?


Grey Alien(Posted 2006) [#6]
Bradford6: Yeah unfortunately preprocessing isn't an option as I want to have it dynamically scale, rotate etc based on my timing routines. Again, If I want to spin the entire screen (and it's made of many things drawn on it), change zones won't work, thanks anyway.

AngelDaniel: If I wanted to draw a title screen (with menu etc), then when the user clicks a button, make it spin off, I'd have to grab the entire screen which is too slow with GrabImage because it downloads it from the video card to ram evidently and probably reuploads it. I don't really want to write OpenGL code as my default driver is DirectX. Also if I write using special DirectX stuff then it won't work in OpenGL, and my framework supports both. Maybe I'll have to write it in both and choose the correct function depending on the current driver, what a pain... It's not just text I want to render, it's images and text, several things that make up a "screen". Then I want to be able to grab that screen and transform it as a whole instead of transforming all the individual elements. But perhaps that is actually the way to go, it's just a pain too...

I would just like a keyword in BlitzMax that lets me create a new image and then divert all drawing to it and it works in OpenGL and DirectX and isn't slow ... sigh. In fact I'd pay money for it.


TartanTangerine (was Indiepath)(Posted 2006) [#7]
I would just like a keyword in BlitzMax that lets me create a new image and then divert all drawing to it and it works in OpenGL and DirectX and isn't slow ... sigh. In fact I'd pay money for it.

Yeah but images are in fact textures so you need a function that lets you render to that texture. I think they call it render to texture :) And yeah mine is DX and OGL
Strict

Import Indiepath.Render2Texture

HideMouse()
SetGraphicsDriver GLMax2DDriver()
Graphics 640,480,0

tRender.Initialise()

AutoMidHandle(1)

Local logo:Timage = LoadImage("bmax160_2.png",MIPMAPPEDIMAGE|FILTEREDIMAGE)
Local myImage:TImage = tRender.Create(128,128,MIPMAPPEDIMAGE|FILTEREDIMAGE)

tRender.TextureRender_Begin(myImage)
   Cls
tRender.TextureRender_End()

SetBlend(ALPHABLEND)

Local ii:Float = 0

While Not KeyHit(KEY_ESCAPE)
   
   SetBlend(ALPHABLEND)
   SetAlpha(1)
   tRender.TextureRender_Begin(myImage)
   Cls   
      SetRotation(ii)
      DrawImage logo,320,240
   tRender.TextureRender_End()


   tRender.BackBufferRender_Begin()
   Cls
      SetRotation(ii)
       DrawImage logo,320,240
      SetBlend(ALPHABLEND)
      SetAlpha(0.7)
      SetRotation(0)
      DrawImageRect myImage,-20,-20,680,520
      SetAlpha(0.4)
      SetBlend LIGHTBLEND
      DrawImageRect myImage,-40,-40,720,560

   tRender.BackBufferRender_End()
   
   Flip
   ii:+1
   
Wend



Grey Alien(Posted 2006) [#8]
I was waiting for that ;-), now all I need is the module ... How much is it? wanna trade? No wait can't. I need to get an equivalent (my own) working in my framework so I can sell it...


TartanTangerine (was Indiepath)(Posted 2006) [#9]
It's free, talk to me about a license - But do it in the morning :)


Grey Alien(Posted 2006) [#10]
but I might get a good deal from you now ;-)


BlackSp1der(Posted 2006) [#11]
free rendertotexture from Diablo, but only for OpenGL.

http://www.blitzmax.com/Community/posts.php?topic=58765#654938


Grey Alien(Posted 2006) [#12]
well that's half of it, thanks. Maybe I can figure out the DirectX version (if I have a spare week).


TartanTangerine (was Indiepath)(Posted 2006) [#13]
What part of FREE was misunderstood?


smilertoo(Posted 2006) [#14]
I think the confusion is between its free, and contact me for a license.


Grey Alien(Posted 2006) [#15]
yeah that's it. You know how it is, as a developer you always have to look at the small print attached to "free". Tim if it's free great, but I'd need to include it (or a bit of it) in my framework, and therein lies a potential problem, unless it's 100% free i.e. no licence restrictions...