So I was looking through the available filters here, and they all seem to be bitmap filters (like Photoshop filters) rather than shape filters. Is there any way to, for example, make a circle look beveled like it has slightly three-dimensional edges? Flash has drop shadows and glow filters, things that apply to the actual shape of vector graphics.
Maybe you could achieve it with the right normal maps, but otherwise this might call for custom effects. The stuff you’re asking about requires some knowledge of the geometry, some preprocessed information (e.g. the normal maps), or the ability to only ask about its nearest neighbors. These limits come because a shader is a massively parallel operation done independently by each pixel, but they achieve this by operating mostly in isolation and not being able to write to fellow pixels’ locations.
In the case of a circle you have a very regular geometry: x2 + y2 = r2, that you can exploit, knowing that normalized texture coordinates (which is what you get in a shader) go from 0 to 1 in each direction, with (.5, .5) being the center for a typical object.
For instance, this looks at how far along the radius you are: an effect
It figures out the offset from the center between -.5 and +.5, gets the absolute value and divides that in turn to get a 0-to-1 position along the radius. (The step() at the end just turns pixels outside this range black / transparent. You can omit it on a circle display object.) Then it tries to ramp this value up by raising its power. Other functions are good for this too, like DSP filters.
Try playing with the x coordinate to see different powers at work. With small ones you get some feathering, with larger ones it gets a bit stronger.
Something similar that gives some basic lighting is this, some dot product lighting that assumes a plane surface (for beveling you might go with something like a capsule, lozenge, etc.), or with some smoothing. And of course you can build these up, though it’s not necessarily easy!
With meshes you can even lay out the texture coordinates to accommodate the effect.
Anyhow, just some food for thought. Maybe others have ideas too.
Hmm, I don’t know that an actual mathematical representation of the shape would be needed. Photoshop actually does have all the filters Flash does. It just looks at the pixels that aren’t transparent to indicate where the “shape” is. So for example, a drop shadow could be made by duplicating the image, converting all color to black while keeping the alpha values, and shifting the new image to the side a little.
something like this maybe? perhaps just as a start, tweak further as desired…
local R = 50 local baseCanvas = graphics.newTexture({ type="canvas", width=R\*2, height=R\*2 }) local baseCircle = display.newCircle(0,0,R) baseCircle:setFillColor(0.2,0.5,1) baseCanvas:draw(baseCircle) local lightCanvas = graphics.newTexture({ type="canvas", width=R\*2, height=R\*2 }) local lightCircle = display.newCircle(0,0,R) lightCircle.fill = { type = "gradient", color1 = { 1, 1, 1 }, color2 = { 0, 0, 0 }, direction = "down" } lightCircle.rotation = -45 lightCanvas:draw(lightCircle) local knockout = display.newCircle(0,0,R\*0.8) knockout:setFillColor(0.5,0.5,0.5) lightCanvas:draw(knockout) baseCanvas:invalidate() lightCanvas:invalidate() local comp = display.newCircle(R,R,R) comp.fill = { type="composite", paint1={ type="image", filename=baseCanvas.filename, baseDir=baseCanvas.baseDir }, paint2={ type="image", filename=lightCanvas.filename, baseDir=lightCanvas.baseDir }, } comp.fill.effect = "composite.hardLight"
Hey, that’s a nice-looking bevel. Well done!
Maybe you could achieve it with the right normal maps, but otherwise this might call for custom effects. The stuff you’re asking about requires some knowledge of the geometry, some preprocessed information (e.g. the normal maps), or the ability to only ask about its nearest neighbors. These limits come because a shader is a massively parallel operation done independently by each pixel, but they achieve this by operating mostly in isolation and not being able to write to fellow pixels’ locations.
In the case of a circle you have a very regular geometry: x2 + y2 = r2, that you can exploit, knowing that normalized texture coordinates (which is what you get in a shader) go from 0 to 1 in each direction, with (.5, .5) being the center for a typical object.
For instance, this looks at how far along the radius you are: an effect
It figures out the offset from the center between -.5 and +.5, gets the absolute value and divides that in turn to get a 0-to-1 position along the radius. (The step() at the end just turns pixels outside this range black / transparent. You can omit it on a circle display object.) Then it tries to ramp this value up by raising its power. Other functions are good for this too, like DSP filters.
Try playing with the x coordinate to see different powers at work. With small ones you get some feathering, with larger ones it gets a bit stronger.
Something similar that gives some basic lighting is this, some dot product lighting that assumes a plane surface (for beveling you might go with something like a capsule, lozenge, etc.), or with some smoothing. And of course you can build these up, though it’s not necessarily easy!
With meshes you can even lay out the texture coordinates to accommodate the effect.
Anyhow, just some food for thought. Maybe others have ideas too.
Hmm, I don’t know that an actual mathematical representation of the shape would be needed. Photoshop actually does have all the filters Flash does. It just looks at the pixels that aren’t transparent to indicate where the “shape” is. So for example, a drop shadow could be made by duplicating the image, converting all color to black while keeping the alpha values, and shifting the new image to the side a little.
something like this maybe? perhaps just as a start, tweak further as desired…
local R = 50 local baseCanvas = graphics.newTexture({ type="canvas", width=R\*2, height=R\*2 }) local baseCircle = display.newCircle(0,0,R) baseCircle:setFillColor(0.2,0.5,1) baseCanvas:draw(baseCircle) local lightCanvas = graphics.newTexture({ type="canvas", width=R\*2, height=R\*2 }) local lightCircle = display.newCircle(0,0,R) lightCircle.fill = { type = "gradient", color1 = { 1, 1, 1 }, color2 = { 0, 0, 0 }, direction = "down" } lightCircle.rotation = -45 lightCanvas:draw(lightCircle) local knockout = display.newCircle(0,0,R\*0.8) knockout:setFillColor(0.5,0.5,0.5) lightCanvas:draw(knockout) baseCanvas:invalidate() lightCanvas:invalidate() local comp = display.newCircle(R,R,R) comp.fill = { type="composite", paint1={ type="image", filename=baseCanvas.filename, baseDir=baseCanvas.baseDir }, paint2={ type="image", filename=lightCanvas.filename, baseDir=lightCanvas.baseDir }, } comp.fill.effect = "composite.hardLight"
Hey, that’s a nice-looking bevel. Well done!