Fix voxel occlusion: only draw sides visible to camera

This commit is contained in:
Richard Zink committed 2026-10-06 17:12:51 +02:00
1 parent 273fcc2390
commit fb357e2934
1 file changed
+25 -33
+25 -33
View File
@@ -75,26 +75,27 @@
return ((a.x + a.y) - (b.x + b.y)); return ((a.x + a.y) - (b.x + b.y));
}); });
var heightMap = {};
for (var i = 0; i < tiles.length; i++) {
var t = tiles[i];
heightMap[t.x + ',' + t.y] = t.h;
}
for (var i = 0; i < tiles.length; i++) { for (var i = 0; i < tiles.length; i++) {
var t = tiles[i]; var t = tiles[i];
var wx = t.x, wy = t.y, h = t.h; var wx = t.x, wy = t.y, h = t.h;
var water = isWater(h); var water = isWater(h);
var hLeft = heightMap[(wx - TILE) + ',' + wy] || 0;
var hRight = heightMap[(wx + TILE) + ',' + wy] || 0;
var hFront = heightMap[wx + ',' + (wy - TILE)] || 0;
var hBack = heightMap[wx + ',' + (wy + TILE)] || 0;
var topColor = water ? '#2299dd' : '#33aa33'; var topColor = water ? '#2299dd' : '#33aa33';
var leftColor = water ? '#1166aa' : '#226622'; var leftColor = water ? '#1166aa' : '#226622';
var rightColor = water ? '#0d4477' : '#114411'; var rightColor = water ? '#0d4477' : '#114411';
if (h > 0) {
var lighting = 0.5 + Math.max(0, sinA * 0.3 + 0.2);
topColor = applyLighting(topColor, lighting);
leftColor = applyLighting(leftColor, lighting * 0.7);
rightColor = applyLighting(rightColor, lighting * 0.5);
} else if (water) {
topColor = '#2299dd';
leftColor = '#1166aa';
rightColor = '#0d4477';
}
var top1 = project(wx, wy + TILE, h * HEIGHT_UNIT); var top1 = project(wx, wy + TILE, h * HEIGHT_UNIT);
var top2 = project(wx + TILE, wy + TILE, h * HEIGHT_UNIT); var top2 = project(wx + TILE, wy + TILE, h * HEIGHT_UNIT);
var top3 = project(wx + TILE, wy, h * HEIGHT_UNIT); var top3 = project(wx + TILE, wy, h * HEIGHT_UNIT);
@@ -109,35 +110,26 @@
ctx.closePath(); ctx.closePath();
ctx.fill(); ctx.fill();
if (h !== 0 || water) { if (hLeft < h) {
var bot1 = project(wx, wy + TILE, 0);
var bot2 = project(wx + TILE, wy + TILE, 0);
var bot3 = project(wx + TILE, wy, 0);
var bot4 = project(wx, wy, 0);
ctx.fillStyle = leftColor; ctx.fillStyle = leftColor;
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(bot4[0], bot4[1]); ctx.moveTo(top4[0], top4[1]);
ctx.lineTo(top4[0], top4[1]);
ctx.lineTo(top1[0], top1[1]); ctx.lineTo(top1[0], top1[1]);
ctx.lineTo(bot1[0], bot1[1]); ctx.lineTo(top1[0], top1[1] + (h - hLeft) * HEIGHT_UNIT);
ctx.closePath(); ctx.lineTo(top4[0], top4[1] + (h - hLeft) * HEIGHT_UNIT);
ctx.fill();
ctx.fillStyle = rightColor;
ctx.beginPath();
ctx.moveTo(bot3[0], bot3[1]);
ctx.lineTo(top3[0], top3[1]);
ctx.lineTo(top4[0], top4[1]);
ctx.lineTo(bot4[0], bot4[1]);
ctx.closePath(); ctx.closePath();
ctx.fill(); ctx.fill();
} }
if (h > 0) { if (hBack < h) {
ctx.strokeStyle = 'rgba(0, 0, 0, 0.4)'; ctx.fillStyle = rightColor;
ctx.lineWidth = 1; ctx.beginPath();
ctx.strokeRect(top1[0], top1[1], top3[0] - top1[0], top3[1] - top1[1]); ctx.moveTo(top3[0], top3[1]);
ctx.lineTo(top4[0], top4[1]);
ctx.lineTo(top4[0], top4[1] + (h - hBack) * HEIGHT_UNIT);
ctx.lineTo(top3[0], top3[1] + (h - hBack) * HEIGHT_UNIT);
ctx.closePath();
ctx.fill();
} }
} }
} }