Search code examples
colorsluablendinglove2d

Creating a fog effect that varies with alpha


I'm trying to implement "fog-of-war" in a mapping tool I'm developing.

For each grid cell, if a cell is "fogged", the color is set to grey multiplied by the cell's current color. Otherwise, the cell color is set to whatever color the cell normally should be.

Below is my draw function.

for x = 0, (self.gridSize - 1) * self.scale, self.scale do
        for y = 0, (self.gridSize - 1) * self.scale, self.scale do
            local mouseX, mouseY = camera:mousepos()

            local curCell = self:getCell(x, y, true)
            local state = Grid:getState(x, y, true)

            if fog and curCell.fogged then
                local color = multiplyColors(curCell.color, {100,100,100,10})
                color[4] = 150
                if curCell:getState() == 1 then
                    love.graphics.setColor(color)
                else
                    love.graphics.setColor({100, 100, 100, 100})
                end
                love.graphics.rectangle('fill', x, y, self.scale, self.scale)
            elseif math.floor(mouseX / self.scale) == math.floor(x / self.scale) and math.floor(mouseY / self.scale) == math.floor(y / self.scale) then
                love.graphics.setColor(255, 0, 0, 30)
                love.graphics.rectangle('fill', x, y, self.scale, self.scale)

            elseif state == 1 then
                love.graphics.setColor(curCell.color)
                love.graphics.rectangle('fill', x, y, self.scale, self.scale)

            elseif state == 0 and self.bGridLines then
                love.graphics.setColor(100, 100, 100, 10)
                love.graphics.rectangle('line', x, y, self.scale, self.scale)
            end
        end
    end

And here's the multiplyColors function

function multiplyColors(c1, c2)
    local newColor = {}

    newColor[1] = math.floor((c1[1] * c2[1]) / 255)
    newColor[2] = math.floor((c1[2] * c2[2]) / 255)
    newColor[3] = math.floor((c1[3] * c2[3]) / 255)

    return newColor

end

While this creates an okay-looking effect, I need the ability to set the fog opacity.

For example, if I change the line color[4] = 150 to color[4] = 255, the desired output should be something like this instead of what I actually get when changing that line. Likewise, changing the line to color[4] = 0 yields this (which admittedly looks sorta neat) instead of something like this.

Here is a link to the complete repository: https://github.com/camdenb/DnD-Map-Creator

Thanks!


Solution

  • An easy way to get different opacity levels in your fog would be to draw the fog over the whole screen by writing outside your loops:

    love.graphics.setBackgoundColor(100, 100, 100) -- fog, everywhere
    

    Afterward, if a cell is foggy then draw it with a lower alpha value to expose the fog underneath.

       if fogged and curCell.fogged then
          local c = curCell.color
          -- you can change 100 for various amounts of fog
          -- 0 means all fog and 255 means no fog
          love.graphics.setColor(c[1], c[2], c[3], 100)
          -- more code to draw...
       end
    

    You may want to experiment with different blend modes. The LÖVE wiki has a few examples to get different effects when blending the fog background with the cells being drawn over top.