Rotozoomer effect for TinyFPGA BX


#1

There’s been some talk on twitter recently about FPGA “demos” (as in demoscene demos), and this inspired me to create a simple “rotozoomer” effect on the TinyFPGA. I borrowed the VGASyncGen code from @juanmard , added some sine & cosine tables, and, well, here’s the result :slight_smile:

Code is on github here if you’re interested: https://github.com/gundy/tinyfpga-bx-demos/tree/develop/examples/rotozoomer1


#2

Great! Excellent use! :grin:


#3

That is slick!! It reminds of the graphics mode on the SNES that allowed bitmaps to be scaled and transformed with perspective.


#4

So…could you now use the output from the tables to drive a ROM with a bitmap image?


#5

I’m trying this @lukevalenty… but not work for now…:confused:
In a pair of hours an issue of your project @gundy… if you want… :stuck_out_tongue_winking_eye:


#6

As it happens, I’d already started looking into that too…

link to source is here: https://github.com/gundy/tinyfpga-bx-demos/tree/develop/examples/rotozoomer2


#7

I suppose I should add that my drawing skills aren’t great, but I edited the image as an “indexed colour bitmap” in GIMP. I’ve included the 8-colour palette file (.gpl) in the source repository.

To get the image into the .mem format, I exported it as a .h (c header), and massaged it a little in a text editor (swapped commas for spaces etc).


#8

WOOooo!!! Great!!
In screen-logo project I used Matlab to convert in a text file, maybe Gimp it’s better… :grinning:


#9

Test with my texture… Now it works!
@gundy if you want this example in your project tell me and I do a pull-request. :wink:
You can see my code here… Rotozoomer3


#10

My video example it’s on Twitter…

Thanks @gundy… See you on Twitter. :stuck_out_tongue_winking_eye:


#11

Nice work!!! Love it! And sure, send through a pull request, I’ll add it to my repo too :slight_smile:


#12

It’s your job! :+1:
I only reused modules that I already had… I also like your more colorful textures. :stuck_out_tongue_winking_eye:


#13

Very cool! I’m much would it take to turn that into separate rotation and zoom controls? I’m guessing it would probably require tables that are too large. Or maybe a Cordic core could generate some values in the VBLANK for the next frame.


#14

I’m not quite sure what you mean by this, but the zoom (scale) and rotate (angle) are already controlled with separate registers - it’s just that I happen to have tied the scale register to the angle counter for animation purposes (scale is essentially computed as sin(angle/2)).

The current sine/cosine tables are signed, fixed-point 0.16 values, and operate over a 0…255 range (256 being essentially 2π radians).

It would be fairly easy to expose the angle and scale registers separately to a u-controller or other mechanism if you wanted to. :slight_smile:

Also, thanks v/much for the “cordic” name-drop - I just did some reading on that, and it looks like it might be quite useful for some other ideas I had :smiley:


#15

Awesome! :star_struck:

So then the next things I want to do with it are:

  1. Adapt it to a tilemap graphics engine.
  2. Add a pseudo perspective value…i’m thinking something like the mode the SNES had to do Mario Kart and Pilot Wings.
  3. Control it with a CPU. :grinning:

#16

Ooooh, now I see where you’re coming from… SNES mode 7… nice one… something like that doesn’t seem like it’d be too hard to do…

Also, if we allowed for 16 different kinds of tiles @ 32x32x4bpp (1 SB_RAM block each), and a 64x64x4-bit tile map (4xSB_RAM), that would still leave 12 RAM blocks for some sprites, or characters, or whatever else you wanted to fit in there :smiley:

I don’t have the time to look into this right now, but if someone else wants to have a go, it’d be awesome!

The other thing I’ve been pondering, loosely, is maybe a raycasting demo of some sort (remember wolfenstein3d?) … I think raycasting (or at least finding the intersection points) would be easiest to do with a CPU, although the FPGA could definitely hardware-accelerate the actual texture drawing…


#17

Hi @gundy, I’m trying to see the theoretical part of the project, but there are two lines that I still do not understand:

      if (xpos == 0) begin
          u_start <= u_start - v_stride[16:0];
          v_start <= v_start + u_stride[16:0];

I know that they are related to the matrix of transformation of sines and cosines that rotate the texture in 2D, but I can not obtain them theoretically.

Could you give me some reference?

Thank you. :))


#18

Ok, I think I understand it.
I wrote my thougths in a README of “rotozoomer4” example.
Next step, “pull-request” to you. :slight_smile:


#19

Hey! Sorry that I was too slow with the reply - I’ve had a few other commitments keeping me busy lately…

Thanks so much for adding the README - I really appreciate it…

As you figured already, the idea is basically that you’re mapping (x,y) screen co-ordinates to (u,v) texture-space. You could do that using a matrix transformation for each pixel (but that would be computationally expensive), so the alternative approach is that you pick a (u,v) starting point in texture space that corresponds to (x=0, y=0) in screen space, and then step through the texture in one direction for every x pixel, and at 90 degrees for every y pixel moved in screen space.

This means that for every pixel you’re only really doing a simple fixed-point addition: (u,v) <= (u,v) + step , where “step” is calculated based on the rotation angle, and a scale factor.


#20

Great! I think I already understand it,… That’s what I think… :grinning:
Thank you! :slightly_smiling_face: