-
Notifications
You must be signed in to change notification settings - Fork 4
/
quake-1-e1m1-light.html
94 lines (80 loc) · 4.32 KB
/
quake-1-e1m1-light.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="benchmark.css">
<title>Benchmark - Quake 1 (E1M1) with lighting - Retro n-gon renderer</title>
</head>
<body>
<script src="../../../distributable/rngon.cat.js"></script>
<script type="module">
import {benchmark} from "./benchmark.js";
import {scene} from "./assets/quake-1/e1m1.rngon-model.js";
(async()=>
{
await scene.initialize();
benchmark([Rngon.mesh(scene.ngons)],
{x:500, y:30, z:400},
{x:-20, y:197, z:0},
{
fov: 60,
nearPlane: 2,
farPlane: 5000,
scale: 0.2,
lights:
[
Rngon.light(Rngon.vector3(488, 177, 299)),
Rngon.light(Rngon.vector3(409, 115, 758)),
Rngon.light(Rngon.vector3(481, 182, 113)),
],
pixelShaderFunction: perpixel_light,
});
})();
function perpixel_light({renderWidth, renderHeight, pixelBuffer, fragmentBuffer, ngonCache})
{
const lightDirection = Rngon.vector3();
const surfaceNormal = Rngon.vector3();
for (let i = 0; i < (renderWidth * renderHeight); i++)
{
const thisFragment = fragmentBuffer[i];
const thisNgon = (ngonCache[thisFragment.ngonIdx] || null);
let strongestShade = 0;
for (let l = 0; l < Rngon.internalState.lights.length; l++)
{
const light = Rngon.internalState.lights[l];
/// Temp hack. Light objects don't yet support setting intensity etc.,
/// so we'll just manually assign those parameters based on the light
/// index.
let lightReach = 0;
let lightIntensity = 0;
switch (l)
{
case 0: case 2: lightReach = (300 * 300); lightIntensity = 3; break;
case 1: lightReach = (200 * 200); lightIntensity = 2; break;
}
const distance = (((thisFragment.worldX - light.position.x) * (thisFragment.worldX - light.position.x)) +
((thisFragment.worldY - light.position.y) * (thisFragment.worldY - light.position.y)) +
((thisFragment.worldZ - light.position.z) * (thisFragment.worldZ - light.position.z)));
const distanceMul = Math.max(0, Math.min(1, (1 - (distance / lightReach))));
if ((thisFragment.shade > 0) && (distanceMul > 0))
{
lightDirection.x = (light.position.x - thisFragment.worldX);
lightDirection.y = (light.position.y - thisFragment.worldY);
lightDirection.z = (light.position.z - thisFragment.worldZ);
Rngon.vector3.normalize(lightDirection);
surfaceNormal.x = thisFragment.normalX;
surfaceNormal.y = thisFragment.normalY;
surfaceNormal.z = thisFragment.normalZ;
const shadeMul = Math.max(0, Math.min(1, Rngon.vector3.dot(surfaceNormal, lightDirection)));
strongestShade = Math.max(strongestShade, (distanceMul * shadeMul * lightIntensity));
}
}
pixelBuffer[(i * 4) + 0] *= strongestShade;
pixelBuffer[(i * 4) + 1] *= strongestShade;
pixelBuffer[(i * 4) + 2] *= strongestShade;
}
}
</script>
</body>
</html>