Draw Pixels (Native Extension)

NE was updated with new parameter “angle” for filled rectangle

9 Likes

Draw pixels NE has a lot of changes after my last post here. Small status update for people who don’t follow repository on github.

First of all huge THANKS to all contributors: @britzl, @d954mas, @thekrasnikoff ! Thank you guys!

New methods:
drawpixels.pixel(buffer, x, y, r, g, b, a) to draw a pixel to the buffer
drawpixels.color(buffer, x, y) to read color from buffer
drawpixels.line(buffer_info, x0, y0, x1, y1, red, green, blue, alpha) to draw a line to the buffer
drawpixels.bezier(buffer_info, x0, y0, xc, yc, x1, y1, red, green, blue, alpha) draw a bezier line between two points and one control point

Moreover:
Refactoring and code clearing
Performance optimisation!!!
Bug fixing

Release notes for every release avaliable on this page: https://github.com/AGulev/drawpixels/releases

13 Likes

Correct link: https://defold.com/assets/drawpixels/

2 Likes

Is there a way to draw on top of a predefined texture/png? Rather than starting with a “blank canvas”?

It is possible


I did this right now in the example, so I will give the function code init

Summary
function init(self)
  msg.post("@render:", "clear_color", {color = vmath.vector4(1, 1, 1, 1)})
  -- size of texture when scaled to nearest power of two
  local width = 1024
  local height = 2048
  local channels = 4
  local file = io.open("image.png", "rb")
  local bytes = file:read("*a")
  local png = image.load(bytes,true)
  local my_buffer = png.buffer
  -- we have to create table with next fields: buffer, width, height, channels
  self.buffer_info = {
    buffer = buffer.create(#my_buffer, { {name=hash("rgba"), type=buffer.VALUE_TYPE_UINT8, count=4} } ),
    width = width,
    height = height,
    channels = channels -- 3 for rgb, 4 for rgba
  }
  local stream = buffer.get_stream(self.buffer_info.buffer, hash("rgba"))
  for i = 1, #my_buffer do
    stream[i] = string.byte(my_buffer, i)
  end
  self.dirty = true
  self.current_color = vmath.vector4(0, 0, 0, 1)
  self.current_tool = "pencil"
  -- drawing params
  self.prev_pos = vmath.vector3()
  self.resource_path = go.get("#sprite", "texture0")
  self.header = {
    width = width,
    height = height,
    type = resource.TEXTURE_TYPE_2D,
    format = resource.TEXTURE_FORMAT_RGBA,
    num_mip_maps = 1
  }
  self.rotation = 0
end
6 Likes

That is BEAUTIFUL. Thanks! This is a powerful extension.

3 Likes

I’ve been playing with this a while and it’s so much fun! I’m stuck trying to create “canvas” instances dynamically. This doesn’t work because the pixels are tied to this bitmap:

self.resource_path = go.get("#sprite", "texture0")

What’s drawn on one canvas is therefore also drawn to the other. One solution is to use two separate sprites. In my case that won’t work, because my (ambitious) plan is to create (literally) millions canvases dynamically, each different from the others.

Is it possible to create a texture on the fly somehow? I noticed this is possible in GUI, but I haven’t been able to find a similar way to do it with a go.

Here is a minimal example of the issue: PixelDrawInstances.zip (5.4 MB)

Edit: If textures cannot be created at runtime, I suppose one workaround would be to re-use a pool of 10 sprites or so, and make sure none of the visible canvases are using the same sprite.

Well you’re going to have to limit yourself. Each canvas takes up texture memory and there’s only a certain amount of it available. Think of a max amount that you can support (think about target platform and min GPU memory you want to support) and design around that.

1 Like

Yes, wise words. This is exciting though, a lot of possibilities for a nice side project!

New DrawPixels 2.0.0

  • New API methods: drawpixels.gradient_line() , drawpixels.arc() , drawpixels.filled_arc() , drawpixels.gradient_arc() , drawpixels.start_fill() , drawpixels.end_fill() , drawpixels.fill_area() .
  • Antialiasing option for the following functions: drawpixels.filled_circle() , drawpixels.line() , drawpixels.circle() .
  • Line width option for the following functions: drawpixels.circle() , drawpixels.line() .
  • premultiply_alpha option.

Thanks @sergeysinyavsky for these improvements!

13 Likes

Great work. This is turning into a Legendary Extension ™!

5 Likes

Really great, thanks.

I think I have a really simple request:

How exactly would I add stickers (sprites) to the example? (As in draw with smilies or something)

Hi @AGulev

I’m testing your “draw pixel” code. I just want to draw a filled rectangle but it’s not showing me anything… I followed the instruction provided in the github…
could you please help me? I put a snapshot of the code below:

Please make sure you update texture using resource.set_texture()

3 Likes

Emm… that’s what I missed!

Thanks a lot dear, I’m going to test it…

Regards,
Riad

4 Likes

Wow. Only just saw this project for the first time. So awesome @AGulev !!! Really like the toolkit.
Using it to test a little genetic evolution program. Thanks! WIll post some screenshots once working.

6 Likes

Oh, so much fun. Thanks again. I’ll put this project up sometime soon. Want to let the original author of biosim know what Ive done - its all MIT, but I like to make sure peoples work is recognised.


Original source: https://github.com/davidrmiller/biosim4

11 Likes

Absolutely fascinating. Ended up watching the Biosim 4 video, and it’s highly recommended. Do post (maybe in a different thread?) any future experiments with this!

5 Likes
4 Likes

Example project used stretch projection and also canvas size is edge to edge to window size. But what will be approach for using this with fixed projection and if canvas part is smaller in size. How will achive drawing pixel align to mouse cursor in this case. Or if we are rendering on gui node then how drawing pixel align to mouse cursor position.