Back to blog
Aug 10, 2025
2 min read

Elden Ring Normal Texture Convert (Code)

A simple tool to convert Elden Ring’s normal map, then use it in Skyrim or other game engines.

This is the standalone version (.html). Or you can use it directly on my website: link

How to use? You can make a new .html file and copy the code, then open this .html with a browser.

HTML Code:

1
<!DOCTYPE html>
2
<html>
3
<head>
4
<title>Reconstruct Z from Normal Map</title>
5
</head>
6
<body>
7
<h2>Upload Elden Ring Packed Normal Map (.png)</h2>
8
<input type="file" id="upload" accept="image/*" />
9
<canvas id="canvas" style="display:none;"></canvas>
10
<a id="downloadLink" style="display:none;">Download Reconstructed Normal</a>
11
12
<script>
13
const upload = document.getElementById("upload");
14
const canvas = document.getElementById("canvas");
15
const ctx = canvas.getContext("2d");
16
const link = document.getElementById("downloadLink");
17
18
upload.addEventListener("change", async (e) => {
19
const file = e.target.files[0];
20
if (!file) return;
21
22
const img = new Image();
23
img.onload = () => {
24
canvas.width = img.width;
25
canvas.height = img.height;
26
ctx.drawImage(img, 0, 0);
27
const imgData = ctx.getImageData(0, 0, img.width, img.height);
28
const data = imgData.data;
29
30
for (let i = 0; i < data.length; i += 4) {
31
const r = data[i] / 255; // X
32
const g = data[i + 1] / 255; // Y
33
34
const x = r * 2.0 - 1.0;
35
const y = g * 2.0 - 1.0;
36
let z = Math.sqrt(Math.max(0.0, 1.0 - x * x - y * y));
37
38
// Convert back to 0-255
39
data[i] = Math.round((x + 1.0) * 0.5 * 255); // R = X
40
data[i + 1] = Math.round((y + 1.0) * 0.5 * 255); // G = Y
41
data[i + 2] = Math.round(z * 255); // B = Z
42
// Alpha stays the same or you can set to 255
43
}
44
45
ctx.putImageData(imgData, 0, 0);
46
47
// Provide download link
48
canvas.toBlob(blob => {
49
const url = URL.createObjectURL(blob);
50
link.href = url;
51
link.download = "reconstructed_normal.png";
52
link.textContent = "Download Reconstructed Normal Map";
53
link.style.display = "inline-block";
54
}, "image/png");
55
};
56
57
const reader = new FileReader();
58
reader.onload = () => {
59
img.src = reader.result;
60
};
61
reader.readAsDataURL(file);
62
});
63
</script>
64
</body>
65
</html>