Skip to content

Instantly share code, notes, and snippets.

@ruccho
Last active April 8, 2024 02:19
Show Gist options
  • Star 50 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save ruccho/efa1139ddd6da6d4d22def161209d2e7 to your computer and use it in GitHub Desktop.
Save ruccho/efa1139ddd6da6d4d22def161209d2e7 to your computer and use it in GitHub Desktop.
The enhanced version of this script is available: https://gist.github.com/ruccho/2d1eb4aea3dfa55690c2ddc4419172ff
----------------------------------------------------------------------
-- Generate Normal Map
--
-- It works only for RGB color mode.
----------------------------------------------------------------------
if app.apiVersion < 1 then
return app.alert("This script requires Aseprite v1.2.10-beta3")
end
local cel = app.activeCel
if not cel then
return app.alert("There is no active image")
end
local img = cel.image:clone()
local position = cel.position
if img.colorMode == ColorMode.RGB then
local rgba = app.pixelColor.rgba
local rgbaA = app.pixelColor.rgbaA
for it in img:pixels() do
local x = it.x
local y = it.y
local top = 2
local left = 2
local right = 2
local bottom = 2
if rgbaA(it()) < 255 then
-- Transparent pixel to ignore
else
-- Pixel to prcess
-- explore top
if y > 0 then
-- possible to explore
local topPixel = img:getPixel(x, y - 1)
if rgbaA(topPixel) < 255 then
top = 0
elseif y > 1 then
topPixel = img:getPixel(x, y - 2)
if rgbaA(topPixel) < 255 then
top = 1
end
end
else
top = 0
end
-- explore bottom
if y < img.height - 1 then
-- possible to explore
local bottomPixel = img:getPixel(x, y + 1)
if rgbaA(bottomPixel) < 255 then
bottom = 0
elseif y < img.height - 2 then
bottomPixel = img:getPixel(x, y + 2)
if rgbaA(bottomPixel) < 255 then
bottom = 1
end
end
else
bottom = 0
end
-- explore left
if x > 0 then
-- possible to explore
local leftPixel = img:getPixel(x - 1, y)
if rgbaA(leftPixel) < 255 then
left = 0
elseif x > 1 then
leftPixel = img:getPixel(x - 2, y)
if rgbaA(leftPixel) < 255 then
left = 1
end
end
else
left = 0
end
-- explore right
if x < img.width - 1 then
-- possible to explore
local rightPixel = img:getPixel(x + 1, y)
if rgbaA(rightPixel) < 255 then
right = 0
elseif x < img.width - 2 then
rightPixel = img:getPixel(x + 2, y)
if rgbaA(rightPixel) < 255 then
right = 1
end
end
else
right = 0
end
local light = 0
-- -2 ~ +2
local y_digit = - top + bottom
local y = y_digit * 32 + 128
local x_digit = - right + left
local x = x_digit * 32 + 128
local z_digit = math.max(math.abs(x_digit), math.abs(y_digit))
local z = z_digit * -32 + 255
local color = rgba(x,y,z,255)
it(color)
end
end
elseif img.colorMode == ColorMode.GRAY then
return app.alert("This script is only for RGB Color Mode")
elseif img.colorMode == ColorMode.INDEXED then
return app.alert("This script is only for RGB Color Mode")
end
local sprite = app.activeSprite
local frame = app.activeFrame
local currentLayer = app.activeLayer
local newLayerName = currentLayer.name .. "_NormalGenerated"
local newLayer = nil
for i,layer in ipairs(sprite.layers) do
if layer.name == newLayerName then
-- the layer to write normal on is already exists
newLayer = layer
end
end
if newLayer == nil then
newLayer = sprite:newLayer()
newLayer.name = newLayerName
end
local newCel = sprite:newCel(newLayer, frame, img, position)
app.refresh()
@flamendless
Copy link

flamendless commented Mar 9, 2019

I have the latest aseprite version, but i get this attempt to compare nil with number at line 7

commenting out that part, a out of bounds error shows at line 128

@metalim
Copy link

metalim commented Jun 26, 2019

Works in 1.2.12.1. But requires baked layer, doesn't work with Groups.
Also script is not for proper normal map creation (from grayscale image of "depth" values), but rather treats each pixel as "all or nothing", "automatically" smoothing edges of a sprite.

@giodot
Copy link

giodot commented Dec 6, 2019

Is it possible for you to add an invert Y option?

@PapaCheese
Copy link

Is it possible for you to add an invert Y option?

just add a - before the y in line 102 :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment