How to draw a rounded rectangle with a custom corner radius in Codea?

Hi! I have a question about drawing a rounded rectangle in Codea.

I currently draw a semi-transparent black rectangle like this:

rectMode(CENTER)
noStroke()
fill(0, 0, 0, 191)

rect(
panelX,
panelY,
panelW,
panelH
)

The rectangle is approximately 1856 × 1138 px. It’s Works but cant add corners.

I would like to give it strongly rounded corners, with a radius of around 200–220 px, but the radius does not work.

What is the correct way to draw a filled rounded rectangle with a custom corner radius in the current version of Codea?

Ideally, I’m looking for a clean solution without manually constructing the shape from rectangles and circles.

This will let you customize the corner radius:

--# RoundedRect
-- A cheap rounded rect: one mesh and one shader, built once and restyled on
-- every call rather than rebuilt. The original version of this shader mixed
-- fillColor and strokeColor backwards, so the interior painted as the stroke
-- and the border painted as the fill; the mix() arguments below are swapped
-- to fix that.

RoundedRectVertexShader = [[
precision highp float;
uniform mat4 modelViewProjection;
attribute vec4 position;
attribute vec2 texCoord;
varying highp vec2 vTexCoord;
void main() {
vTexCoord = texCoord;
gl_Position = modelViewProjection * position;
}
]]

RoundedRectFragmentShader = [[
precision highp float;
uniform lowp vec4 fillColor;
uniform lowp vec4 strokeColor;
uniform vec2 rectSize;
uniform float cornerRadius;
uniform float strokeWidth;
uniform float edgeSoftness;
varying highp vec2 vTexCoord;
float sdRoundedRect(vec2 p, vec2 halfSize, float r) {
vec2 q = abs(p) - (halfSize - vec2(r));
return length(max(q, vec2(0.0))) + min(max(q.x, q.y), 0.0) - r;
}
void main() {
vec2 halfSize = rectSize * 0.5;
vec2 p = (vTexCoord - 0.5) * rectSize;
float d = sdRoundedRect(p, halfSize, cornerRadius);
float aa = max(edgeSoftness, 0.75);
float shapeAlpha = 1.0 - smoothstep(0.0, aa, d);
// 0 in the deep interior, 1 once within strokeWidth of the edge
float towardEdge = smoothstep(-strokeWidth - aa, -strokeWidth + aa, d);
lowp vec4 c = mix(fillColor, strokeColor, towardEdge);
gl_FragColor = vec4(c.rgb, c.a * shapeAlpha);
}
]]

local sharedMesh = nil

function roundedRectMesh()
  if sharedMesh then return sharedMesh end
  sharedMesh = mesh()
  local rect = sharedMesh:addRect(0, 0, 1, 1)
  sharedMesh:setRectTex(rect, 0, 0, 1, 1)
  sharedMesh.shader = shader(RoundedRectVertexShader, RoundedRectFragmentShader)
  return sharedMesh
end

function drawRoundedRect(x, y, w, h, radius, fillCol, strokeCol, strokeW)
  local m = roundedRectMesh()
  m.shader.fillColor = fillCol
  m.shader.strokeColor = strokeCol or color(0, 0, 0, 0)
  m.shader.rectSize = vec2(w, h)
  m.shader.cornerRadius = radius or 0
  m.shader.strokeWidth = strokeW or 0
  m.shader.edgeSoftness = 1.0
  pushMatrix()
  translate(x + w * 0.5, y + h * 0.5)
  scale(w, h)
  m:draw()
  popMatrix()
end

I got it off a dude used to come around named @yojimbo2000

Heres a couple of other methods using just standard drawing:

function setup()
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)
    
    smooth() -- needed for lineCapMode
    lineCapMode(ROUND)
    
    x,y = WIDTH/2, HEIGHT/2
    w,h = 100,100
    r = 5
    
    strokeWidth(r)
    stroke(255)
    
    -- rect with rounded corners using lines with lineCapMode(ROUND)
    line(x+w,y+h, x,y+h) -- top
    line(x,y, x,y+h) -- left
    line(x,y, x+w,y) -- bottom
    line(x+w,y+h, x+w,y) --right

    noStroke()
    fill(0, 0, 0, 191)
    rect(
    x,
    y,
    w,
    h
    )
    
    -- rounding corners with ellipses
    r = 8
    y = y + h + 25
    fill(255)
    
    ellipse(x,y,r) -- bottom left
    ellipse(x+w,y,r) -- bottom right 
    ellipse(x,y+h,r) -- top left
    ellipse(x+w,y+h,r) -- top right
    
    lineCapMode(SQUARE)
    -- add lines between ellipses here
    
    fill(0, 0, 0, 191)
    rect(
    x,
    y,
    w,
    h
    )

end

These both work by drawing ellipses in the corners either with line and lineCapMode(ROUND) or with an ellipse placed in each corner to ‘round’ them. I have deliberately set these up to elude to and show how rounded corners work rather than look nice, so they will need some tweaking.

Right, and those are great, but you can’t use them with transparency. They must be solid. The shader I provided can handle transparency. Not a big deal unless you want that though.