Rainbow Rectangle

It’s a rectangle filled with a rainbow. What’s not to like?

-- Rainbow Rect

-- Use this function to perform your initial setup
function setup()
    a = rainbow_rect(0,0, WIDTH,HEIGHT)
end

-- This function gets called once every frame
function draw()
    -- This sets a dark background color 
    background(40, 40, 50)
    a:draw()
    -- This sets the line thickness
    strokeWidth(5)

    -- Do your drawing here
    
end

-- x,y specify bottom left corner
function rainbow_rect(x,y,w,h)
    local rectangle = mesh()
    local h2,h3,h4,h5 = h*.75,h*.5,h*.25,0
    local verts = {vec2(w,h), vec2(0,h), vec2(0,h2),    -- h is red
                    vec2(w,h), vec2(0,h2), vec2(w,h2),   -- h2 is yellow
                     vec2(w,h2), vec2(0,h2), vec2(0,h3),
                      vec2(w,h2), vec2(0,h3), vec2(w,h3), -- h3 is green
                       vec2(w,h3), vec2(0,h3), vec2(0,h4),
                        vec2(w,h3), vec2(0,h4), vec2(w,h4), -- h4 is blue
                         vec2(w,h4), vec2(0,h4), vec2(0,h5),
                          vec2(w,h4), vec2(0,h5), vec2(w,h5)} --h5 is purple
    local colors = {}
    local c
    for i,v in ipairs(verts) do
            if v.y == h then c = color(255,0,0)
        elseif v.y == h2 then c = color(255,255,0)
        elseif v.y == h3 then c = color(0,255,0)
        elseif v.y == h4 then c = color(0,0,255)
        elseif v.y == h5 then c = color(141, 0, 255, 255)
            end
        colors[i] = c
    end
    for i,v in ipairs(verts) do
        v.x = v.x + x
        v.y = v.y + y
    end
    rectangle.vertices = verts
    rectangle.colors = colors
    return rectangle
end

Instead of returning rectangle you could return an image instead

local image = image(w,h)
setContext(image)
rectangle:draw()
return image

Originally I was trying to make a rainbow gradient shader for a sphere/ellipse but i couldn’t figure it out.

@xThomas Here’s a simple way of doing a circle. I’ll let you do it as a shader. Basically I’m calculating the x,y points around the circumference of a circle. I’m then drawing a line from the top of the circle to the bottom as I move from the right to the left. Like cutting a sphere into thin slices.

displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)

function setup()
    tab={}
    cx=WIDTH/2
    cy=HEIGHT/2
    size=HEIGHT/2-10
    step=.2
    d=256/(180/step)
    for z=0,180,step do
        x=math.cos(math.rad(z))*size
        y=math.sin(math.rad(z))*size
        table.insert(tab,vec2(x,y))        
    end   
end

function draw()
    background(0)
    strokeWidth(2)
    for a,b in pairs(tab) do
        stroke(255-a*d,math.abs(450-a),a*d)
        line(cx+b.x,cy+b.y,cx+b.x,cy-b.y)
    end
end

@dave1707:

Oh, cool! I never thought of drawing a circle using just lines. But yeah, I still haven’t gotten any shader for the rainbow. Might take me a bit of time to learn

In the meantime, I did get a rainbow circle half working at least as a plain old textured mesh. Colors are really washed out for some reason I don’t know, and it’s way long



function rainbowCircle(x,y,size,r)
    -- USE POWERS OF 2 FOR size IF YOU ENABLE TEXTURE WRAPPING
    -- size builds the circle
    -- r is rotation in degrees of the texture
    local CONST_SIZE = size
    local CONST_ROTATEPOINT = vec2(size/2, size/2)
    local r = r
    local rectangle = mesh()
    local w,h = size, size
    local h2,h3,h4,h5 = h*.75,h*.5,h*.25,0
    local verts = {vec2(w,h), vec2(0,h), vec2(0,h2),    -- h is red
                    vec2(w,h), vec2(0,h2), vec2(w,h2),   -- h2 is yellow
                     vec2(w,h2), vec2(0,h2), vec2(0,h3),
                      vec2(w,h2), vec2(0,h3), vec2(w,h3), -- h3 is green
                       vec2(w,h3), vec2(0,h3), vec2(0,h4),
                        vec2(w,h3), vec2(0,h4), vec2(w,h4), -- h4 is blue
                         vec2(w,h4), vec2(0,h4), vec2(0,h5),
                          vec2(w,h4), vec2(0,h5), vec2(w,h5)} --h5 is purple
    local colors = {}
    local c
    for i,v in ipairs(verts) do
            if v.y == h then c = color(255,0,0)
        elseif v.y == h2 then c = color(255,255,0)
        elseif v.y == h3 then c = color(0,255,0)
        elseif v.y == h4 then c = color(0,0,255)
        elseif v.y == h5 then c = color(141, 0, 255)
            end
        colors[i] = c
    end
    
    -- rotate verts
    local pt
    for i,v in ipairs(verts) do
        pt = math.rotateTo(v, r, CONST_ROTATEPOINT)
        v.x,v.y = pt.x, pt.y
    end
    local rainbow = image(w,h)  -- sets up our texture
    setContext(rainbow)
    rectangle.vertices = verts
    rectangle.colors = colors
    rectangle:draw()            -- draws our texture
    setContext()
    --[[ ============================================ ]]--
    -- now we create the circle mesh
    local circle = mesh()
    local r = size/2 -- r means radius now
    local origx, origy = x,y --store original x,y values
    local x,y = r,r --new x,y values
    local verts={}
    local coords = {}
    local center = vec2(r,r)
    for i = 1,1080,3 do
        local angle = i * math.pi / 100
        local angle3 = (i+3) * math.pi / 100
        local x1, y1 = x + r * math.cos(angle), y + r * math.sin(angle)
        local x2, y2 = r,r
        local x3, y3 = x + r * math.cos(angle3), y + r * math.sin(angle3)
        verts[i] = vec2(x1,y1)
        verts[i+1] = vec2(x2,y2)
        verts[i+2] = vec2(x3,y3)
    end
    x,y = origx,origy --restore original x,y values 
    
    --TEXCOORDS: HELP. ME.
    local coord,cx,cy
    for i,v in ipairs(verts) do
        cx,cy = v.x/CONST_SIZE, v.y/CONST_SIZE
        coords[i] = vec2(cx,cy)
    end
    
    --MOVE TO X,Y COORDINATE ON SCREEN
    --(Otherwise you'd need to use translate(x,y))
    for i,v in ipairs(verts) do
        v.x, v.y = v.x + x, v.y + y 
    end
    circle.vertices = verts
    circle.texCoords = coords
    circle.texture = rainbow
    circle:setColors(255,255,255)        
    return circle, rectangle, rainbow
end
-- rotates point around the centre by degrees
-- rounds the returned coordinates using math.round() if round == true
-- returns new coordinates object
local function rotateAboutPoint( point, degrees, centre )
	local pt = { x=point.x - centre.x, y=point.y - centre.y }
	pt = math.rotateTo( pt, degrees )
	pt.x, pt.y = pt.x + centre.x, pt.y + centre.y
	return pt
end

-- rotates a point around the (0,0) point by degrees
-- returns new point object
-- center: optional
math.rotateTo = function( point, degrees, center )
	if (center ~= nil) then
		return rotateAboutPoint( point, degrees, center )
	else
		local x, y = point.x, point.y
		local theta = math.rad( degrees )
		local pt = {
			x = x * math.cos(theta) - y * math.sin(theta),
			y = x * math.sin(theta) + y * math.cos(theta)
		}
		return pt
	end
end
function setup()
    a,b,c= rainbowCircle(320,240,512,100)
end

function draw()
    background(40, 40, 50)
    a:draw()
    b:draw()
    sprite(c, WIDTH/2,HEIGHT/2)
end

I am not sure if that is it but a medh must always have its vertices devisable by 3, like 3,6,9,…

@GR00G0

Just checked. print(#coords) and print(#verts) both output 1080. (On the rounded circle)

were you trying to run my code and having a,problem?

@xThomas Add the line of code I show below just before the return in the function rainbowCircle(). I’m not sure why it’s needed to brighten the colors, but I found that out long ago when I was messing around with meshes.

    circle:setColors(255,255,255)        -- add this line of code

    return circle, rectangle, rainbow     -- existing line of code

Here’s my above program modified to show a range of colors in the circle. You can also slide your finger right or left to scroll the colors.

displayMode(FULLSCREEN)
supportedOrientations(LANDSCAPE_ANY)

function setup()
    dx=0
    tab1={}
    r,g,b=0,255,255
    y=WIDTH
    while y>=0 do
        table.insert(tab1,vec3(r,g,b))
        y=y-WIDTH/(256*6)
        if r==255 and g==0 and b==0 then
            rv,gv,bv=0,1,0
        elseif r==255 and g==255 and b==0 then
            rv,gv,bv=-1,0,0
        elseif r==0 and g==255 and b==0 then
            rv,gv,bv=0,0,1
        elseif r==0 and g==255 and b==255 then
            rv,gv,bv=0,-1,0
        elseif r==0 and g==0 and b==255 then
            rv,gv,bv=1,0,0
        elseif r==255 and g==0 and b==255 then
            rv,gv,bv=0,0,-1
        end 
        r=r+rv
        g=g+gv
        b=b+bv       
    end
    cx,cy=WIDTH/2,HEIGHT/2
    tab={}
    size=HEIGHT/2-6
    for z=0,180,.3 do
        x=math.cos(math.rad(z))*size
        y=math.sin(math.rad(z))*size
        table.insert(tab,vec2(x,y))        
    end 
    s=#tab1/#tab
    scroll=0
end

function draw()
    background(0)
    strokeWidth(5)
    if scroll>#tab1 then
        scroll=scroll-#tab1
    elseif scroll<=0 then
        scroll=scroll+#tab1
    end
    for a,b in pairs(tab) do
        f=(a*s)//1+scroll
        if f>#tab1 then
            f=f-#tab1
        elseif f<=0 then
            f=f+#tab1
        end
        stroke(tab1[f].x,tab1[f].y,tab1[f].z)
        line(cx+b.x,cy+b.y,cx+b.x,cy-b.y)
    end
end

function touched(t)
    if t.state==MOVING then
        scroll=(scroll+t.deltaX)//1
    end
end