首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >雷克斯特,寻找更有效的地板/天花板光线投射

雷克斯特,寻找更有效的地板/天花板光线投射
EN

Stack Overflow用户
提问于 2021-03-17 09:34:14
回答 1查看 746关注 0票数 0

对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无纹理(质量对不起)

EN

回答 1

Stack Overflow用户

发布于 2022-07-10 14:57:18

由于这个问题与任何语言无关,所以我从Javascript的角度回答。我也实现了所谓的“垂直地板/天花板”技术。但是,我不是用ctx.drawImage()绘制每个像素的像素,而是使用putImageData

首先,我使用临时画布从要呈现的瓷砖中获取数据:

代码语言:javascript
复制
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:

代码语言:javascript
复制
var floorSprite = this.ctx.createImageData(600, 400);

然后我做了我的“垂直地板/天花板”的光线投射:

代码语言:javascript
复制
 //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 raystingputImageData来优化,把游戏速度与墙壁/天花板渲染或者没有是几乎相同的。

这是结果

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66670372

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档