With a little help from some community members and information here & here I've written a gimp plugin (in Python) which combines two normal maps in a mathematically "correct" fashion. The only issue I have with it is that it's a little slow, combining two 1024x1024 normal maps takes around 8.5 seconds on my PC (i5 760 @ stock clocks), combining two 4096x4096 maps takes ~136s.

The main loop is listed below:

Note: Clamp() is a function I found online.

Code: Select all

`for n in xrange(num_pixels):`

if(n % Update == 0):

gimp.progress_update(float(n) / float(num_pixels))

#Indices for slicing

start = n * pixel_size

end = start + pixel_size

basePixel = basePixels[start:end]

detailPixel = detailPixels[start:end]

destPixel = destPixels[start:end]

basePixel[0] = ((basePixel[0])-127.5)/127.5

basePixel[1] = ((basePixel[1])-127.5)/127.5

basePixel[2] = (basePixel[2])/127.5

detailPixel[0] = (127.5-(detailPixel[0]))/127.5

detailPixel[1] = (127.5-(detailPixel[1]))/127.5

detailPixel[2] = ((detailPixel[2])-127.5)/127.5

partialResult = ((basePixel[0]*detailPixel[0])+(basePixel[1]*detailPixel[1])+(basePixel[2]*detailPixel[2]))/basePixel[2]

destPixel[0] = int(clamp(127.5*(((basePixel[0]*partialResult)-detailPixel[0])+1),0,255))

destPixel[1] = int(clamp(127.5*(((basePixel[1]*partialResult)-detailPixel[1])+1),0,255))

destPixel[2] = int(clamp(127.5*(((basePixel[2]*partialResult)-detailPixel[2])+1),0,255))

destPixel[3] = 255

destPixels[start:end] = destPixel

EDIT: I just spotted a minor optimisation which has shaved off ~0.5s for the 1024x1024 case, giving a runtime of 8s. Code snippet updated