diff --git a/game/engines/default/engine/Entity.lua b/game/engines/default/engine/Entity.lua
index e6daf7f72377ba062f09b11d8d164f0609273f08..40a7701421c74e1592dc36a85da5eb25d5054dfc 100644
--- a/game/engines/default/engine/Entity.lua
+++ b/game/engines/default/engine/Entity.lua
@@ -278,24 +278,30 @@ function _M:makeMapObject(tiles, idx)
 
 	-- Texture 0 is always the normal image/ascii tile
 	-- we pcall it because some weird cases can not find a tile
-	local ok, tex, texx, texy, pos_x, pos_y = pcall(tiles.get, tiles, self.display, self.color_r, self.color_g, self.color_b, self.color_br, self.color_bg, self.color_bb, self.image, self._noalpha and 255, self.ascii_outline, true)
+	local ok, btex, btexx, btexy, bpos_x, bpos_y = pcall(tiles.get, tiles, self.display, self.color_r, self.color_g, self.color_b, self.color_br, self.color_bg, self.color_bb, self.image, self._noalpha and 255, self.ascii_outline, true)
 	if ok then
 		if self.anim then
-			self._mo:texture(0, tex, false, texx / self.anim.max, texy, pos_x, pos_y)
+			self._mo:texture(0, btex, false, btexx / self.anim.max, btexy, bpos_x, bpos_y)
 			self._mo:setAnim(0, self.anim.max, self.anim.speed or 1, self.anim.loop or -1)
 		else
-			self._mo:texture(0, tex, false, texx, texy, pos_x, pos_y)
+			self._mo:texture(0, btex, false, btexx, btexy, bpos_x, bpos_y)
 		end
 	end
 
 	-- Additional MO chained to the same Z order
 	if tiles.use_images and self.add_mos then
+		local tex, texx, texy, pos_x, pos_y
 		local cmo = self._mo
 		for i = 1, #self.add_mos do
 			local amo = self.add_mos[i]
 			-- Create a simple additional chained MO
 			local mo = core.map.newObject(self.uid, 1 + (tiles.use_images and amo.textures and #amo.textures or 0), false, false, false, amo.display_x or 0, amo.display_y or 0, amo.display_w or 1, amo.display_h or 1, amo.display_scale or 1)
-			tex, texx, texy, pos_x, pos_y = tiles:get("", 0, 0, 0, 0, 0, 0, amo.image, false, false, true)
+			if amo.image then
+				tex, texx, texy, pos_x, pos_y = tiles:get("", 0, 0, 0, 0, 0, 0, amo.image, false, false, true)
+			elseif amo.image_alter == "sdm" then
+				tex, texx, texy, pos_x, pos_y = btex:generateSDM()
+				texx, texy, pos_x, pos_y = btexx, btexy * 2, bpos_x, bpos_y
+			end
 			mo:texture(0, tex, false, texx, texy, pos_x, pos_y)
 			if amo.particle then
 				local args = amo.particle_args or {}
diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index f1f5d0eaa7d80c51c451f1c89798529338f6e919..abf493fe35a11974007d4510760143f48223c8c3 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -2889,7 +2889,7 @@ function _M:updateModdableTile()
 
 	if self.shader_auras and next(self.shader_auras) then
 		for _, def in pairs(self.shader_auras) do
-			add[#add+1] = {image = base.."base_distancemap_01.png", shader=def.shader, textures=def.textures, display_h=2, display_y=-1}
+			add[#add+1] = {image_alter="sdm", shader=def.shader, textures=def.textures, display_h=2, display_y=-1}
 		end
 	end
 
diff --git a/game/modules/tome/data/gfx/shaders/awesomeaura.frag b/game/modules/tome/data/gfx/shaders/awesomeaura.frag
index 1fc95481e9682dcb789290410790cae020e062a7..4b86c16308f5653fdf0f4bf1774e1147c32cf7d8 100644
--- a/game/modules/tome/data/gfx/shaders/awesomeaura.frag
+++ b/game/modules/tome/data/gfx/shaders/awesomeaura.frag
@@ -1,7 +1,169 @@
 uniform sampler2D tex;
 uniform sampler2D flames;
 
-void main(void)
+uniform float tick;
+uniform float time_factor;
+
+vec4 permute( vec4 x ) {
+
+	return mod( ( ( x * 34.0 ) + 1.0 ) * x, 289.0 );
+
+} 
+
+vec4 taylorInvSqrt( vec4 r ) {
+
+	return 1.79284291400159 - 0.85373472095314 * r;
+
+}
+
+float snoise( vec3 v ) {
+
+	const vec2 C = vec2( 1.0 / 6.0, 1.0 / 3.0 );
+	const vec4 D = vec4( 0.0, 0.5, 1.0, 2.0 );
+
+	// First corner
+
+	vec3 i  = floor( v + dot( v, C.yyy ) );
+	vec3 x0 = v - i + dot( i, C.xxx );
+
+	// Other corners
+
+	vec3 g = step( x0.yzx, x0.xyz );
+	vec3 l = 1.0 - g;
+	vec3 i1 = min( g.xyz, l.zxy );
+	vec3 i2 = max( g.xyz, l.zxy );
+
+	vec3 x1 = x0 - i1 + 1.0 * C.xxx;
+	vec3 x2 = x0 - i2 + 2.0 * C.xxx;
+	vec3 x3 = x0 - 1. + 3.0 * C.xxx;
+
+	// Permutations
+
+	i = mod( i, 289.0 );
+	vec4 p = permute( permute( permute(
+		i.z + vec4( 0.0, i1.z, i2.z, 1.0 ) )
+		+ i.y + vec4( 0.0, i1.y, i2.y, 1.0 ) )
+		+ i.x + vec4( 0.0, i1.x, i2.x, 1.0 ) );
+
+	// Gradients
+	// ( N*N points uniformly over a square, mapped onto an octahedron.)
+
+	float n_ = 1.0 / 7.0; // N=7
+
+	vec3 ns = n_ * D.wyz - D.xzx;
+
+	vec4 j = p - 49.0 * floor( p * ns.z *ns.z );  //  mod(p,N*N)
+
+	vec4 x_ = floor( j * ns.z );
+	vec4 y_ = floor( j - 7.0 * x_ );    // mod(j,N)
+
+	vec4 x = x_ *ns.x + ns.yyyy;
+	vec4 y = y_ *ns.x + ns.yyyy;
+	vec4 h = 1.0 - abs( x ) - abs( y );
+
+	vec4 b0 = vec4( x.xy, y.xy );
+	vec4 b1 = vec4( x.zw, y.zw );
+
+
+	vec4 s0 = floor( b0 ) * 2.0 + 1.0;
+	vec4 s1 = floor( b1 ) * 2.0 + 1.0;
+	vec4 sh = -step( h, vec4( 0.0 ) );
+
+	vec4 a0 = b0.xzyw + s0.xzyw * sh.xxyy;
+	vec4 a1 = b1.xzyw + s1.xzyw * sh.zzww;
+
+	vec3 p0 = vec3( a0.xy, h.x );
+	vec3 p1 = vec3( a0.zw, h.y );
+	vec3 p2 = vec3( a1.xy, h.z );
+	vec3 p3 = vec3( a1.zw, h.w );
+
+	// Normalise gradients
+
+	vec4 norm = taylorInvSqrt( vec4( dot( p0, p0 ), dot( p1, p1 ), dot( p2, p2 ), dot( p3, p3 ) ) );
+	p0 *= norm.x;
+	p1 *= norm.y;
+	p2 *= norm.z;
+	p3 *= norm.w;
+
+	// Mix final noise value
+
+	vec4 m = max( 0.6 - vec4( dot( x0, x0 ), dot( x1, x1 ), dot( x2, x2 ), dot( x3, x3 ) ), 0.0 );
+	m = m * m;
+	return 42.0 * dot( m*m, vec4( dot( p0, x0 ), dot( p1, x1 ),
+		dot( p2, x2 ), dot( p3, x3 ) ) );
+
+}  
+
+vec2 snoise2(vec3 pos)
 {
-	gl_FragColor = texture2D(tex, gl_TexCoord[0].xy) * texture2D(flames, gl_TexCoord[0].xy) + 0.2;
+	return vec2(snoise(pos), snoise(pos + vec3(0.0, 0.0, 1.0)));
 }
+
+float GetFireDelta(float currTime, vec2 pos, float freqMult, float stretchMult, float scrollSpeed, float evolutionSpeed)
+{
+	//firewall
+	float delta = 0.0;
+//	pos.y += (1.0 - pos.y) * 0.5;
+	//pos.y += 0.5;
+	pos.y /= stretchMult;
+	pos *= freqMult;
+	pos.y -= currTime * scrollSpeed;
+//	pos.y -= currTime * 3.0;
+
+	
+	delta += snoise(vec3(pos * 1.0, currTime * 1.0 * evolutionSpeed)) * 1.5;
+	delta += snoise(vec3(pos * 2.0, currTime * 2.0 * evolutionSpeed)) * 1.5;
+	delta += snoise(vec3(pos * 4.0, currTime * 4.0 * evolutionSpeed)) * 1.5;	
+	delta += snoise(vec3(pos * 8.0, currTime * 8.0 * evolutionSpeed)) * 1.5;
+	delta += snoise(vec3(pos * 16.0, currTime * 16.0 * evolutionSpeed)) * 0.5;
+
+	return delta;
+}
+
+vec4 GetFireAuraColor(float currTime, vec2 planarPos, float freqMult, float stretchMult, float ampMult, float power, float scrollSpeed, float paletteCoord)
+{		
+	float delta =  
+		GetFireDelta(currTime, planarPos + vec2(currTime * scrollSpeed * 0, 0.0), freqMult, stretchMult, 2.5, 0.5) * (1.0 - planarPos.x)	+ 
+		GetFireDelta(currTime, vec2(planarPos.x + currTime * scrollSpeed * 0.0 - 1.0, planarPos.y), freqMult, stretchMult, 2.5, 0.5) * planarPos.x;
+		
+	delta *= min(1.0, max(0.0, 1.0 * (1.0 - planarPos.y)));
+	delta *= min(1.0, max(0.0, 1.0 * (0.0 + planarPos.y)));
+
+	float verticalPos = 1.0 - planarPos.y + delta * ampMult;	
+	verticalPos = min(0.99, verticalPos);
+	verticalPos = max(0.01, verticalPos);
+	
+	return texture2D(flames, vec2(paletteCoord, verticalPos));
+}
+
+
+vec4 Uberblend(vec4 col0, vec4 col1)
+{
+//	return vec4((1.0 - col0.a) * (col1.rgb) + col0.a * (col1.rgb * col1.a + col0.rgb * (1.0 - col1.a)), min(1.0, col0.a + col1.a));
+//	return vec4((1.0 - col1.a) * (col0.rgb) + col1.a * (col1.rgb * col1.a + col0.rgb * (1.0 - col1.a)), min(1.0, col0.a + col1.a));
+	return vec4(
+		(1.0 - col0.a) * (1.0 - col1.a) * (col0.rgb * col0.a + col1.rgb * col1.a) / (col0.a + col1.a + 1e-1) +
+		(1.0 - col0.a) * (0.0 + col1.a) * (col1.rgb) +
+		(0.0 + col0.a) * (1.0 - col1.a) * (col0.rgb * (1.0 - col1.a) + col1.rgb * col1.a) +
+		(0.0 + col0.a) * (0.0 + col1.a) * (col1.rgb),
+		min(1.0, col0.a + col1.a));
+}
+
+
+void main(void)
+{
+	vec2 radius = gl_TexCoord[0].xy - vec2(0.5, 0.5);
+	float innerRadius = 0.25;
+	float outerRadius = 0.5;
+	
+	vec2 planarPos;
+	vec4 displacement = texture2D(tex, gl_TexCoord[0].xy);
+	planarPos.x = displacement.b;
+	planarPos.y = displacement.a * 3.0 * (1.0 + 10.0 * pow((planarPos.x) * (1.0 - planarPos.x) * 4.0, 1.0));
+	
+	vec4 resultColor = vec4(0.0, 0.0, 0.0, 0.0);
+		
+	resultColor = GetFireAuraColor(tick / time_factor, planarPos, 6.0, 15.0, 1.0, 1.0, 1.0, 0.75);//texture2D(tex, gl_TexCoord[0].xy) * texture2D(flames, gl_TexCoord[0].xy) + 0.2;
+	
+	gl_FragColor = resultColor;
+}
\ No newline at end of file
diff --git a/game/modules/tome/data/gfx/shaders/awesomeaura.lua b/game/modules/tome/data/gfx/shaders/awesomeaura.lua
index 2a8b63a0196c93ae75d76b8e9cfeb22f6fc76b54..a4f88bc942c9a63abaa8951e1fe518623b867784 100644
--- a/game/modules/tome/data/gfx/shaders/awesomeaura.lua
+++ b/game/modules/tome/data/gfx/shaders/awesomeaura.lua
@@ -23,6 +23,7 @@ return {
 	args = {
 		tex = { texture = 0 },
 		flames = { texture = 1 },
+		time_factor = time_factor or 4000,
 	},
 	clone = false,
 }
diff --git a/game/modules/tome/data/gfx/shockbolt/player/human_female/base_distancemap_01.png b/game/modules/tome/data/gfx/shockbolt/player/human_female/base_distancemap_01.png
index 9fc102a5a83b8f15f6eedbc0e813748880392bae..da5709d26fa7f6dd8561615e6eb883ceff96d0c2 100644
Binary files a/game/modules/tome/data/gfx/shockbolt/player/human_female/base_distancemap_01.png and b/game/modules/tome/data/gfx/shockbolt/player/human_female/base_distancemap_01.png differ
diff --git a/game/modules/tome/data/talents/spells/wildfire.lua b/game/modules/tome/data/talents/spells/wildfire.lua
index 99f54faa6d546de1a75726d54b8efa0a4ac0cb5a..3d66f573f7405bd82f75f84040cbff85be9379cf 100644
--- a/game/modules/tome/data/talents/spells/wildfire.lua
+++ b/game/modules/tome/data/talents/spells/wildfire.lua
@@ -77,7 +77,7 @@ newTalent{
 		game:playSoundNear(self, "talents/fire")
 		local cft = self:getTalentFromId(self.T_CLEANSING_FLAMES)
 		self.shader_auras = self.shader_auras or {}
-		self.shader_auras.burning_wake = {shader="awesomeaura", textures={{"image", "particles_images/flamesgeneric.png"}}}
+		self.shader_auras.burning_wake = {shader="awesomeaura", textures={{"image", "particles_images/flamesshockwave.png"}}}
 		self:updateModdableTile()
 		return {
 			bw = self:addTemporaryValue("burning_wake", t.getDamage(self, t)),
diff --git a/game/profile-thread/Client.lua b/game/profile-thread/Client.lua
index 742afa8b67e6f3c61dcb6407bd8788da1fcd8761..5f6ceaa69fac6495bc6dfd0e4021a4032e97df61 100644
--- a/game/profile-thread/Client.lua
+++ b/game/profile-thread/Client.lua
@@ -23,7 +23,7 @@ local UserChat = require "profile-thread.UserChat"
 
 module(..., package.seeall, class.make)
 
-local debug = true
+local debug = false
 
 local mport = debug and 2259 or 2257
 local pport = debug and 2260 or 2258
diff --git a/src/core_lua.c b/src/core_lua.c
index 44b6798ec82ec84a377fcb711c6d0b39f9a40b65..b8af189a682f2781f9ce4db4e1c374879d342d38 100644
--- a/src/core_lua.c
+++ b/src/core_lua.c
@@ -1196,6 +1196,198 @@ static int gl_texture_to_sdl(lua_State *L)
 	return 1;
 }
 
+typedef struct
+{
+	int x, y;
+} Vector;
+static inline float clamp(float val, float min, float max) { return val < min ? min : (val > max ? max : val); }
+static void build_sdm_ex(const unsigned char *texData, int srcWidth, int srcHeight, unsigned char *sdmTexData, int dstWidth, int dstHeight, int dstx, int dsty)
+{
+
+	int maxSize = dstWidth > dstHeight ? dstWidth : dstHeight;
+	int minSize = dstWidth < dstHeight ? dstWidth : dstHeight;
+
+	Vector *pixelStack = (Vector *)malloc(dstWidth * dstHeight * sizeof(Vector));
+	Vector *vectorMap = (Vector *)malloc(dstWidth * dstHeight * sizeof(Vector));
+	int *pixelStackIndex = (int *) malloc(dstWidth * dstHeight * sizeof(int));
+	
+	int currSize = 0;
+	int prevSize = 0;
+	int newSize = 0;
+
+	int x, y;
+	for(y = 0; y < dstHeight; y++)
+	{
+		for(x = 0; x < dstWidth; x++)
+		{
+			pixelStackIndex[x + y * dstWidth] = -1;
+			vectorMap[x + y * dstWidth].x = 0;
+			vectorMap[x + y * dstWidth].y = 0;
+
+			int srcx = dstx + x;
+			int srcy = dsty + y;
+			if(srcx < 0 || srcx >= srcWidth || srcy < 0 || srcy >= srcHeight) continue;
+
+			if(texData[(x + y * srcWidth) * 4 + 3] > 128)
+			{
+				pixelStackIndex[x + y * dstWidth] = currSize;
+				pixelStack[currSize].x = x;
+				pixelStack[currSize].y = y;
+				currSize++;
+			}
+		}
+	}
+	int dist = 0;
+	bool done = 0;
+	while(!done)
+	{
+		dist++;
+		int newSize = currSize;
+		int pixelIndex;
+		int neighbourNumber;
+		for(pixelIndex = prevSize; pixelIndex < currSize; pixelIndex++)
+		{
+			for(neighbourNumber = 0; neighbourNumber < 8; neighbourNumber++)
+			{
+				int xoffset = 0;
+				int yoffset = 0;
+				switch(neighbourNumber)
+				{
+					case 0: xoffset =  1; yoffset =  0; break;
+					case 1: xoffset =  0; yoffset =  1; break;
+					case 2: xoffset = -1; yoffset =  0; break;
+					case 3: xoffset =  0; yoffset = -1; break;
+					case 4: xoffset =  1; yoffset =  1; break;
+					case 5: xoffset = -1; yoffset =  1; break;
+					case 6: xoffset = -1; yoffset = -1; break;
+					case 7: xoffset =  1; yoffset = -1; break;
+				}
+				if(pixelStack[pixelIndex].x + xoffset >= dstWidth  || pixelStack[pixelIndex].x + xoffset < 0 ||
+					 pixelStack[pixelIndex].y + yoffset >= dstHeight || pixelStack[pixelIndex].y + yoffset < 0) continue;
+
+				int currIndex = pixelStack[pixelIndex].x + pixelStack[pixelIndex].y * dstWidth;
+				int neighbourIndex = (pixelStack[pixelIndex].x + xoffset) + (pixelStack[pixelIndex].y + yoffset) * dstWidth;
+				
+				Vector currOffset;
+				currOffset.x = vectorMap[currIndex].x + xoffset;
+				currOffset.y = vectorMap[currIndex].y + yoffset;
+				if(pixelStackIndex[neighbourIndex] == -1)
+				{
+					vectorMap[neighbourIndex] = currOffset;
+
+					pixelStackIndex[neighbourIndex] = newSize;
+
+					pixelStack[newSize].x = pixelStack[pixelIndex].x + xoffset;
+					pixelStack[newSize].y = pixelStack[pixelIndex].y + yoffset;
+					newSize++;
+				}else
+				{
+					if(vectorMap[neighbourIndex].x * vectorMap[neighbourIndex].x + vectorMap[neighbourIndex].y * vectorMap[neighbourIndex].y >
+						 currOffset.x * currOffset.x + currOffset.y * currOffset.y)
+					{
+						vectorMap[neighbourIndex] = currOffset;
+						/*float weight0 = sqrtf(vectorMap[neighbourIndex].x * vectorMap[neighbourIndex].x + vectorMap[neighbourIndex].y * vectorMap[neighbourIndex].y);
+						float weight1 = sqrtf(currOffset.x * currOffset.x + currOffset.y * currOffset.y);
+						vectorMap[neighbourIndex].x = vectorMap[neighbourIndex].x * weight1 / (weight0 + weight1) + currOffset.x * weight0 / (weight0 + weight1);
+						vectorMap[neighbourIndex].y = vectorMap[neighbourIndex].y * weight1 / (weight0 + weight1) + currOffset.y * weight0 / (weight0 + weight1);*/
+					}
+				}        
+			}
+		}
+		if(currSize == newSize)
+		{
+			done = 1;
+		}
+		prevSize = currSize;
+		currSize = newSize;
+	}
+
+	for(y = 0; y < dstHeight; y++)
+	{
+		for(x = 0; x < dstWidth; x++)
+		{
+			Vector offset = vectorMap[x + y * dstWidth];
+			float offsetLen = sqrtf((float)(offset.x * offset.x + offset.y * offset.y));
+
+			Vector currPoint;
+			currPoint.x = x;
+			currPoint.y = y;
+
+
+			Vector basePoint;
+			basePoint.x = currPoint.x - offset.x*0;
+			basePoint.y = currPoint.y - offset.y*0;
+
+			Vector centerPoint;
+			centerPoint.x = dstx + srcWidth  / 2;
+			centerPoint.y = dsty + srcHeight / 2;
+			float ang = atan2((float)(basePoint.x - centerPoint.x), -(float)(basePoint.y - centerPoint.y)); //0 is at up
+			//float ang = atan2((float)(offset.x), -(float)(offset.y));
+			sdmTexData[(x + y * dstWidth) * 4 + 0] = 127 + (float)(-vectorMap[x + y * dstWidth].x) / maxSize * 127;
+			sdmTexData[(x + y * dstWidth) * 4 + 1] = 127 + (float)(-vectorMap[x + y * dstWidth].y) / maxSize * 127;
+			sdmTexData[(x + y * dstWidth) * 4 + 2] = (unsigned char)(clamp(ang / 3.141592f * 0.5f + 0.5f, 0.0f, 1.0f) * 255);
+			sdmTexData[(x + y * dstWidth) * 4 + 3] = (unsigned char)(offsetLen / sqrtf(dstWidth * dstWidth + dstHeight * dstHeight) * 255);
+		}
+	}
+
+	/*for(y = 0; y < dstHeight; y++)
+	{
+		for(x = 0; x < dstWidth; x++)
+		{
+			int dstPointx = x + (sdmTexData[(x + y * dstWidth) * 4 + 0] / 255.0 - 0.5) * maxSize;
+			int dstPointy = y + (sdmTexData[(x + y * dstWidth) * 4 + 1] / 255.0 - 0.5) * maxSize;
+
+			float planarx = sdmTexData[(x + y * dstWidth) * 4 + 2] / 255.0;
+			float planary = sdmTexData[(x + y * dstWidth) * 4 + 3] / 255.0;
+			
+			char resultColor[4];
+			GetBackgroundColor(Vector2f(planarx, planary), 0.1f, resultColor);
+
+
+			for(int componentIndex = 0; componentIndex < 4; componentIndex++)
+			{
+				sdmTexData[(x + y * dstWidth) * 4 + componentIndex] = resultColor[componentIndex];
+			}
+		}
+	}*/
+	free(pixelStack);
+	free(vectorMap);
+	free(pixelStackIndex);
+}
+
+
+static int gl_texture_alter_sdm(lua_State *L) {
+	GLuint *t = (GLuint*)auxiliar_checkclass(L, "gl{texture}", 1);
+
+	// Bind the texture to read
+	tglBindTexture(GL_TEXTURE_2D, *t);
+
+	// Get texture size
+	GLint w, h;
+	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w);
+	glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &h);
+	GLubyte *tmp = calloc(w*h*4, sizeof(GLubyte));
+	glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, tmp);
+
+	GLubyte *sdm = calloc(w*h*2*4, sizeof(GLubyte));
+	build_sdm_ex(tmp, w, h, sdm, w, h * 2, 0, 0);
+
+	GLuint *st = (GLuint*)lua_newuserdata(L, sizeof(GLuint));
+	auxiliar_setclass(L, "gl{texture}", -1);
+
+	glGenTextures(1, st);
+	tfglBindTexture(GL_TEXTURE_2D, *st);
+	glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h * 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, sdm);
+
+	free(tmp);
+	free(sdm);
+
+	lua_pushnumber(L, w);
+	lua_pushnumber(L, h * 2);
+
+	return 3;
+}
+
 static int gl_tex_white = 0;
 int init_blank_surface()
 {
@@ -2685,6 +2877,7 @@ static const struct luaL_Reg sdl_texture_reg[] =
 	{"toScreenHighlightHex", sdl_texture_toscreen_highlight_hex},
 	{"makeOutline", sdl_texture_outline},
 	{"toSurface", gl_texture_to_sdl},
+	{"generateSDM", gl_texture_alter_sdm},
 	{"bind", sdl_texture_bind},
 	{NULL, NULL},
 };
diff --git a/src/map.c b/src/map.c
index 7f2efc8a2cb0cc371aa99a97cac8f4a335a0e477..103296514bfdb8aa5c5681d8a6ae43b8d0096d4d 100644
--- a/src/map.c
+++ b/src/map.c
@@ -415,7 +415,7 @@ static int map_objects_toscreen(lua_State *L)
 		map_object *dm;
 
 		int z;
-		if (allow_shader && m->shader) useShader(m->shader, 1, 1, 1, 1, 1, 1, 1, 1);
+		if (allow_shader && m->shader) useShader(m->shader, 0, 0, w, h, 1, 1, 1, a);
 		for (z = (!shaders_active) ? 0 : (m->nb_textures - 1); z >= 0; z--)
 		{
 			if (multitexture_active && shaders_active) tglActiveTexture(GL_TEXTURE0+z);
@@ -426,13 +426,24 @@ static int map_objects_toscreen(lua_State *L)
 		dm = m;
 		while (dm)
 		{
-			tglBindTexture(GL_TEXTURE_2D, dm->textures[0]);
-
 			int dx = x + dm->dx * w, dy = y + dm->dy * h;
 			float dw = w * dm->dw;
 			float dh = h * dm->dh;
 			int dz = moid;
 
+		 	if (m != dm && dm->shader) {
+				for (z = dm->nb_textures - 1; z > 0; z--)
+				{
+					if (multitexture_active) tglActiveTexture(GL_TEXTURE0+z);
+					tglBindTexture(dm->textures_is3d[z] ? GL_TEXTURE_3D : GL_TEXTURE_2D, dm->textures[z]);
+				}
+				if (dm->nb_textures && multitexture_active) tglActiveTexture(GL_TEXTURE0); // Switch back to default texture unit
+
+		 		useShader(dm->shader, 0, 0, w, h, 1, 1, 1, a);
+		 	}
+
+			tglBindTexture(GL_TEXTURE_2D, dm->textures[0]);
+
 			texcoords[0] = dm->tex_x[0]; texcoords[1] = dm->tex_y[0];
 			texcoords[2] = dm->tex_x[0] + dm->tex_factorx[0]; texcoords[3] = dm->tex_y[0];
 			texcoords[4] = dm->tex_x[0] + dm->tex_factorx[0]; texcoords[5] = dm->tex_y[0] + dm->tex_factory[0];
@@ -444,6 +455,11 @@ static int map_objects_toscreen(lua_State *L)
 			vertices[9] = dx; vertices[10] = dh + dy; vertices[11] = dz;
 			glDrawArrays(GL_QUADS, 0, 4);
 
+			if (m != dm) {
+		 		if (m->shader) useShader(m->shader, 0, 0, w, h, 1, 1, 1, a);
+		 		else glUseProgramObjectARB(0);
+		 	}
+
 			if (allow_cb && (dm->cb_ref != LUA_NOREF))
 			{
 				if (allow_shader && m->shader) glUseProgramObjectARB(0);
@@ -469,7 +485,7 @@ static int map_objects_toscreen(lua_State *L)
 				}
 				lua_pop(L, 1);
 
-				if (allow_shader && m->shader) useShader(m->shader, 1, 1, 1, 1, 1, 1, 1, 1);
+				if (allow_shader && m->shader) useShader(m->shader, 0, 0, w, h, 1, 1, 1, a);
 			}
 
 			dm = dm->next;
@@ -1480,7 +1496,7 @@ void display_map_quad(lua_State *L, GLuint *cur_tex, int *vert_idx, int *col_idx
 	dm = m;
 	while (dm)
 	{
-	 	if (dm->shader) {
+	 	if (m != dm && dm->shader) {
 			glDrawArrays(GL_QUADS, 0, (*vert_idx) / 2);
 			(*vert_idx) = 0;
 			(*col_idx) = 0;
@@ -1520,8 +1536,10 @@ void display_map_quad(lua_State *L, GLuint *cur_tex, int *vert_idx, int *col_idx
 			r, g, b, ((dm->dy < 0) && up_important) ? a / 3 : a,
 			(m->next || dm->shader) ? 1 : 0,
 			i, j);
-	 	if (m->shader) useShader(m->shader, dx, dy, map->tile_w, map->tile_h, r, g, b, a);
-	 	else glUseProgramObjectARB(0);
+		if (m != dm) {
+	 		if (m->shader) useShader(m->shader, dx, dy, map->tile_w, map->tile_h, r, g, b, a);
+	 		else glUseProgramObjectARB(0);
+	 	}
 		dm->animdx = animdx;
 		dm->animdy = animdy;
 		dm = dm->next;