For example the checkered texture with white polygon:
Code: Select all
Width, Height = love.graphics.getDimensions ()
PixelSize = 16
love.graphics.setDefaultFilter ('nearest', 'nearest')
-- prepare checker texture
local checker = love.graphics.newCanvas (Width, Height, {dpiscale=1/PixelSize})
love.graphics.setCanvas (checker)
for y = 0, Height-1*PixelSize, PixelSize do
for x = 0, Width-1*PixelSize, PixelSize do
if (x/PixelSize+y/PixelSize)%(2) == 0 then
love.graphics.setColor (0.2,0.2,0.2)
else
love.graphics.setColor (0.4,0.4,0.4)
end
love.graphics.rectangle ('fill', x,y, PixelSize, PixelSize)
end
end
Polygon = {10, 300, 400,30, 700,200, 200,500}
love.graphics.setColor (1,1,1)
love.graphics.polygon ('fill', Polygon)
love.graphics.setCanvas ()
function love.draw()
love.graphics.draw (checker)
end
- Screenshot 2023-05-20 005838.png (8.48 KiB) Viewed 1323 times
-------------------------------
And the pixelated polygon (move mouse to change geometry) with texture on it (of coarse here can be any texture, not checkered or low-dpi):
Code: Select all
Width, Height = love.graphics.getDimensions ()
PixelSize = 16
love.graphics.setDefaultFilter ('nearest', 'nearest')
-- prepare checker texture
local checker = love.graphics.newCanvas (Width, Height, {dpiscale=1/PixelSize})
love.graphics.setCanvas (checker)
for y = 0, Height-1*PixelSize, PixelSize do
for x = 0, Width-1*PixelSize, PixelSize do
if (x/PixelSize+y/PixelSize)%(2) == 0 then
love.graphics.setColor (0.2,0.2,0.2)
else
love.graphics.setColor (0.4,0.4,0.4)
end
love.graphics.rectangle ('fill', x,y, PixelSize, PixelSize)
end
end
love.graphics.setCanvas ()
local function getMask (polygon)
local mask = love.graphics.newCanvas (Width, Height, {dpiscale=1/PixelSize})
love.graphics.setCanvas (mask)
love.graphics.setColor (1,1,1)
love.graphics.polygon ('fill', polygon)
love.graphics.setCanvas ()
return mask
end
local mask_shader = love.graphics.newShader[[
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
if (Texel(texture, texture_coords).rgb == vec3(0.0)) {
// a discarded pixel wont be applied as the stencil.
discard;
}
return vec4(1.0);
}
]]
local function myStencilFunction()
love.graphics.setShader(mask_shader)
love.graphics.draw(Mask, 0, 0)
love.graphics.setShader()
end
function love.load()
Polygon = {10, 300, 400,30, 700,200, 200,500}
Mask = getMask (Polygon)
ResultCanvas = love.graphics.newCanvas (Width, Height, {dpiscale=1/PixelSize})
love.graphics.setCanvas ({ResultCanvas, stencil=true})
love.graphics.stencil(myStencilFunction, "replace", 1)
love.graphics.setStencilTest("greater", 0)
love.graphics.draw(checker)
love.graphics.setStencilTest()
love.graphics.setCanvas ()
end
function love.draw()
-- love.graphics.draw (checker)
love.graphics.draw (ResultCanvas)
end
function love.mousemoved (x, y)
Polygon[#Polygon-1], Polygon[#Polygon] = x, y
Mask = getMask (Polygon)
ResultCanvas = love.graphics.newCanvas (Width, Height, {dpiscale=1/PixelSize})
love.graphics.setCanvas ({ResultCanvas, stencil=true})
love.graphics.stencil(myStencilFunction, "replace", 1)
love.graphics.setStencilTest("greater", 0)
love.graphics.draw(checker)
love.graphics.setStencilTest()
love.graphics.setCanvas ()
end
- Screenshot 2023-05-20 011543.png (8.01 KiB) Viewed 1322 times
-------------------------------------------------
And the version with rotating polygon:
Code: Select all
Width, Height = love.graphics.getDimensions ()
PixelSize = 16
love.graphics.setDefaultFilter ('nearest', 'nearest')
-- prepare checker texture
local checker = love.graphics.newCanvas (Width, Height, {dpiscale=1/PixelSize})
love.graphics.setCanvas (checker)
for y = 0, Height-1*PixelSize, PixelSize do
for x = 0, Width-1*PixelSize, PixelSize do
if (x/PixelSize+y/PixelSize)%(2) == 0 then
love.graphics.setColor (0.2,0.2,0.2)
else
love.graphics.setColor (0.4,0.4,0.4)
end
love.graphics.rectangle ('fill', x,y, PixelSize, PixelSize)
end
end
love.graphics.setCanvas ()
local function getMask (polygon)
local cx, cy, angle = polygon.cx, polygon.cy, polygon.angle
local mask = love.graphics.newCanvas (Width, Height, {dpiscale=1/PixelSize}) -- change this solution to not create new canvas on each frame! :x
love.graphics.setCanvas (mask)
love.graphics.setColor (1,1,1)
love.graphics.push ()
love.graphics.translate (cx, cy)
love.graphics.rotate (angle)
love.graphics.translate (-cx, -cy)
love.graphics.polygon ('fill', polygon)
love.graphics.pop ()
love.graphics.setCanvas ()
return mask
end
local mask_shader = love.graphics.newShader[[
vec4 effect(vec4 color, Image texture, vec2 texture_coords, vec2 screen_coords) {
if (Texel(texture, texture_coords).rgb == vec3(0.0)) {
// a discarded pixel wont be applied as the stencil.
discard;
}
return vec4(1.0);
}
]]
local function myStencilFunction()
love.graphics.setShader(mask_shader)
love.graphics.draw(Mask, 0, 0)
love.graphics.setShader()
end
function love.load()
Polygon = {10, 300, 400,30, 700,200, 200,500}
Polygon.cx, Polygon.cy = 400, 250
Polygon.angle, Polygon.omega = 0, 0.3
end
function love.update(dt)
Polygon.angle = Polygon.angle + dt*Polygon.omega
Mask = getMask (Polygon)
ResultCanvas = love.graphics.newCanvas (Width, Height, {dpiscale=1/PixelSize})
love.graphics.setCanvas ({ResultCanvas, stencil=true})
love.graphics.stencil(myStencilFunction, "replace", 1)
love.graphics.setStencilTest("greater", 0)
love.graphics.draw(checker)
love.graphics.setStencilTest()
love.graphics.setCanvas ()
end
function love.draw()
-- love.graphics.draw (checker)
love.graphics.draw (ResultCanvas)
end
function love.mousemoved (x, y)
Polygon[#Polygon-1], Polygon[#Polygon] = x, y
end