Stencil buffer or something like

Hi,

I’m new in Corona, so I have a problem.

I have to know how to change colour for overlay zone like on image.

This is not a mixing colour. There are three different colours, that I need to setup. 

Red, purple and blue.

On the last engine , I created this with stencil buffer, but I can’t fine options to do it with Corona.

BTW for lines I have the same problem. I need this result 

There are two lines, and when these lines crossing or overlay, I need the third colour. 

Thanks a lot

Regards.

There are two things that might help you.

Blend Modes:   https://docs.coronalabs.com/api/type/Paint/blendMode.html

and

Fills: https://docs.coronalabs.com/guide/graphics/path.html

Rob

Thanks Rob.

But Blend Modes just use base two colours from object to create third colour. But I need to setup different colours. 

I can’t create for example blue colour when I will mix red and green. Or for example I need specific colour.

So, I have to do it dynamically because these two circles will moved.

Solution can be, for example - something like overlay_object.color = pink. 

Or some api like stencil, where we can test how many objects in these zone and change colour for example.

Like this 

cjoKk.png

Can you replicate what you want in photoshop easily?  A lot of photoshop filters and blend modes can be done in Corona.  If you can’t do it in photoshop with simple layer blends then you will have to code it dynamically.

Thanks. Will try to do it in Photoshop. As I understood there is a library to create filters and blend modes in Corona?

BTW how I can code it dynamically. Maybe this is a solution. How can I get overlay zone? Is there some api or methods.

Thanks a lot for answers. 

These are the filters and blends you can do in Corona.

Tried to do it via blend and filters. Not successful. 

So, I have to do it manually and dynamically. But I don’t know how. 

Can I use dynamic mask for example? I know how to create it for circles, but not for lines

Thanks

I did a little research on stencil buffers and that sounds like something a custom shader would do. We have several community members who are really good writing OpenGL shaders. Let me see if I can get someone to look into this thread and offer some advice.

Rob

Hi.

I had a go and seem to have something working. This uses the memory bitmap plugin, so see the instructions for that.

local memoryBitmap = require("plugin.memoryBitmap") -- Save the current texture filter settings. Temporarily set them to -- nearest mode, since we want to snap to colors rather than blend -- with our neighbors. local def = display.getDefault("minTextureFilter") display.setDefault("minTextureFilter", "nearest") -- Make a one-dimensional texture to store as many colors as we support. It -- might be best if this is a power-of-2, but maybe it doesn't matter. local Width = 4 local colors = memoryBitmap.newTexture{ width = Width, height = 1, format = "rgb" } -- Put color #1 in column #1, #2 in column #2, etc. colors:setPixel(1, 1, 0, 1, 0) -- green at (1, 1) colors:setPixel(2, 1, 1, 0, 0) -- red at (2, 1) -- Restore the previous filter mode. display.setDefault("minTextureFilter", def) -- Render our geometry in a canvas so that we can reference it in our effect local function Rect (canvas, x, y, w, h) local rect = display.newRect(x, y, w, h) rect.blendMode = "add" -- Accumulate the object... rect:setFillColor(1 / Width) -- ...by this much. (The final result is the -- offset into our color set.) This emulates -- stencil addition, basically. canvas:draw(rect) return rect end -- Define the region that will display the effect. local region = display.newRect(display.contentCenterX, display.contentCenterY, 250, 250) -- Make a canvas into which the objects will be rendered. local canvas = graphics.newTexture{ type = "canvas", width = region.width, height = region.height } -- Create a P-shaped object like the one in your example above, stuffing -- the pieces into the canvas. Rect(canvas, -10, 20, 110, 20) Rect(canvas, 35, -40, 20, 100) Rect(canvas, -10, -80, 70, 20) Rect(canvas, -35, 0, 20, 140) local r = Rect(canvas, -50, -80, 60, 20) r.rotation = -45 -- Commit the draw calls to the canvas. canvas:invalidate() -- Register an effect to the draw region that takes the canvas in sampler #0 and -- the color map in sampler #1. region.fill = { type = "composite", paint1 = { type = "image", filename = canvas.filename, baseDir = canvas.baseDir }, paint2 = { type = "image", filename = colors.filename, baseDir = colors.baseDir } } -- Create a blend effect. local kernel = { category = "composite", name = "blender" } kernel.fragment = [[P\_COLOR vec4 FragmentKernel (P\_UV vec2 uv) { P\_COLOR float frac = texture2D(CoronaSampler0, uv).r; // Fetch the accumulated offset from // the canvas if (frac \> 0.0) // Any object crossed this pixel? { P\_COLOR vec3 color = texture2D(CoronaSampler1, vec2(frac, 0.0)).rgb; // Read the color from // that offset in the // color set return vec4(color, 1.0); } else return vec4(0.0); // No object: transparent }]] graphics.defineEffect(kernel) -- Apply the effect to the region. region.fill.effect = "composite.custom.blender"

I’ve tried to explain what’s going on, but let me know if you need more information. Obviously if this is dynamic you’ll need to adjust some of this.

Hi

Thanks a lot it’s very useful. I tried to do this code. The result is

So, as I understood something wrong with offset for colour choose.

I’m not clearly understood what is Width varible. Number of colours, but with this  

 rect:setFillColor(1 / Width)

Thanks a lot for your code. Will investigate and try to change :slight_smile:

Regards

Whoops, sorry. Change each instance of “minTextureFilter” to “magTextureFilter”. I did notice the colors were off, but figured it was a reasonable start. Just tried now with the other key and it seems to work.

Width is the maximum number of colors in the “color set”. I rounded it up to 4, though as I say in the comments maybe a non-power-of-2 would be okay. In Corona’s shaders, texture coordinates will have been mapped to the [0, 1] range, so pixel #1 is found in the interval [0, 1 / Width], #2 in [1 / Width , 2 / Width], etc. Nearest filtering keeps these from blending together.

By assigning 1 / Width as the “color”, we’re basically assigning the per-object density. Additive blending makes these layer on as they cross the same spot. Rather than containing conventional color information, the canvas contains these densities; “denser” parts have a further offset into the color set.

Off-hand I don’t know if it’s wise to read right at the color set’s pixel boundary; non-power-of-2 widths might have issues, for instance. Maybe subtracting half a pixel would be more robust. This could be string.format()'d into the shader source using Width , or added as a shader parameter.

Yep it’s working. Thanks a lot. :D  :smiley:

Will try to do it dynamically with three colours and circles like in first post. 

Thanks

There are two things that might help you.

Blend Modes:   https://docs.coronalabs.com/api/type/Paint/blendMode.html

and

Fills: https://docs.coronalabs.com/guide/graphics/path.html

Rob

Thanks Rob.

But Blend Modes just use base two colours from object to create third colour. But I need to setup different colours. 

I can’t create for example blue colour when I will mix red and green. Or for example I need specific colour.

So, I have to do it dynamically because these two circles will moved.

Solution can be, for example - something like overlay_object.color = pink. 

Or some api like stencil, where we can test how many objects in these zone and change colour for example.

Like this 

cjoKk.png

Can you replicate what you want in photoshop easily?  A lot of photoshop filters and blend modes can be done in Corona.  If you can’t do it in photoshop with simple layer blends then you will have to code it dynamically.

Thanks. Will try to do it in Photoshop. As I understood there is a library to create filters and blend modes in Corona?

BTW how I can code it dynamically. Maybe this is a solution. How can I get overlay zone? Is there some api or methods.

Thanks a lot for answers. 

These are the filters and blends you can do in Corona.

Tried to do it via blend and filters. Not successful. 

So, I have to do it manually and dynamically. But I don’t know how. 

Can I use dynamic mask for example? I know how to create it for circles, but not for lines

Thanks

I did a little research on stencil buffers and that sounds like something a custom shader would do. We have several community members who are really good writing OpenGL shaders. Let me see if I can get someone to look into this thread and offer some advice.

Rob

Hi.

I had a go and seem to have something working. This uses the memory bitmap plugin, so see the instructions for that.

local memoryBitmap = require("plugin.memoryBitmap") -- Save the current texture filter settings. Temporarily set them to -- nearest mode, since we want to snap to colors rather than blend -- with our neighbors. local def = display.getDefault("minTextureFilter") display.setDefault("minTextureFilter", "nearest") -- Make a one-dimensional texture to store as many colors as we support. It -- might be best if this is a power-of-2, but maybe it doesn't matter. local Width = 4 local colors = memoryBitmap.newTexture{ width = Width, height = 1, format = "rgb" } -- Put color #1 in column #1, #2 in column #2, etc. colors:setPixel(1, 1, 0, 1, 0) -- green at (1, 1) colors:setPixel(2, 1, 1, 0, 0) -- red at (2, 1) -- Restore the previous filter mode. display.setDefault("minTextureFilter", def) -- Render our geometry in a canvas so that we can reference it in our effect local function Rect (canvas, x, y, w, h) local rect = display.newRect(x, y, w, h) rect.blendMode = "add" -- Accumulate the object... rect:setFillColor(1 / Width) -- ...by this much. (The final result is the -- offset into our color set.) This emulates -- stencil addition, basically. canvas:draw(rect) return rect end -- Define the region that will display the effect. local region = display.newRect(display.contentCenterX, display.contentCenterY, 250, 250) -- Make a canvas into which the objects will be rendered. local canvas = graphics.newTexture{ type = "canvas", width = region.width, height = region.height } -- Create a P-shaped object like the one in your example above, stuffing -- the pieces into the canvas. Rect(canvas, -10, 20, 110, 20) Rect(canvas, 35, -40, 20, 100) Rect(canvas, -10, -80, 70, 20) Rect(canvas, -35, 0, 20, 140) local r = Rect(canvas, -50, -80, 60, 20) r.rotation = -45 -- Commit the draw calls to the canvas. canvas:invalidate() -- Register an effect to the draw region that takes the canvas in sampler #0 and -- the color map in sampler #1. region.fill = { type = "composite", paint1 = { type = "image", filename = canvas.filename, baseDir = canvas.baseDir }, paint2 = { type = "image", filename = colors.filename, baseDir = colors.baseDir } } -- Create a blend effect. local kernel = { category = "composite", name = "blender" } kernel.fragment = [[P\_COLOR vec4 FragmentKernel (P\_UV vec2 uv) { P\_COLOR float frac = texture2D(CoronaSampler0, uv).r; // Fetch the accumulated offset from // the canvas if (frac \> 0.0) // Any object crossed this pixel? { P\_COLOR vec3 color = texture2D(CoronaSampler1, vec2(frac, 0.0)).rgb; // Read the color from // that offset in the // color set return vec4(color, 1.0); } else return vec4(0.0); // No object: transparent }]] graphics.defineEffect(kernel) -- Apply the effect to the region. region.fill.effect = "composite.custom.blender"

I’ve tried to explain what’s going on, but let me know if you need more information. Obviously if this is dynamic you’ll need to adjust some of this.