dcearth/map/blur.lua

113 lines
2.8 KiB
Lua

local love = assert( love )
local lg = love.graphics
local lt = love.timer
local coroutine = assert( coroutine )
local bmp = require 'map.bmp'
local scale = 1
local w, h = scale * 512, scale * 285
local dilateShader = require 'shaders.dilate'
local finalCanvas = lg.newCanvas( w, h )
local canvas = lg.newCanvas( w, h )
local identityTransform = love.math.newTransform()
local tiles = {}
do
local sideLength = 4
local i = 1
for x = 1, sideLength do
for y = 1, sideLength do
local width = math.floor( w / sideLength )
local height = math.floor( h / sideLength )
tiles[i] = function() return
(x - 1) * width, (y - 1) * height,
width, height
end
i = i + 1
end
end
end
--the coroutine library doesn't reset all the global graphics state for us
--so this yield function does
local function y( s, currentTile )
lg.pop( "all" )
coroutine.yield( s )
lg.push( "all" )
lg.setCanvas( canvas )
lg.setShader( dilateShader )
lg.setScissor( currentTile() )
lg.setBlendMode( "add" )
end
local function renderRadar( map, filename )
local statusString = "%s: rendering %s radius\n %s\n %d/%d"
--we need this first push to the stack to keep y() simple
lg.push( "all" )
y( filename, tiles[1] )
--then we clear the whole canvas to opaque black, pause, and select the first tile
lg.setScissor()
lg.clear( 0, 0, 0, 1 )
dilateShader:send( "sailable", map.sailable.img )
for tile = 1, #tiles do
--dilate placeable land area by 30 degrees (radar radius)
dilateShader:send( "radius", math.floor( 512 * 30 / 360 ) )
for name, terr in pairs( map.territory ) do
y( statusString:format( filename, "radar", name, tile, #tiles ), tiles[tile] )
lg.setColor(
0.9 + terr.colour[1],
0.9 + terr.colour[2],
0.9 + terr.colour[3],
1 / 6 )
lg.draw( terr.img, 0, 0, 0, scale, scale )
end
--dilate placeable land area by 45 degrees (sub launch radius)
dilateShader:send( "radius", math.floor( 512 * 45 / 360 ) )
for name, terr in pairs( map.territory ) do
y( statusString:format( filename, "sub", name, tile, #tiles ), tiles[tile] )
lg.setColor(
0.9 + terr.colour[1],
0.9 + terr.colour[2],
0.9 + terr.colour[3],
1 / 12 )
lg.draw( terr.img, 0, 0, 0, scale, scale )
end
end
lg.setCanvas( finalCanvas )
lg.setScissor()
lg.setShader()
lg.clear( 0, 0, 0, 1 )
lg.setColor( 1, 1, 1, 1 )
lg.draw( canvas )
lg.pop( "all" )
coroutine.yield( ("%s: encoding image data"):format( filename ))
return bmp.blur( finalCanvas:newImageData() )
end
local t = {}
function t:save( )
return renderRadar( self.map, self.filename )
end
function t.load( filename, map )
t.filename = filename
t.map = map
return t
end
function t.draw()
lg.setScissor()
return lg.draw( canvas )
end
return t