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

0 Members and 1 Guest are viewing this topic.

Offline Matrefeytontias

  • Axe roxxor (kinda)
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1982
  • Rating: +310/-12
  • Axe roxxor
    • View Profile
    • RMV Pixel Engineers
[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).

Hoping that this'll help you :)
« Last Edit: June 21, 2013, 09:24:01 am by Matrefeytontias »

Offline Streetwalrus

  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 3821
  • Rating: +80/-8
    • View Profile
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. :D

Offline DJ Omnimaga

  • Clacualters are teh gr33t
  • CoT Emeritus
  • LV15 Omnimagician (Next: --)
  • *
  • Posts: 55943
  • Rating: +3154/-232
  • CodeWalrus founder & retired Omnimaga founder
    • View Profile
    • Dream of Omnimaga Music
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. :)

Offline Runer112

  • Project Author
  • LV11 Super Veteran (Next: 3000)
  • ***********
  • Posts: 2289
  • Rating: +639/-31
    • View Profile
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 »

Offline DJ Omnimaga

  • Clacualters are teh gr33t
  • CoT Emeritus
  • LV15 Omnimagician (Next: --)
  • *
  • Posts: 55943
  • Rating: +3154/-232
  • CodeWalrus founder & retired Omnimaga founder
    • View Profile
    • Dream of Omnimaga Music
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? :trollface:













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 »

Offline Matrefeytontias

  • Axe roxxor (kinda)
  • LV10 31337 u53r (Next: 2000)
  • **********
  • Posts: 1982
  • Rating: +310/-12
  • Axe roxxor
    • View Profile
    • RMV Pixel Engineers
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.

Offline Xeda112358

  • they/them
  • Moderator
  • LV12 Extreme Poster (Next: 5000)
  • ************
  • Posts: 4704
  • Rating: +719/-6
  • Calc-u-lator, do doo doo do do do.
    • View Profile
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