Opacity/transparency problem

So @Simeon gave me a wonderful answer on my most resent discussion, he answerd about rounded rectangles.
But I have gotten into a problem with that solution.

Because that solusion draws rounded lines to create the “roundness” and a box in the middle that makes it show all those on top of each other when the opasity goes down.

So is there a way to put together those lines and rectangles so they give out the same color when they are above each other?
I could make it fade from the color of the background but that would potensionally hide stuff behind it.

I have heard about meshes, can they do this? If possible then how do they work?

I am tripping over even more problems, can you for example set a mask for stuff to draw? This would be increadibly useful when doing a list or something. If you know what I mean (and I do not relate to the horny sex “if you know what I mean” joke).

Try the code below, which uses a shader. It allows you to make a negative or positive stencil by flipping the parameter.

http://instagram.com/p/aM42J8hHdN/
http://instagram.com/p/aM5QJiBHdv/

The important things are

  1. you need to use a mesh to draw your image, as shown
  2. the stencil image must be attached to the shader, not the mesh (see how texture and texture2 are set slightly differently)

The shader itself simply checks whether the stencil mask has a pixel drawn at each position, and if so, it draws the normal image pixel (unless you have flipped the setting). So any non blank (alpha>0) pixel acts as a stencil.

If this seems like black magic, I have tutorials on meshes and on shaders here
http://coolcodea.wordpress.com/

and I will probably explain this shader in a future post because it looks useful. Don’t be intimidated by the code - a month ago I wouldn’t have understood any of it myself, so it just takes a little time and effort to get to know it.

function setup()
    parameter.boolean("Negative",false)
    img=readImage("Cargo Bot:Starry Background")
    stencilImg=readImage("Planet Cute:Character Princess Girl")
    m=mesh()
    u=m:addRect(0,0,img.width,img.height)
    m:setRectTex(u,0,0,1,1)
    m.texture=img
    m.shader = shader(stencilShader.vertexShader, stencilShader.fragmentShader)
    m.shader.texture2=stencilImg
    m.shader.negative=Negative
end

function draw()
    background(200)
    pushMatrix()
    translate(300,300)
    m.shader.negative=Negative
    m:draw()
    popMatrix()
end

stencilShader = {
vertexShader = [[
//
// A basic vertex shader
//

//This is the current model * view * projection matrix
// Codea sets it automatically
uniform mat4 modelViewProjection;

//This is the current mesh vertex position, color and tex coord
// Set automatically
attribute vec4 position;
attribute vec4 color;
attribute vec2 texCoord;

//This is an output variable that will be passed to the fragment shader
varying lowp vec4 vColor;
varying highp vec2 vTexCoord;

void main()
{
    //Pass the mesh color to the fragment shader
    vColor = color;
    vTexCoord = texCoord;

    //Multiply the vertex position by our combined transform
    gl_Position = modelViewProjection * position;
}

]],
fragmentShader = [[
//
// A basic fragment shader
//

//Default precision qualifier
precision highp float;

//This represents the current texture on the mesh
uniform lowp sampler2D texture;

//This texture will be rendered atop the first
uniform lowp sampler2D texture2;

uniform bool negative;

//The interpolated vertex color for this fragment
varying lowp vec4 vColor;

//The interpolated texture coordinate for this fragment
varying highp vec2 vTexCoord;

void main()
{
    //Sample the texture at the interpolated coordinate
    lowp vec4 col1 = texture2D( texture, vTexCoord );
    lowp vec4 col2 = texture2D( texture2, vTexCoord );

    //Set the output color to the texture color
    if (negative)
        {if (col2.a>0.)  gl_FragColor = col1; else discard;} 
    else if (col2.a==0.) gl_FragColor = col1; else discard;
}

]]}

If you want to reduce the opacity of all the parts of your rounded rectangle at the same time, and assuming you are drawing it frequently, it makes sense to create an image of the rounded rectangle, then you only have to draw one image each time, and the opacity will apply to everything on the image.

I’ve written you a function which does this, creating a rounded rectangle using Simeon’s code, and putting it into a mesh. Then some code in draw fades it smoothly into the background colour if you adjust the transparency parameter.

I suggest that if you want to do this stuff, then you need to learn about meshes and all the stuff in this code, before you go much further.

function setup()
    --draw image of rounded rectangle
    w,h,r,c=250,100,8,color(255,255,255)
    roundedMesh=drawRoundRect(w,h,r,c)
    parameter.integer("Transparency",0,255,255)
end

function drawRoundRect(w,h,r,c)
    local img=image(w,h)
    setContext(img)
    roundRect(0,0,w,h,r,c)
    setContext()
    m=mesh()
    --mesh will draw the image centred on whatever x,y you translate to
    --if you prefer to have x,y be the bottom left corner
    --use the commented line instead
    --m:addRect(-w/2,-h/2,w,h)
    m:addRect(0,0,w,h)
    m:setRectTex(0,0,1,1)
    m.texture=img
    return m
end

function roundRect(x, y, w, h, r,c)
    pushStyle()
    stroke(c)
    fill(c)
    insetPos = vec2(x+r,y+r)
    insetSize = vec2(w-2*r,h-2*r)

    rectMode(CORNER)
    rect(insetPos.x,insetPos.y,insetSize.x,insetSize.y)

    if r > 0 then
        smooth()
        lineCapMode(ROUND)
        strokeWidth(r*2)

        line(insetPos.x, insetPos.y, 
             insetPos.x + insetSize.x, insetPos.y)
        line(insetPos.x, insetPos.y,
             insetPos.x, insetPos.y + insetSize.y)
        line(insetPos.x, insetPos.y + insetSize.y,
             insetPos.x + insetSize.x, insetPos.y + insetSize.y)
        line(insetPos.x + insetSize.x, insetPos.y,
             insetPos.x + insetSize.x, insetPos.y + insetSize.y)            
    end
    popStyle()
end

function draw()
    backColour=color(220,150,100)  --needed so we can fade towards this colour
    background(backColour)
    
    pushMatrix()
    translate(300,300) --go to where we want to draw rectangle
    
    --fade towards the background colour, if required
    if Transparency<255 then
        local trans=Transparency/255
        local transr=backColour.r*(1-trans)+255*trans
        local transg=backColour.g*(1-trans)+255*trans
        local transb=backColour.b*(1-trans)+255*trans
        local transa=backColour.a*(1-trans)+255*trans
        m:setColors(transr,transg,transb,transa)
    end
    m:draw()
    popMatrix()
end

My rounded rectangle function (in the discussion Simeon linked to in your original thread) doesn’t suffer from the opacity issue as it uses a mesh that exactly matches the rounded rectangle.

@Andrew_Stacey - I would be tempted to use your function, except it is a lot of code (over 100 lines), for something that seems fairly simple. The length will put many people off (as it did me).

I don’t think it’s necessary to have the mesh exactly follow the corners because corners are small, and fat fingers aren’t going to notice the difference, and it would also be rare to want some corners rounded and not all of them. I guess I’m suggesting a cut down simpler version would probably be used more frequently - and it would be a shame to waste your good work.

@Ignatz It’s not about fingers but eyes. Fat fingers might not notice (and, indeed, I tend not to take the rounding into effect when working out if a rectangle has been touched) but not-quite round corners can really jar the eyes.

The rounded rectangle function itself is only 58 lines of code (there’s another function for adding a rounded rectangle to an existing mesh, maybe that’s put your count off). Moreover, it can deal with several possibilities including:

  1. Not every corner is rounded,
  2. Changing the radius of rounding,
  3. Drawing the rectangle at an angle.

It also caches the mesh so that it doesn’t have to reconstruct it every time.

I reckon these are worth 60 lines of code!

But don’t worry about my “good work” being wasted - I only write code that I want to use (well, mainly) so you can rest assured that I’ll use my rounded rectangle function whenever I want a rounded rectangle and you can use your complicated shaders (of 65 lines!).

Ah, I notice you question the use of not rounding every corner. I use it in menus. If I have a free-standing menu with a title then I put both the title and the menu in separate boxes so that the title can stand out (it is almost always shorter). But to make it clear that the two are one unit the title box does not round the lower corners and the menu box does not round the top-left corner.

don’t worry, Andrew, I don’t want to fight with you! I admire your code, but it can be intimidating. It’s not clear that there is a spare function in there…

I understand why you offer optional rounding, that’s useful. And I didn’t see that you can draw it at an angle. Cool.

PS my shader is there to fade the rectangle, not to draw it. And only 3 lines are different from the default shader. I like the amazing things you can do with so few changes!

Black.magic.

No seriously this is freaky! Meshes, shaders, rounding, fades, functions.

I am getting confused, but I will try to take the time to understand your code (both @Ignatz and @Andrew_Stacey), tho I have already struck into a confusion in your code (@Ignatz your code).

function roundrectanglewhatever()
    pushStyle()
    -- some other code
    popStyle()
end

push/pop-Style??
And also something called pushMatrix()??

What is that doing? I have seen it multiple times in Codea code but never understood it… What is it?

@akaJag I think you should spend a little time reading the various tutorials, help pages, and wiki pages. There’s a lot of stuff contained there and plenty of places that explain what pushStyle() and popStyle() do.

I agree you should read up on Codea some more, to get to know some of these mysteries. They aren’t so hard once you understand what they are for.

This tutorial covers pushStyle among other things

http://coolcodea.wordpress.com/2013/03/11/how-codea-draws/

Thank you!!