对Raycasting感兴趣的大多数人可能知道Lodev和Permadi教程:https://lodev.org/cgtutor/raycasting2.html
https://permadi.com/1996/05/ray-casting-tutorial-11/
一开始我实现了所谓的“垂直地板/天花板”的光线投射,它继续拖着一列一列的墙壁程序,它只是starst画地板的时候做了墙,那个优化的思想,但是算法本身非常非常慢。
所以我尝试了Lodevs的“水平地板/天花板”光线投射,它是巨大的差异和速度。一切都会好起来的,但是这个算法,尽管速度很快,却浪费了在整个屏幕上填充地板和天花板的性能,然后它就画出了墙壁。
我想优化这一功能,因此地板和ceiiling将绘制后,墙壁被画,只填补空白空间。
也许解决办法是在铸墙过程中记住空格,然后创建包含x,y弦的数组,所以在地板和细胞铸造过程中,我们已经知道在哪里画。你怎么认为。你知道更多的秘密,也许是一些提示,学习的来源,算法吗?提前谢谢..。
ps。我用鼠标环顾四周,所以地平线在变。
我正在Windows上进行开发,但我正在将我的代码移植到使用m68k 060/080 cpus的更快的Amigas上,在320x240x32或640x480x32中使用RTG。到目前为止我得到了不错的结果..。所以尽我所能去优化az。
下面是我的一些测试和进展..。
PC <-> AMIGA (WIN UAE)
https://www.youtube.com/watch?v=hcFBPfDYZig
AMIGA,V600 080/78 Mhz - 320x240x32无纹理(质量对不起)
发布于 2022-07-10 14:57:18
由于这个问题与任何语言无关,所以我从Javascript的角度回答。我也实现了所谓的“垂直地板/天花板”技术。但是,我不是用ctx.drawImage()绘制每个像素的像素,而是使用putImageData。
首先,我使用临时画布从要呈现的瓷砖中获取数据:
var tempCanvas = document.createElement('canvas');
var tempCtx = tempCanvas.getContext('2d');
tempCanvas.width = 64;
tempCanvas.height = 64;
var wallsSprite = new Image();
wallsSprite.onload = function () {
tempCtx.drawImage(wallsSprite, 0, 128, 64, 64, 0, 0, 64, 64);
floorData = tempCtx.getImageData(0, 0, 64, 64);
tempCtx.drawImage(wallsSprite, 0, 192, 64, 64, 0, 0, 64, 64);
ceilData = tempCtx.getImageData(0, 0, 64, 64);
}
wallsSprite.src = "./walls_2.png";我创建了一个空的imageData:
var floorSprite = this.ctx.createImageData(600, 400);然后我做了我的“垂直地板/天花板”的光线投射:
//we check if the wall reaches the bottom of the canvas
// this.wallToBorder = (400 - wallHeight) / 2;
if (this.wallToBorder > 0) {
// we calculate how many pixels we have from bottom of wall to border of canvas
var pixelsToBottom = Math.floor(this.wallToBorder);
//we calculate the distance between the first pixel at the bottom of the wall and the player eyes (canvas.height / 2)
var pixelRowHeight = 200 - pixelsToBottom;
// then we loop through every pixels until we reach the border of the canvas
for (let i = pixelRowHeight; i < 200; i += 1) {
// we calculate the straight distance between the player and the pixel
var directDistFloor = (this.screenDist * 200) / (Math.floor(i));
// we calculate it's real world distance with the angle relative to the player
var realDistance = (directDistFloor / Math.cos(this.angleR));
// we calculate it's real world coordinates with the player angle
this.floorPointx = this.player.x + Math.cos(this.angle) * realDistance / (this.screenDist / 100);
this.floorPointy = this.player.y + Math.sin(this.angle) * realDistance / (this.screenDist / 100);
// we map the texture
var textY = Math.floor(this.floorPointx % 64);
var textX = Math.floor(this.floorPointy % 64);
// we modify floorSprite array:
if (floorData && ceilData) {
floorSprite.data[(this.index * 4) + (i + 200) * 4 * 600] = floorData.data[textY * 4 * 64 + textX * 4]
floorSprite.data[(this.index * 4) + (i + 200) * 4 * 600 + 1] = floorData.data[textY * 4 * 64 + textX * 4 + 1]
floorSprite.data[(this.index * 4) + (i + 200) * 4 * 600 + 2] = floorData.data[textY * 4 * 64 + textX * 4 + 2]
floorSprite.data[(this.index * 4) + (i + 200) * 4 * 600 + 3] = 255;
floorSprite.data[(this.index * 4) + (200 - i) * 4 * 600] = ceilData.data[textY * 4 * 64 + textX * 4]
floorSprite.data[(this.index * 4) + (200 - i) * 4 * 600 + 1] = ceilData.data[textY * 4 * 64 + textX * 4 + 1]
floorSprite.data[(this.index * 4) + (200 - i) * 4 * 600 + 2] = ceilData.data[textY * 4 * 64 + textX * 4 + 2]
floorSprite.data[(this.index * 4) + (200 - i) * 4 * 600 + 3] = 255;
}
}
}
}
}最后,我们在绘制墙壁之前绘制地板和天花板:
this.ctx.putImageData(floorSprite, 0, 0);
结果非常快,因为:
wastes performance on filling up the whole screen with floor and ceiling, and after that it draws walls了。也许它可以通过混合horizontal raysting和putImageData来优化,把游戏速度与墙壁/天花板渲染或者没有是几乎相同的。
https://stackoverflow.com/questions/66670372
复制相似问题