Draw pixels to canvas

I seem to remember there being a planned way to do this nicely… can we get more details about it if this is a real thing and I’m not hallucinating it?

Edit: I was thinking of the buffers feature .

@Mathias_Westerdahl

Is code from this demo anywhere?

So we use buffer and resource to create texture buffers and modify them on the fly per pixel?

It should be possible to make something like Pico-8 in Defold right now…

When I test this example

function init(self)
  self.height = 128
  self.width = 128
  self.buffer = buffer.create(self.width * self.height, { {name=hash("rgb"), type=buffer.VALUE_TYPE_UINT8, count=3} } )
  self.stream = buffer.get_stream(self.buffer, hash("rgb"))

  for y=1,self.height do
      for x=1,self.width do
          local index = (y-1) * self.width * 3 + (x-1) * 3 + 1
          self.stream[index + 0] = 0xff
          self.stream[index + 1] = 0x80
          self.stream[index + 2] = 0x10
      end
  end

  local resource_path = go.get("#sprite", "texture0")
  local header = { width=self.width, height=self.height, type=resource.TEXTURE_TYPE_2D, format=resource.TEXTURE_FORMAT_RGB, num_mip_maps=1 }
  resource.set_texture( resource_path, header, self.stream )
end

I get

ERROR:SCRIPT: /examples/tools/texture_buffer_swap/buffer_controller.scrip:18: bad argument #3 to 'set_texture' (buffer expected, got userdata)
stack traceback:
	[C]: in function 'set_texture'
	/examples/tools/texture_buffer_swap/buffer_controller.scrip:18: in function </examples/tools/texture_buffer_swap/buffer_controller.scrip:1>

Still testing

It should work with sprites?

function update(self)
    -- copy the data from the texture of sprite1 to sprite2
    local buffer = resource.load(go.get("#sprite1", "texture0"))
    resource.set( go.get("#sprite2", "texture0"), buffer )
end

Gives

ERROR:SCRIPT: /examples/tools/texture_buffer_swap/buffer_controller.scrip:2: bad argument #1 to 'load' (string expected, got userdata)
stack traceback:
	[C]: in function 'load'
	/examples/tools/texture_buffer_swap/buffer_controller.scrip:2: in function </examples/tools/texture_buffer_swap/buffer_controller.scrip:1>

I’m on Windows 10 at the moment. I’ll test on Mac soon. Maybe not working because Windows doesn’t have native extensions yet??

Edit: Didn’t work on Mac either.

The API reference example is incorrect @sicher . It should be

resource.set_texture( resource_path, header, self.buffer )

I’ve reported the issue.

3 Likes

What about the second example?

	local buffer = resource.load(go.get("#sprite1", "texture0"))
ERROR:SCRIPT: /examples/tools/texture_buffer_swap/buffer_controller.scrip:2: bad argument #1 to 'load' (string expected, got userdata)
stack traceback:
	[C]: in function 'load'
	/examples/tools/texture_buffer_swap/buffer_controller.scrip:2: in function </examples/tools/texture_buffer_swap/buffer_controller.scrip:1>
INFO:DLIB: SSDP: Started on address 169.254.19.187
INFO:DLIB: SSDP: Started on address 169.254.108.130

Doing tostring() seems to make it go one step further but I strongly doubt that’s right to do…

DEBUG:SCRIPT: hash: [build/default/_generated_e27b97ae.texturec]
ERROR:RESOURCE: Resource path is not absolute (hash: [build/default/_generated_e27b97ae.texturec])
ERROR:SCRIPT: /examples/tools/texture_buffer_swap/buffer_controller.scrip:5: The resource was not found: 9327522419242501489, hash: [build/default/_generated_e27b97ae.texturec]
stack traceback:
	[C]: in function 'load'
	/examples/tools/texture_buffer_swap/buffer_controller.scrip:5: in function </examples/tools/texture_buffer_swap/buffer_controller.scrip:1>

The first example still doesn’t seem right.

I’m uncertain about the whole stream format that I get back. I’m trying to draw/modify pixels of the stream that I’ve created and then set them on the sprite, but the format seems weird. The API example works since it’s a fixed width and height and all of the pixels are set to the same value.

Is the source from this demo anywhere? It might help.

I’ve uploaded the example here.

One important thing to note is that when you call resource.set_texture(), you are replacing the entire texture. So, if you have more than one texture in the atlas, beware that the sprites’ texture coordinates will stay the same as before! That’s why I have an atlas with only one texture in it, to make it simple.

5 Likes

Thank you for sharing this. That does make sense about the entire texture being replaced.

Some goals:

  1. Make small pixel art editor that can save and load files.
  2. Render screen to texture and then be able to add extra textures on top then send the screenshot to a server, save to disk, or share with social features on phones.
  3. Make general shape drawing lib.
  4. Make a tool which can take buffer information from certain positions and draw to a display texture.
  5. Make graphing calculator clone.

But thing I’m most excited about is making a mini pico-8 type thing in Defold. Can have most things in pure code, and just draw to a single texture that is only so many pixels large.

1 Like

Any idea why resource.load isn’t working? I’d like to be able to get the texture data of an existing texture and put it into a buffer.

The first demo wasn’t working for me before in part too because I had a sprite set to a custom material with a sampler. Just need to get resource.load working now.

Seems to work pretty fast for smaller textures. Doing fullscreen size updates is super slow though. I hope that the smaller texture size works fast enough on mobile.

Custom materials work only if you do not set a mipmap option in the sampler.

In engine it’s faster than the above.

I played around with the buffer API and created a simple paint application:

DEMO: http://britzl.github.io/publicexamples/draw_pixels/index.html
CODE: https://github.com/britzl/publicexamples/tree/master/examples/draw_pixels

It would be kinda fun to expand this to a proper paint application with save/load functionality.

3 Likes

There are existing Lua encoders / decoders out there for jpeg, png and so shouldn’t be too difficult!

Doing playback of audio through constructed / loaded buffers would be cool too… Then we could draw the waveforms with this and play them back.

Making a simple 8x8 pixel art tool with preset color palettes. Then will setup animation for frames. Lots of cool possibilities.

Any idea about getting this to work?

Ah, sorry, I forgot. Using a hash for resource.load() is a reported issue DEF-2482, eta unknown.

2 Likes

As I understand, I can not get the current sprite buffer and make some changes there?

No, not yet I’m afraid.

1 Like

ok, i’ll try to work around it using PNG extension by @britzl , thanks

Like this way of thinking, is what makes Defold full of little hidden gems.
Pixel access is most time obscured on other engines. And I always like to have the option to play with pixels, that make me feel nostalgic for the old times when I was drawing directly to the CGA memory using Turbo Pascal :slight_smile:

1 Like