How do you draw on textures?

BlitzMax Forums/BlitzMax Beginners Area/How do you draw on textures?

Kimor(Posted 2015) [#1]
Say I load 2 textures called ball and player, and then want to draw one in the other one, and have it stuck there for whatever use.

In BlitzPlus you did something like this

Graphics 640,480
dot = loadimage("dot.png")
player = loadimage("player.png")

; draw on texture instead of on the screen
setbuffer player
drawimage dot,5,5

; draw on the screen
setbuffer frontbuffer 
drawimage player,100,100
waitkey


How would you go about doing that in BlitzMax using drawing to textures?


Derron(Posted 2015) [#2]
Loop over every pixel of the target image's pixmap, multiply the source color with the source image's pixmap-pixel's color and store it in the target image's pixmap pixel.

Commands:
pixmap:TPixmap = LockImage(image)
color:int = ReadPixel(pixmap, x,y)
WritePixel(pixmap, x,y, color)

A more complex sample of how to do that is given there:
Function DrawImageOnImage:int(src:object, dest:object, x:Int, y:Int, modifyColor:TColor = null)
https://github.com/GWRon/Dig/blob/master/base.gfx.imagehelper.bmx

TColor is a custom Class, you could replace it with "r:int, g:int, b:int" or "color:int" (and then using the ARGB_Red(color), ... functions)

bye
Ron


RupeB(Posted 2015) [#3]
Isnīt Pixmap slow and software based? Or is it hardware that draws a texture onto another texture?

I think the way to do it texture to texture is via DrawSubImageRect but Iīm quiet new myself with BlitzMAX.


Derron(Posted 2015) [#4]
There is some render2texture code available in the forums...but just for dx9.. OR ogl. For dx7 you need to tinker on your own. Both use different function names
R2T would use hw accel.

My code uses software rendering...as it works crossplatform...but not useful for realtime.

Bye
Ron


RupeB(Posted 2015) [#5]
What API does standard BMAX support out of the box really?
I thought DX7 DX9 DX11 Opengl version high enough for shaders?

As I can see there are few ways

* DrawSubImageRect (but I guess at a lower level it does one of the things below?)
* pixershader
* vbo
* pbo which is not for off-screen rendering it's just for asynchronous texture writes/reads) bad choice
* glCopyTexImage2D (which is not a real render2texture or renderbuffer) bad choicce
* pBuffer is deprecated standard bad choice

It seem there was a module 9 years ago called Indiepath.Render2Texture thatīs totally vanished, I wonder what that technique module used. Any chance for the source? All links Iīve seen are dead and some places even says the person sold licences so it might gone that direction.


Nurgle(Posted 2015) [#6]
This is Kelptos render to texture code.



Derron(Posted 2015) [#7]
Softwarerendering might benefit from not needing any GPU at all (even not a virtual GPU like provided by some software for some time now).


DrawSubImageRect is something completely different: it allows to draw a portion of a whole image - compared to DrawImage(), which draws the complete contained texture.


bye
Ron


RupeB(Posted 2015) [#8]
Ah nice, so itīs like an textureatlas? would it be allright to truly look at it and use it as that?

About GPUīs, but everything and their grandfather DO carry a GPU since I-donīt-know-when?
The high graphic resolution is not made for CPU' you couldn't even fake low resolutions and stretch it fullscreen with a CPU.
You would have problem to even fill a 640x480 with a highend computer.

It would probably work if quality memory was used as the main memory and a bus to match it, but thatīs never the case.
All truly fast memory ends up as either CPU cache or GPU memory.

I guess thatīs whey I plotted using software in Blitz3d using a the restriction of 5000-15.000 pixels to have reliable 60 fps stream via
software only, but most people would shun at that. When you have 1920x1080 to fill it doesnīt do as much as you would wish for so I understand them completely.

I miss the time when computer where simple embedded systems that had no jerks and was powered and built to match what they where meant to be used for.

Sorry about the rant, I love this product, I remember Blitz II on the old Commodore. BLITZMODE and you had 100% control over your systems. Those where the days.


Kryzon(Posted 2015) [#9]
Why can't you just composite the ball on top of the player each time you redraw the screen? You're going redraw the full screen anyway.
Then you don't have to worry about messing with pixels and dynamic images.

If you say 'have it stuck there for whatever use' (a persistent graphic of the ball on top of the player), I'd do that in an art program.

If you intend to change the ball on top of the player to something else later (a different type of ball image, for example), it's much easier to do it like I said above, by clearing the screen, drawing the player and then whatever you want on top of the player. Then Flip the screen for the user to see. That's your frame rendering logic.


Kimor(Posted 2015) [#10]
Hey there, and thanks for att those ideas and code. Much appriciated
Kryzon ya, for some reason this was a bad example explaining that goal,

but I cannot do that (well i COULD) but I won't, because this ball is gonna be painted
ALOT of times (and Itīs not static) itīs bit involved, I really need that indirectness of painting on a texture.


RupeB(Posted 2015) [#11]
I'm gonna have a try that VBO code.

Perhaps there is a way to draw a part of a texture ontop of itself? Instead of another texture ontop of another texture. That would work aswell.


RupeB(Posted 2015) [#12]
I would try that VBO code. I think thatīs the best bet.

Perhaps there is a way to draw a part of a texture ontop of itself? Instead of another texture ontop of another texture. That would work aswell.


Kryzon(Posted 2015) [#13]
I still don't understand what you're trying to do -- there may be other solutions like a pre-rendered animation etc.

In any case, TImage has a Lock( frame ) method that returns a pixmap representing the image.
Call Lock( ball, 0 ), manipulate the pixels of the pixmap, then call Unlock( ball, 0 ) (which does nothing by the way), then draw the image.

Note that this would be faster if you handled the locking and uploading yourself with API calls. The standard BlitzMax way throws out the old internal image data and it accumulates until it is garbage collected. There is a small performance penalty from this.
To manipulate the pixels of the pixmap, first read the documentation in the IDE from Module Reference -> Graphics -> BRL.Pixmap, then use function PixmapPixelPtr to obtain a pointer to the pixmap pixels.
The formula for accessing a single pixel as an unsigned integer is:

pixmapPixels:Byte Ptr = PixmapPixelPtr( pixmap )
singlePixelRGB:Int = pixmapPixels[ x + y * imageWidth ] 'It's a value like #FF00AAGG. Be aware of the pixmap format.


Kimor(Posted 2015) [#14]
Itīs hard to describe
This exe with some test zelda tile graphics shows the actual effect.

http://www.filedropper.com/double

Look for the moving tiles that moves *within other tiles*, thatīs the effect thatīs sought after.


Derron(Posted 2015) [#15]
Without looking: if you just draw "tile A portion" on "tile B" this is doable via "DrawSubImageRect".

I thought of something more complicated. So I am eg. drawing images on a background image to keep draw calls down a bit. This is a "one time"-job per game (depends on how the game setup is).

I also use this to procedurally create sprite atlasses (first, tint the team-color areas of a figure, then draw the whole figure sprite on a bigger figure-sprite-atlas, afterwards render all figures..this saves texture switches).


bye
Ron


Kimor(Posted 2015) [#16]
That sounds great! but that wouldīt ALOT of DrawSubImageRect, lots of OpenGL calls (or dx). How would I go about to make it batched?


Brucey(Posted 2015) [#17]
You can use shaders to batch things up nicely.


Kimor(Posted 2015) [#18]
Brucey Looked at your modules I must say that youīve written an amazing collection of code. It seems like lots of you ppl had done more than your share of programming. Iīm not really that good at reading complex code right yet is there any simple examples of doing those kind of batching techniques using shaders that I could learn from?


Kryzon(Posted 2015) [#19]
You can still do it with fixed-function, more easily so in my opinion.
To batch you do the drawing yourself with raw API calls, but given the original question of this thread I imagine that's out of the question. If you'd rather hire someone to write this for you, drop me an e-mail.

The Max2D source code is a good way to learn how the rendering is done.
https://github.com/maxmods/brl.mod/blob/master/glmax2d.mod/glmax2d.bmx#L208


Kimor(Posted 2015) [#20]
Iīm not very wealthy so I guess I'll try to grasp the source then. I see a lot of it is in common with the VBO above aswell. So I should be okay.

Shader has an advantage though because you COULD change the colors in one go.


Kimor(Posted 2015) [#21]
You could do almost anything in one go, actually. Damn that IS tempting.

VBO & Batching, have what better qualities over shaders? I need motivation to learn those instead of shaders now.


Kryzon(Posted 2015) [#22]
I'll tell you what I wish someone had told me: that you shouldn't learn any of those, since your apparent goal is to make a game and not a game engine.
You need a game engine that has the features you need so you only worry about your game looking good and being fun, while the engine handles the internals for you.


Kimor(Posted 2015) [#23]
True, what works works and thatīs all that matters.


RupeB(Posted 2015) [#24]
I often get abit nerdy aswell, about programmiong and details because I have such a deep curiousity for how things do work and fory finding you know, "perfection"?

'You know what I mean. Details such as frame hickups literally gets to me somewhere deep inside haha. When one get that kind off OCD thing and want something, just remind yourself of this one phrase;

The software developer who TRULY cares for performance, designs their own hardware.

;)


RupeB(Posted 2015) [#25]
I would certainly go for that to VBO example to emulate what you did in that exe.

Also think about this: you could use the VBO buffer as an offscreen buffer to put all your tiles all at once,
and then splat it on the screen all in one go, at a non-integer coordinate, making for very smooth scrolling
and still have a nice pixel layout of everything in the buffer if you need to access it.