### Author Topic: [Tutorial] Optimize pixel-by-pixel drawing  (Read 1597 times)

0 Members and 1 Guest are viewing this topic.

#### Matrefeytontias

• Axe roxxor (kinda)
• LV10 31337 u53r (Next: 2000)
• Posts: 1982
• Rating: +310/-12
• Axe roxxor
##### [Tutorial] Optimize pixel-by-pixel drawing
« on: June 21, 2013, 09:22:36 am »
Hallaw,

When you have to draw a great part of the screen pixel by pixel (like for a game of life), the program usually become reaaally slow, since Axe is not good at pixel drawing. So I've thought of a method to greatly speed up this kind of tasks.

So, how does it work ? You know that the TI-z80-s screen (excepted the 84+ C) takes 1 byte to code 8 pixels, so that 1 bit = 1 pixel. The technique consists in calculating each pixel as we would do normally, and then turn on or off the corresponding bit of a variable instead of turning it on on the screen (which is absolutely slower). Then, when the 8 bits of the variable have been modified the way you wanted, you can directly store the variable in the corresponding byte of the buffer, thus turning on/off 8 pixels at a time. Of course, this'll only work if the width of area you want to paint is a multiple of 8.

So let's do it !

Let's say that our function is named BuildByte, since that's what it does.

First, we need a counter. This counter must send a signal every 8 times we call it.

:.Only once
:0→C
:
:Lbl BuildByte
:If C++^8
:.The counter doesn't send the signal
:Else
:.It does
:End
:...

Then, we need the variable which will contain the pixels data :
:.It must be initialized to 0 at the beginning of the program
:0→B

Say that the function BuildByte takes three arguments, the X-coordinate of the byte where the pixel must be drawn (not the pixel, so it must be a number between 0 and 11), the Y-coordinate of the pixel (between 0 and 63), then 0 if the current pixel must be white, or 1 if it must be black. We need to put this 0 or 1 to the corresponding bit of B. Then if C is a multiple of 8, then it means that the 8 bits of B have been set, and we store B in the corresponding byte of L6.

But how do we do set the corresponding bit precisely, and not any other bit ? It's actually pretty simple : we always set the first bit, and then if C modulo 8 is not 0, we shift B left once. Why that ? After 7 shifts, the first pixel/bit you passed to the function will become the last bit → the first pixel of the byte when it's on-screen.

:Lbl BuildByte
:.r1 is the X coordinate
:;r2 is the Y coordinate
:.r3 is the value of the pixel
:
:r3 or B→B
:If C++^8
:B*2→B
:Else
:B→{r2*12+r1+L6}
:0→B
:End
:Return

Remember that this will be efficient only if a relatively high number of calculations are needed for each pixel. For example, this plasma program I wrote a while ago uses this method (attached screenshot runs at 6 MHz).

« Last Edit: June 21, 2013, 09:24:01 am by Matrefeytontias »

#### Streetwalrus

• LV12 Extreme Poster (Next: 5000)
• Posts: 3821
• Rating: +80/-8
##### Re: [Tutorial] Optimize pixel-by-pixel drawing
« Reply #1 on: June 21, 2013, 12:36:43 pm »
I read this diagonally but the screenie looks pretty fast.

#### DJ Omnimaga

• Former TI programmer
• CoT Emeritus
• LV15 Omnimagician (Next: --)
• Posts: 55838
• Rating: +3151/-232
• CodeWalrus founder & retired Omnimaga founder
##### Re: [Tutorial] Optimize pixel-by-pixel drawing
« Reply #2 on: June 21, 2013, 02:12:46 pm »
Wow that is great! I think I thought about doing that in the past once, but I didn't realize it was actually faster. Thanks for the tutorial.
In case you are wondering where I went, I left Omni back in 2015 to form CodeWalrus due to various reasons explained back then, but I stopped calc dev in 2016 and am now mostly active on the CW Discord server at https://discord.gg/cuZcfcF

#### Runer112

• Project Author
• LV11 Super Veteran (Next: 3000)
• Posts: 2289
• Rating: +639/-31
##### Re: [Tutorial] Optimize pixel-by-pixel drawing
« Reply #3 on: June 21, 2013, 02:33:59 pm »
Out of curiosity, could you post the source of that plasma program? I'd be interested to look at it, I like Axe programs that do manual graphics rendering.

I'm certainly not asking because I want to try to optimize it to hell >.>
« Last Edit: June 21, 2013, 02:37:28 pm by Runer112 »

#### DJ Omnimaga

• Former TI programmer
• CoT Emeritus
• LV15 Omnimagician (Next: --)
• Posts: 55838
• Rating: +3151/-232
• CodeWalrus founder & retired Omnimaga founder
##### Re: [Tutorial] Optimize pixel-by-pixel drawing
« Reply #4 on: June 21, 2013, 02:40:07 pm »
Out of curiosity, could you post the source of that plasma program? I'd be interested to look at it, I like Axe programs that do manual graphics rendering.
You only want the source so you can make a version that is twice faster?

I'm certainly not asking because I want to try to optimize it to hell >.>
[/quote]
« Last Edit: June 21, 2013, 02:40:17 pm by DJ Omnimaga »
In case you are wondering where I went, I left Omni back in 2015 to form CodeWalrus due to various reasons explained back then, but I stopped calc dev in 2016 and am now mostly active on the CW Discord server at https://discord.gg/cuZcfcF

#### Matrefeytontias

• Axe roxxor (kinda)
• LV10 31337 u53r (Next: 2000)
• Posts: 1982
• Rating: +310/-12
• Axe roxxor
##### Re: [Tutorial] Optimize pixel-by-pixel drawing
« Reply #5 on: June 21, 2013, 05:02:32 pm »
Xeda asked for the source so I posted it on pastebin, but for some reason I can't reach it you'd better look at the "Axe plasma" thread.

#### Xeda112358

• they/them
• Moderator
• LV12 Extreme Poster (Next: 5000)
• Posts: 4647
• Rating: +717/-6
• Calc-u-lator, do doo doo do do do.
##### Re: [Tutorial] Optimize pixel-by-pixel drawing
« Reply #6 on: June 21, 2013, 05:09:12 pm »
I still have it open here. If that isn't working:
Code: [Select]
:.PLASMA:.by KKI+MAT:.Full:.Precalculs:det(256)→C:For(A,0,255):       127+cos(A*256/32)→{A+C}:End:0→Θ:Repeat getKey(15):       L6-1→P+12→Q:       Θ+1^32→Θ:       {Θ*2+24+C}/40→D:       {Θ+C}/32→E:       .Lignes:       0→Y:       Lbl YH:       .Precalculs:       {Y+E+C}→M:       .Colonnes:       0→X:       Lbl XW:       .Couleur:       M+{X+D+C}:       +{X+Y+D+E/2+Θ+C}→Z:       .Init/Decale:       !If X^4:               P+++12→Q:       0→{P}:0→{Q}:Else:       {P}*4→{P}:       {Q}*4→{Q}:End:If Z≤192:       {P}+3→{P}:{Q}+3→{Q}:ElseIf Z≤384:       {P}++:{Q}+2→{Q}:ElseIf Z≤576:       {P}++:End:If X++-48:       Goto XW:End:If Y++-32:       P+12→P+12→Q:Goto YH:End:DispGraph:.Output(0,0,A►Dec,{A+S}►Dec:End