Javascript 如何在HTML画布上渲染光线投射的墙纹理
我正在尝试建立一个光线投射引擎。我已经使用Javascript 如何在HTML画布上渲染光线投射的墙纹理,javascript,canvas,frame-rate,raycasting,Javascript,Canvas,Frame Rate,Raycasting,我正在尝试建立一个光线投射引擎。我已经使用ctx.fillRect()成功地逐列渲染了场景,如下所示 我为上面的渲染编写的代码: var scene = [];// this contains distance of wall from player for an perticular ray var points = [];// this contains point at which ray hits the wall /* i have a Raycaster class wh
ctx.fillRect()
成功地逐列渲染了场景,如下所示
我为上面的渲染编写的代码:
var scene = [];// this contains distance of wall from player for an perticular ray
var points = [];// this contains point at which ray hits the wall
/*
i have a Raycaster class which does all math required for ray casting and returns
an object which contains two arrays
1 > scene : array of numbers representing distance of wall from player.
2 > points : contains objects of type { x , y } representing point where ray hits the wall.
*/
var data = raycaster.cast(wall);
/*
raycaster : instance of Raycaster class ,
walls : array of boundries constains object of type { x1 , y1 , x2 , y2 } where
(x1,y1) represent start point ,
(x2,y2) represent end point.
*/
scene = data.scene;
var scene_width = 800;
var scene_height = 400;
var w = scene_width / scene.length;
for(var i=0;i<scene.length;++i){
var c = scene[i] == Infinity ? 500 : scene[i] ;
var s = map(c,0,500,255,0);// how dark/bright the wall should be
var h = map(c,0,500,scene_height,10); // relative height of wall (farther the smaller)
ctx.beginPath();
ctx.fillStyle = 'rgb('+s+','+s+','+s+')';
ctx.fillRect(i*w,200-h*0.5,w+1,h);
ctx.closePath();
}
但是ctx.drawImage()
方法将图像绘制为一个矩形,没有类似的3D效果
我不知道怎么做
我应该使用ctx.tranform()
?如果是,如何进行?如果没有,我该怎么办
我正在寻找使用2D光线投射产生伪3d效果的数学方法。
一些虚拟3d游戏是
我正试着建造一些类似的东西
谢谢:)贴图(或不贴图,视情况而定)纹理坐标的方式没有按预期工作 我正在寻找用于使用2D光线投射产生伪3d效果的数学 这本书有一个很好的章节,详细介绍了Doom如何执行纹理贴图。从条目: 厄运引擎将世界限制在垂直的墙壁和水平的地板/天花板上,相机只能绕垂直轴旋转。这意味着墙壁将沿垂直线保持恒定深度坐标,地板/天花板将沿水平线保持恒定深度。快速仿射映射可以沿着这些直线使用,因为它是正确的 “快速仿射贴图”只是纹理坐标的简单2D插值,对于您正在尝试的操作来说是合适的。厄运引擎的一个限制也是 Doom使用仿射纹理贴图渲染垂直和水平跨距,因此无法绘制斜楼板或斜墙 您的逻辑似乎不包含任何用于在各种坐标空间之间转换坐标的代码。您至少需要在给定的光线跟踪坐标和纹理坐标空间之间应用变换。这通常涉及矩阵数学,非常常见,也可以称为,如从一个空间/曲面投影点到另一个空间/曲面。使用仿射变换,可以避免使用矩阵而采用线性插值 适用于您的变量的坐标方程(见上文)可能如下所示:
u = (1 - a) * wallStart + a * wallEnd
where 0 <= *a* <= 1
在您的例子中,A_x
是墙在世界空间中的位置B_z
是焦距,焦距将为1
A_z
是使用光线跟踪计算的距离。结果是表示到viewspace的平移的x或y坐标
这些文档介绍了用于光线跟踪和变换坐标以渲染游戏的技术。即使您不熟悉C/ASM,代码也非常可读,这是了解更多感兴趣主题的好方法。为了阅读更多的内容,我建议在您选择的引擎中搜索“纹理贴图的坐标矩阵变换”之类的内容,或者搜索类似的内容。
该文件的一个特定区域是从ln 267开始的本节:
> ========================
> =
> = TransformTile
> =
> = Takes paramaters:
> = tx,ty : tile the object is centered in
> =
> = globals:
> = viewx,viewy : point of view
> = viewcos,viewsin : sin/cos of viewangle
> = scale : conversion from global value to screen value
> =
> = sets:
> = screenx,transx,transy,screenheight: projected edge location and size
> =
> = Returns true if the tile is withing getting distance
> =
关于“数学”的一本好书是——我强烈推荐给任何想要创造或提高这些技能的人
更新:
从本质上讲,您将把图像中的像素(点)映射到矩形墙砖上的点上,正如光线跟踪报告的那样
伪(ish)-代码:
var image=getImage(someImage);//得到你想要的图像。确保在绘图之前完成加载
var iWidth=image.width,iHeight=image.height;
变量sX=0,sY=0;//图像的左上角。使用雪碧片等时进行调整
对于(var i=0;ii)已使用ctx.fillRect()成功地逐列渲染场景,如下所示显示此代码(全部)“但ctx.drawImage()
将图像绘制为矩形,没有像Wolfenstein 3D那样的3D效果”,是的,与ctx.fillRect()相同
@Shubhamrind请包括问题中的所有代码,不要只向github添加链接。我们需要一个如所述的链接,希望这会有所帮助,我不知道如何渲染墙纹理您检查了wolfenstein 3d的渲染效果了吗?高斯分布只是2d顶级摄影机场景的一部分,仅用于控制“3d”生成图像正确部分的相机。啊,这很公平。尽管如此,我认为应用空间变换的需求仍然非常现实。我根据OP示例添加了一些代码,演示了如何使用drawImage
To determine which screen x-coordinate corresponds to a point at
A_x_,A_z_
multiply the point coordinates by:
B_x = A_x * B_z / A_z
where
B_x
is the screen x coordinate
A_x
is the model x coordinate
B_z
is the focal length—the axial distance from the camera center *to the image plane*
A_z
is the subject distance.
Because the camera is in 3D, the same works for the screen y-coordinate, substituting y for x in the above diagram and equation.
> ========================
> =
> = TransformTile
> =
> = Takes paramaters:
> = tx,ty : tile the object is centered in
> =
> = globals:
> = viewx,viewy : point of view
> = viewcos,viewsin : sin/cos of viewangle
> = scale : conversion from global value to screen value
> =
> = sets:
> = screenx,transx,transy,screenheight: projected edge location and size
> =
> = Returns true if the tile is withing getting distance
> =
var image = getImage(someImage); // get the image however you want. make sure it finishes loading before drawing
var iWidth = image.width, iHeight = image.height;
var sX = 0, sY = 0; // top-left corner of image. Adjust when using e.g., sprite sheets
for(var i=0;i<scene.length;++i){
var c = scene[i] == Infinity ? 500 : scene[i];
var s = map(c,0,500,255,0);// how dark/bright the wall should be
var h = map(c,0,500,scene_height,10); // relative height of wall (farther the smaller)
var wX = i*w, wY = 200 - h * 0.5;
var wWidth = w + 1, wHeight = h;
//... render the rectangle shape
/* we are using the same image, but we are scaling it to the size of the rectangle
and placing it at the same location as the wall.
*/
var u, v, uW, vH; // texture x- and y- values and sizes. compute these.
ctx.drawImage(image, sX, sY, iWidth, iHeight, u, v, uW, vH);
}