Zone Shader

Hello all. For a game I’m working on I need to draw “blocked” zones (a rect with the lines going across it, pretty straightforward)

I came up with this solution:

-- Use this function to perform your initial setup
function setup()
    parameter.watch("1/DeltaTime")
    
    blockedZones = { 
        {x1 = 0, y1 = 0, x2 = 200, y2 = 400},
    
        {x1 = 210, y1 = 300, x2 = WIDTH - 200, y2 = HEIGHT - 300},
    
        {x1 = WIDTH - 150, y1 = HEIGHT - 200, x2 = WIDTH, y2 = HEIGHT}
    }
end

-- This function gets called once every frame
function draw()
    background(255)

    -- Do your drawing here
    for i, blockedZone in ipairs(blockedZones) do
        stroke(145, 145, 145, 255) strokeWidth(2)
        fill(145, 145, 145, 71) rectMode(CORNERS)
        rect(blockedZone.x1 - 2, blockedZone.y1 - 2, blockedZone.x2 + 4, blockedZone.y2 + 4)
        local wScale = (blockedZone.x2 - blockedZone.x1) / (blockedZone.y2 - blockedZone.y1)
        local h = (blockedZone.y2 - blockedZone.y1) / 20
        local w = h * wScale
        local numStripes = (blockedZone.x2 - blockedZone.x1) / w
        for stripe = 1, numStripes do
            local x1, y1, x2, y2
            x1 = blockedZone.x1 + (w * (stripe - 1))
            y2 = blockedZone.y2 - (h * (stripe - 1))
            x2 = x1 + w
            y1 = y2 - h
                    
            line(blockedZone.x1, y1, x2, blockedZone.y2)
            line(x1, blockedZone.y1, blockedZone.x2, y2)
        end
    end
end

But it eats up the FPS, especially with multiple on the screen at once. I was wondering if it is possible to do something like this with a shader, similar to the brick shader, and if that would be more efficient.

It’s absolutely possible. Sadly I don’t have my iPad (and won’t for a while), so I can’t attempt one, but I’d suggest attempting it with a plain Codea image in Lua code to get out the (simple) math, then convert it to the fragment shader.

@Zoyt, I have the math but it uses lines and I don’t know how/if you can do that in fragment shaders.

@JakAttak - why not just create an image in memory with all the lines in it, then sprite that when you draw? Or maybe you can use this image as your background?

@Ignatz, just making an image and spriting it will make them appear stretched.

@JakAttak I’d make you one but I’m away from my iPad! As ignatz said the image will work!

@JakAttak - if the image is full screen size, how will it get stretched?

@JakAttak - Basically, in the fragment shader, test if vTexCoord (a vec2) if on either the first or second stripe. So it’s basically like manually creating the images, but faster and does a lot for you. So basically, test if vTexCoord is on the first stripe, then set gl_FragColor to the color you want. Else, set gl_FragColor to the second color.
Shaders are really a massive thing to take on and super overwhelming at first, but I suggest you just skim @Ignat’s shader book (if you haven’t already).
Thanks!

@Ignatz, I may have misunderstood, but if you mean one image to use for all of them then they will look squished or stretched based on the dimensions of the zone and the image.

@JakAttak - from your example, it looked like the grids had a fixed size and location, so you just needed to draw all of them once on an image the size of the screen. Do they change in size and location during the game?

No they don’t. What I’m trying to say is that the zones are all different sizes and using the same image for all of them would make some looked stretched an some squished comparatively.

@JakAttak - then why not draw all the zones on one big image, at the beginning?

@Ignatz, hmm… Good idea! Thanks you.