This script is available for JASS, vJass, Lua, and Wurst.
Features
It features 1D, 2D, and 3D Perlin noise.
It uses a permutation table. It represents as an array in JASS/vJass/Wurst and an integer table for Lua. As it follow Kenneth Perlin's implementation, the first 256 elements (0 - 255) contains random integer values ranges from 0 to 255. The elements from 256 - 512 only repeats the values of the first 256 elements. I think it is to avoid overflow?
You can modify the permutation table to satisfy your needs.
Popular sandbox games like Minecraft and Terraria uses a similar algorithm to create procedural generated terrain. This means you could now do the same in Warcraft III.
For Wurst, you can use Grill to add wurstNoiselib as a dependency to your project:
Code: Select all
grill install https://github.com/eGlint/wurstNoiselib
None (JASS/vJASS/Lua)
WurstStdlib2 (Wurst)
Optional
OctavePerlin (plugin for Perlin Noise, comes along with it, source)
For JASS version, it requires the following GUI variables:
NoisePermutation (integer array)
JASS:
Code: Select all
//
// Perlin Noise JASS v1.0.0
//
// Port by Glint
// Perlin Noise by Kenneth Perlin, https://mrl.nyu.edu/~perlin/noise/
//
function Floor takes real value returns integer
local integer n = R2I(value)
if value < 0 and value - n != 0. then
set n = n - 1
endif
return n
endfunction
function RealTernaryOp takes boolean cond, real a, real b returns real
if cond then
return a
else
return b
endif
endfunction
function Fade takes real t returns real
return t * t * t * (t * (t * 6. - 15.) + 10.)
endfunction
function Lerp takes real t, real a, real b returns real
return a + t * (b -a)
endfunction
function Gradient1D takes integer hash, real x returns real
local integer h = BlzBitAnd(hash, 15)
return RealTernaryOp(BlzBitAnd(h, 1) == 0, x, -x)
endfunction
function PerlinNoise1D takes real x returns real
local integer X = BlzBitAnd(Floor(x), 255)
set x = x - Floor(x)
return Lerp(Fade(x), Gradient1D(udg_NoisePermutation[X], x), Gradient1D(udg_NoisePermutation[X + 1], x - 1)) * 2
endfunction
function Gradient2D takes integer hash, real x, real y returns real
local integer h = BlzBitAnd(hash, 15)
local real u = RealTernaryOp(h < 8, x, y)
local real v = RealTernaryOp(h < 4, y, x)
return RealTernaryOp(BlzBitAnd(h, 1) == 0, u, -u) + RealTernaryOp(BlzBitAnd(h, 2) == 0, v, -v)
endfunction
function PerlinNoise2D takes real x, real y returns real
local integer X = BlzBitAnd(Floor(x), 255)
local integer Y = BlzBitAnd(Floor(y), 255)
local real u
local real v
local integer A
local integer B
local real lerpA1
local real lerpA2
set x = x - Floor(x)
set y = y - Floor(y)
set u = Fade(x)
set v = Fade(y)
set A = udg_NoisePermutation[X] + Y
set B = udg_NoisePermutation[X + 1] + Y
set lerpA1 = Lerp(u, Gradient2D(udg_NoisePermutation[A], x, y), Gradient2D(udg_NoisePermutation[B], x - 1., y))
set lerpA2 = Lerp(u, Gradient2D(udg_NoisePermutation[A + 1], x, y - 1.), Gradient2D(udg_NoisePermutation[B + 1], x - 1., y - 1.))
return Lerp(v, lerpA1, lerpA2)
endfunction
function Gradient3D takes integer hash, real x, real y, real z returns real
local integer h = BlzBitAnd(hash, 15)
local real u = RealTernaryOp(h < 8, x, y)
local real v = RealTernaryOp(h < 4, y, RealTernaryOp(h == 12 or h == 14, x, z))
return RealTernaryOp(BlzBitAnd(h, 1) == 0, u, -u) + RealTernaryOp(BlzBitAnd(h, 2) == 0, v, -v)
endfunction
function PerlinNoise3D takes real x, real y, real z returns real
local integer X = BlzBitAnd(Floor(x), 255)
local integer Y = BlzBitAnd(Floor(y), 255)
local integer Z = BlzBitAnd(Floor(z), 255)
local real u
local real v
local real w
local integer A
local integer AA
local integer AB
local integer B
local integer BA
local integer BB
local real lerpA1
local real lerpA2
local real lerpB1
local real lerpB2
set x = x - Floor(x)
set y = y - Floor(y)
set z = z - Floor(z)
set u = Fade(x)
set v = Fade(y)
set w = Fade(z)
set A = udg_NoisePermutation[X] + Y
set AA = udg_NoisePermutation[A] + Z
set AB = udg_NoisePermutation[A + 1] + Z
set B = udg_NoisePermutation[X + 1] + Y
set BA = udg_NoisePermutation[B] + Z
set BB = udg_NoisePermutation[B + 1] + Z
set lerpA1 = Lerp(u, Gradient3D(udg_NoisePermutation[AA], x, y, z), Gradient3D(udg_NoisePermutation[BA], x - 1., y, z))
set lerpA2 = Lerp(u, Gradient3D(udg_NoisePermutation[AB], x, y - 1., z), Gradient3D(udg_NoisePermutation[BB], x - 1., y - 1., z))
set lerpB1 = Lerp(u, Gradient3D(udg_NoisePermutation[AA + 1], x, y, z - 1.), Gradient3D(udg_NoisePermutation[BA + 1], x - 1., y, z - 1.))
set lerpB2 = Lerp(u, Gradient3D(udg_NoisePermutation[AB + 1], x, y - 1., z - 1.), Gradient3D(udg_NoisePermutation[BB + 1], x - 1., y - 1., z - 1.))
return Lerp(w, Lerp(v, lerpA1, lerpA2), Lerp(v, lerpB1, lerpB2))
endfunction
Code: Select all
/*
Perlin Noise vJASS 1.0.0
Port by Glint
Perlin Noise by Kenneth Perlin, https://mrl.nyu.edu/~perlin/noise/
*/
library Noise
private module Init
private static method onInit takes nothing returns nothing
call permutationInit()
endmethod
endmodule
struct Noise extends array
readonly static string version = "1.0.0"
static integer array permutation
implement Init
private static method floor takes real value returns integer
local integer n = R2I(value)
if value < 0. and value - n != 0. then
set n = n - 1
endif
return n
endmethod
private static method realTernaryOp takes boolean cond, real a, real b returns real
if cond then
return a
else
return b
endif
endmethod
private static method fade takes real t returns real
return t * t * t * (t * (t * 6. - 15.) + 10.)
endmethod
private static method lerp takes real t, real a, real b returns real
return a + t * (b -a)
endmethod
private static method grad1D takes integer hash, real x returns real
local integer h = BlzBitAnd(hash, 15)
return realTernaryOp(BlzBitAnd(h, 1) == 0, x, -x)
endmethod
static method perlin1D takes real x returns real
local integer X = BlzBitAnd(floor(x), 255)
set x = x - floor(x)
return lerp(fade(x), grad1D(permutation[X], x), grad1D(permutation[X + 1], x - 1.)) * 2
endmethod
private static method grad2D takes integer hash, real x, real y returns real
local integer h = BlzBitAnd(hash, 15)
local real u = realTernaryOp(h < 8, x, y)
local real v = realTernaryOp(h < 4, y, x)
return realTernaryOp(BlzBitAnd(h, 1) == 0, u, -u) + realTernaryOp(BlzBitAnd(h, 2) == 0, v, -v)
endmethod
static method perlin2D takes real x, real y returns real
local integer X = BlzBitAnd(floor(x), 255)
local integer Y = BlzBitAnd(floor(y), 255)
local real u
local real v
local integer A
local integer B
local real lerpA1
local real lerpA2
set x = x - floor(x)
set y = y - floor(y)
set u = fade(x)
set v = fade(y)
set A = permutation[X] + Y
set B = permutation[X + 1] + Y
set lerpA1 = lerp(u, grad2D(permutation[A], x, y), grad2D(permutation[B], x - 1., y))
set lerpA2 = lerp(u, grad2D(permutation[A + 1], x, y - 1.), grad2D(permutation[B + 1], x - 1., y - 1.))
return lerp(v, lerpA1, lerpA2)
endmethod
private static method grad3D takes integer hash, real x, real y, real z returns real
local integer h = BlzBitAnd(hash, 15)
local real u = realTernaryOp(h < 8, x, y)
local real v = realTernaryOp(h < 4, y, realTernaryOp(h == 12 or h == 14, x, z))
return realTernaryOp(BlzBitAnd(h, 1) == 0, u, -u) + realTernaryOp(BlzBitAnd(h, 2) == 0, v, -v)
endmethod
static method perlin3D takes real x, real y, real z returns real
local integer X = BlzBitAnd(floor(x), 255)
local integer Y = BlzBitAnd(floor(y), 255)
local integer Z = BlzBitAnd(floor(z), 255)
local real u
local real v
local real w
local integer A
local integer AA
local integer AB
local integer B
local integer BA
local integer BB
local real lerpA1
local real lerpA2
local real lerpB1
local real lerpB2
set x = x - floor(x)
set y = y - floor(y)
set z = z - floor(z)
set u = fade(x)
set v = fade(y)
set w = fade(z)
set A = permutation[X] + Y
set AA = permutation[A] + Z
set AB = permutation[A + 1] + Z
set B = permutation[X + 1] + Y
set BA = permutation[B] + Z
set BB = permutation[B + 1] + Z
set lerpA1 = lerp(u, grad3D(permutation[AA], x, y, z), grad3D(permutation[BA], x - 1., y, z))
set lerpA2 = lerp(u, grad3D(permutation[AB], x, y - 1., z), grad3D(permutation[BB], x - 1., y - 1., z))
set lerpB1 = lerp(u, grad3D(permutation[AA + 1], x, y, z - 1.), grad3D(permutation[BA + 1], x - 1., y, z - 1.))
set lerpB2 = lerp(u, grad3D(permutation[AB + 1], x, y - 1., z - 1.), grad3D(permutation[BB + 1], x - 1., y - 1., z - 1.))
return lerp(w, lerp(v, lerpA1, lerpA2), lerp(v, lerpB1, lerpB2))
endmethod
static method permutationInit takes nothing returns nothing
local integer i = 0
loop
exitwhen i > 255
set permutation[i] = GetRandomInt(0, 255)
set permutation[i + 256] = permutation[i]
set i = i + 1
endloop
endmethod
endstruct
endlibrary
Code: Select all
--[[
Perlin Noise Lua v1.0.1
Port by Glint
Perlin Noise by Kenneth Perlin, https://mrl.nyu.edu/~perlin/noise/
]]--
do
Noise = {}
Noise.version = "1.0.1"
Noise.permutation = {}
local function floor(value)
local n = R2I(value)
if value < 0. and value - n ~= 0. then n = n - 1 end
return n
end
local function fade(t)
return t * t * t * (t * (t * 6. - 15.) + 10.)
end
local function lerp(t, a, b)
return a + t * (b -a)
end
local function grad1D(hash, x)
local h = BlzBitAnd(hash, 15)
return (BlzBitAnd(h, 1) == 0 and x or -x)
end
function Noise.perlin1D (x)
local X = BlzBitAnd(floor(x), 255)
x = x - floor(x)
return lerp(fade(x), grad1D(Noise.permutation[X], x), grad1D(Noise.permutation[X + 1], x - 1)) * 2
end
local function grad2D(hash, x, y)
local h = BlzBitAnd(hash, 15)
local u, v = h < 8 and x or y, h < 4 and y or x
return (BlzBitAnd(h, 1) == 0 and u or -u) + (BlzBitAnd(h, 2) == 0 and v or -v)
end
function Noise.perlin2D (x, y)
local X, Y = BlzBitAnd(floor(x), 255), BlzBitAnd(floor(y), 255)
x, y = x - floor(x), y - floor(y)
local u, v = fade(x), fade(y)
local A = Noise.permutation[X] + Y
local B = Noise.permutation[X + 1] + Y
local a1 = lerp(u, grad2D(Noise.permutation[A], x, y), grad2D(Noise.permutation[B], x - 1, y))
local a2 = lerp(u, grad2D(Noise.permutation[A + 1], x, y - 1), grad2D(Noise.permutation[B + 1], x - 1, y - 1))
return lerp(v, a1, a2)
end
local function grad3D(hash, x, y, z)
local h = BlzBitAnd(hash, 15)
local u, v = h < 8 and x or y, h < 4 and y or ((h == 12 or h == 14) and x or z)
return (BlzBitAnd(h, 1) == 0 and u or -u) + (BlzBitAnd(h, 2) == 0 and v or -v)
end
function Noise.perlin3D (x, y, z)
local X, Y, Z = BlzBitAnd(floor(x), 255), BlzBitAnd(floor(y), 255), BlzBitAnd(floor(z), 255)
x, y, z = x - floor(x), y - floor(y), z - floor(z)
local u, v, w = fade(x), fade(y), fade(z)
local A = Noise.permutation[X] + Y
local AA = Noise.permutation[A] + Z
local AB = Noise.permutation[A + 1] + Z
local B = Noise.permutation[X + 1] + Y
local BA = Noise.permutation[B] + Z
local BB = Noise.permutation[B + 1] + Z
local a1 = lerp(u, grad3D(Noise.permutation[AA], x, y, z), grad3D(Noise.permutation[BA], x - 1, y, z))
local a2 = lerp(u, grad3D(Noise.permutation[AB], x, y - 1, z), grad3D(Noise.permutation[BB], x - 1, y - 1, z))
local b1 = lerp(u, grad3D(Noise.permutation[AA + 1], x, y, z - 1), grad3D(Noise.permutation[BA + 1], x - 1, y, z - 1))
local b2 = lerp(u, grad3D(Noise.permutation[AB + 1], x, y - 1, z - 1), grad3D(Noise.permutation[BB + 1], x - 1, y - 1, z - 1))
return lerp(w, lerp(v, a1, a2), lerp(v, b1, b2))
end
function Noise.permutationInit ()
for i = 0, 255 do
Noise.permutation[i] = GetRandomInt(0, 255)
Noise.permutation[i + 256] = Noise.permutation[i]
end
end
end
Code: Select all
/*
Perlin Noise Wurst v1.0.1
Port by Glint
Perlin Noise by Kenneth Perlin, https://mrl.nyu.edu/~perlin/noise/
*/
package Noise
import NoWurst
import Integer
import Vectors
function grad(int hash, real x) returns real
var h = hash.bitAnd(15)
return h.bitAnd(1) == 0 ? x : -x
function grad(int hash, vec2 vec) returns real
var h = hash.bitAnd(15)
let u = h < 8 ? vec.x : vec.y
let v = h < 4 ? vec.y : vec.x
return (h.bitAnd(1) == 0 ? u: -u) + (h.bitAnd(2) == 0 ? v : -v)
function grad(int hash, vec3 vec) returns real
let h = hash.bitAnd(15)
let u = h < 8 ? vec.x : vec.y
let v = h < 4 ? vec.y : (h == 12 or h == 14 ? vec.x : vec.z)
return (h.bitAnd(1) == 0 ? u : -u) + (h.bitAnd(2) == 0 ? v : -v)
function real.fade () returns real
return this * this * this * (this * (this * 6. - 15.) + 10.)
public class Noise
static int array p
static function perlin (real x) returns real
var lx = x
let X = lx.floor().bitAnd(255)
lx -= lx.floor()
return grad(p[X], lx).lerp(
grad(p[X + 1], lx - 1), lx.fade()) * 2
static function perlin (vec2 vec) returns real
var lvec = vec
let X = lvec.x.floor().bitAnd(255)
let Y = lvec.y.floor().bitAnd(255)
lvec = vec2(lvec.x - lvec.x.floor(), lvec.y - lvec.y.floor())
let u = lvec.x.fade()
let v = lvec.y.fade()
let A = p[X] + Y
let B = p[X + 1] + Y
return grad(p[A], lvec).lerp(
grad(p[B], lvec - vec2(1, 0)), u).lerp(
grad(p[A + 1], lvec - vec2(0, 1)).lerp(
grad(p[B + 1], lvec - vec2(1, 1)), u), v)
static function perlin (vec3 vec) returns real
var lvec = vec
let X = vec.x.floor().bitAnd(255)
let Y = vec.y.floor().bitAnd(255)
let Z = vec.z.floor().bitAnd(255)
lvec = vec3(lvec.x - lvec.x.floor(), lvec.y - lvec.y.floor(), lvec.z - lvec.z.floor())
let u = lvec.x.fade()
let v = lvec.y.fade()
let w = lvec.z.fade()
let A = p[X] + Y
let AA = p[A] + Z
let AB = p[A + 1] + Z
let B = p[X + 1] + Y
let BA = p[B] + Z
let BB = p[B + 1] + Z
return grad(p[AA], lvec).lerp(
grad(p[BA], lvec - vec3(1, 0, 0)), u).lerp(
grad(p[AB], lvec - vec3(0, 1, 0)).lerp(
grad(p[BB], lvec - vec3(1, 1, 0)), u), v).lerp(
grad(p[AA + 1], lvec - vec3(0, 0, 1)).lerp(
grad(p[BA + 1], lvec - vec3(1, 0, 1)), u).lerp(
grad(p[AB + 1], lvec - vec3(0, 1, 1)).lerp(
grad(p[BB + 1], lvec - vec3(1, 1, 1)), u), v), w)
static function generateRandomPermutation()
for i = 0 to 255
p[i] = GetRandomInt(0, 255)
p[i + 256] = p [i]
Code: Select all
function GetResult takes nothing returns nothing
local real x = (udg_Offset_X + udg_World_Offset_X + I2R(udg_X)) * udg_Scale
local real y = (udg_Offset_Y + udg_World_Offset_Y + I2R(udg_Y)) * udg_Scale
if udg_IsOctavePerlin then
set udg_Result = OctavePerlin2D(x, y,udg_Octaves, udg_Persistence)
else
set udg_Result = PerlinNoise2D(x, y)
endif
set x = udg_World_Offset_X + udg_X * udg_PerSquare_Width
set y = udg_World_Offset_Y + -(udg_Y * udg_PerSquare_Height)
if udg_Result < .1 then
call SetTerrainType(x, y, 'Ldrt', 0, 1, 0)
elseif udg_Result < .2 then
call SetTerrainType(x, y, 'Ldro', 0, 1, 0)
elseif udg_Result < .25 then
call SetTerrainType(x, y, 'Lgrs', 0, 1, 0)
elseif udg_Result < .5 then
call SetTerrainType(x, y, 'Ldrg', 0, 1, 0)
else
call SetTerrainType(x, y, 'Lrok', 0, 1, 0)
endif
endfunction
JASS changelog
vJASS changelog
Lua changelog
Wurst changelog