Skip to content

Instantly share code, notes, and snippets.

@BalintCsala
Created June 19, 2025 16:22
Show Gist options
  • Save BalintCsala/87f8a77bf4f38ffed337ec02cbd55b17 to your computer and use it in GitHub Desktop.
Save BalintCsala/87f8a77bf4f38ffed337ec02cbd55b17 to your computer and use it in GitHub Desktop.
from PIL import Image
def load_normal_map(path):
img = Image.open(path).convert("RGB")
width, height = img.size
normals = []
for y in range(height):
row = []
for x in range(width):
r, g, b = img.getpixel((x, y))
nx = (r / 255.0) * 2.0 - 1.0
ny = (g / 255.0) * 2.0 - 1.0
nz = (b / 255.0) * 2.0 - 1.0
row.append((nx, ny, nz))
normals.append(row)
return normals, width, height
def save_heightmap(heights, output_path):
height = len(heights)
width = len(heights[0]) if height > 0 else 0
flat_values = [val for row in heights for val in row]
min_val = min(flat_values)
max_val = max(flat_values)
if max_val - min_val == 0:
normalized = [[128 for _ in range(width)] for _ in range(height)]
else:
normalized = [
[int((val - min_val) / (max_val - min_val) * 255) for val in row]
for row in heights
]
img = Image.new('L', (width, height))
for y in range(height):
for x in range(width):
img.putpixel((x, y), normalized[y][x])
img.save(output_path)
if __name__ == "__main__":
normals, width, height = load_normal_map("normals.png")
heights_x_first = [[0]]
# Fill up the first row
for x in range(1, width):
nx, ny, nz = normals[0][x]
x_slope = nx / nz
heights_x_first[0].append(heights_x_first[0][x - 1] + x_slope)
# Fill up the columns
for y in range(1, height):
row = []
for x in range(0, width):
nx, ny, nz = normals[y][x]
y_slope = ny / nz
row.append(heights_x_first[y - 1][x] + y_slope)
heights_x_first.append(row)
save_heightmap(heights_x_first, "height_x_first.png")
heights_y_first = [[0]]
# Fill up the first column
for y in range(1, height):
nx, ny, nz = normals[y][0]
y_slope = ny / nz
heights_y_first.append([heights_y_first[y - 1][0] + y_slope])
# Fill up the columns
for y in range(0, height):
for x in range(1, width):
nx, ny, nz = normals[y][x]
x_slope = nx / nz
heights_y_first[y].append(heights_y_first[y][x - 1] + x_slope)
save_heightmap(heights_y_first, "height_y_first.png")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment