drawing a single pixel

howdy. I’m trying to find an efficient way to draw a single pixel and came up with the following via Meshes:

Point = class()
-- a point is a mesh rect that is 1px wide and 1px long
function Point:init(x, y, _color)
    -- you can accept and set parameters here
    self.m = mesh()
    self.m:addRect( x, y, 1, 1 )
    self.m:setColors( _color )
end

function Point:draw()
    -- Codea does not automatically call this method
    self.m:draw()
end

any comments on if this is a bad method, or what not?

I think this method would work better. Rather than creating a mesh and setting the 3 verticies to the same color, simply make a 1x1 image and set the pixel color. Here’s the code: (ps, i dont know if this is actually a better method as I am new to coding in codea)

-- Pixel

function setup()
myImage = image(1,1)
myImage:set(1,1,23,56,76,255)
end

function draw()
background(0, 0, 0, 255)
sprite(myImage,WIDTH/2, HEIGHT/2)
end

looks good to me

My question is that once I get a bunch of points being rendered, won’t the rendering engine think each point is a pair of triangles, since they’re constructed of meshes, and thus can easily become bogged down?

every pixel would result in the rendering engine trying to draw 2 triangles. would this be a bottleneck, or would it figure out that it was just rendering a single pixel, and there wouldn’t be a bottle neck?

@Ignatz

How many points are you thinking of?

@matkatmusic - What is your use for this? There are many, many solutions to this, and it the best one largely depends on how often you draw to it and the size of the image. i.e. images have a max size of 2048x2048.

I’m trying to draw some Bézier curves for starters. i’m mainly just experimenting with how to draw pixel-based lines and curves.

for example:
This little roundRect class I wrote. I’d like to add the ability for visual feedback when the mesh is touched, but i’m not sure if meshes are the way to go. maybe image() is. I’m just thinking that meshes are triangles, which are native to the graphics card processor, so i’m assuming they’ll always be faster than regular images. but I don’t know

RoundRect = class()

--RoundRect oobject constructed from Points for the curves
-- and mesh rects for the straight line

function RoundRect:init(x, y, w, h, r, lineWidth, c)
    -- you can accept and set parameters here
    self.x = x -- center x
    self.y = y -- center y
    self.w = w -- overall width
    self.h = h -- overall height
    self.r = r -- corner radius
    self.lineWidth = lineWidth
    self.c = c -- colors
    a = w-2*r
    b = h-2*r
    
    self.m = mesh()
    self.m:addRect( x, y + h/2, a, lineWidth )
    self.m:addRect( x, y - h/2, a, lineWidth )
    self.m:addRect( x-w/2, y, lineWidth, b )
    self.m:addRect( x+w/2, y, lineWidth, b )
    
    --this lineWidth stuff is intended to make the curves match the width of the straight lines, but it doesn't
    --that's why it's commented out for now
    --for lw=0, lineWidth do
    --    r = r + lw -- 1st: r, 2nd: r+1, 3rd: r+2, etc
        numPoints = math.ceil( math.pi * r * r )
        offset = numPoints/4
        for i=1, numPoints/4 do
                _x = x-a/2 + r * math.sin( 2 * math.pi * ((i + offset*3)/numPoints))
                _y = y+b/2 + r * math.cos( 2 * math.pi * ((i + offset*3)/numPoints))
            self.m:addRect( _x, _y, 1, 1 )
                _x = x+a/2 + r * math.sin( 2 * math.pi * ((i           )/numPoints))
                _y = y+b/2 + r * math.cos( 2 * math.pi * ((i           )/numPoints))
            self.m:addRect( _x, _y, 1, 1 )
                _x = x+a/2 + r * math.sin( 2 * math.pi * ((i + offset*1)/numPoints))
                _y = y-b/2 + r * math.cos( 2 * math.pi * ((i + offset*1)/numPoints))
            self.m:addRect( _x, _y, 1, 1 )
                _x = x-a/2 + r * math.sin( 2 * math.pi * ((i + offset*2)/numPoints)) 
                _y = y-b/2 + r * math.cos( 2 * math.pi * ((i + offset*2)/numPoints))
            self.m:addRect( _x, _y, 1, 1 )
        end
    --end
    self.m:setColors( c )
end

function RoundRect:draw()
    -- Codea does not automatically call this method
    self.m:draw()
end

function setup()
    r = RoundRect( WIDTH/2, HEIGHT/2, 200, 200, 50, 1, color( 255, 0, 0, 255) )
end

function draw()
    background(0, 0, 0, 255)
    r:draw()
end

@zoyt @Ignatz

In my experience, meshes are always the better option.

It’s always good to do your own code, but if your Bezier curves are a means to an end then I have a shader that draws Bezier curves, if you’d like it just ask.

Since they area that you’re drawing is (probably) not too large, yet it is changing constantly, I’d go with @Andrew_Stacey and say that meshes are better. But if you’re doing something like Bézier curves, I’d suggest using a shader. That way you can change it constantly with no extra overhang.

There is always point(x,y)?

@Coder point(x,y) draws 4 pixels, not 1. Look at the result with a magnifying glass and you’ll see 4 points.

@Coder My mistake. The sprite code above draws 4 pixels (2x2). It looks like the point draws 16 pixels (4x4) on my iPad Air.

You know there’s this, right?

-- Pixel

function draw()
    background(255)
    fill(0)
    noStroke()
    rect(100, 100, 1 / ContentScaleFactor, 1 / ContentScaleFactor)
    noFill()
    stroke(0)
    strokeWidth(1 / ContentScaleFactor)
    ellipse(100, 100, 20)
end

The 1 / ContentScaleFactor is so it still draws 1 pixel, even on retina screens.

@SkyTheCoder Nice example. That does create 1 pixel. I changed my version to show white on a black background so it was easier for me to see it. I used a 10x magnifier to see the single pixel. The ContentScaleFactor is new for me, I don’t recall seeing it before. Had to look it up.

Hi @matkatmusic,

Check out the Codea on line manual at

http://twolivesleft.com/Codea/Reference/Graphics.html#image.get

You should find image.get(x,y) and image.set(x,y, color) which should meet your initial needs. Hope I’m not repeating this.

Bri_G

:wink:

@Bri_G image:set was mentioned above by @Mr_Ninja, but both the mesh and set programs draw 4 pixels (on retina display) instead of 1. On my iPad1 (non retina) they draw 2 pixels.@SkyTheCoder shared the code that draws 1 pixel on the retina display.

I think the reason they draw four is due to this ; http://codeatuts.blogspot.com.au/2012/11/interlude-13-pixels-vs-points-in-ios.html

@Mr_Ninja Interesting reading. The definition of a point explains why there are 4 pixels turned on. But it’s still interesting to be able to write 1 pixel even though you can’t see it without a magnifying glass.