Canvas中是否有类似于Mode7的透视变换?

15

我正在制作一个基于canvas的游戏引擎,想知道如何实现俯视视角。我需要的是传统鸟瞰图和旧版SNES mode7视图之间的中间状态,只需微小的倾斜角度就能营造出3D效果。

我试图弄清楚哪种方法最好来处理透视扭曲。我没有进行旋转操作,因此3D矩阵等内容可能过于复杂,但我需要以一致的角度渲染地图层,并且最好能够调整角度。我还需要处理深度扭曲。基本上,底部像素行应该是1:1的像素宽度和高度,而每一行都会变得比前一行小5%之类的。我希望能够提供一个大型的画布作为纹理,然后提供一个介于0和90之间的摄像机角度,其中0表示完全水平,而90表示鸟瞰图。

有人有相关教程或示例代码吗?我在网上搜索了一下,但找到的所有内容似乎要么不适用于这个特定应用程序,要么过于复杂,涉及各种疯狂的3D扭曲和旋转等复杂操作。我想做的只是把普通的平铺网格向后倾斜一点,没有旋转或复杂的操作。

以下是我想要的示例图; 这是一个示例。http://img801.imageshack.us/img801/2176/perspectivesample.jpg

底部像素行是1:1的像素比例,每一行之上的水平和垂直长度逐渐减小。顶部中心区域的源纹理通常只有底部中心区域的一半高度,但它已经被垂直和水平缩小以适应透视效果。

我认为最好的方法可能是将当前视口状态渲染到另一个平面、鸟瞰视图的画布中,并在顶部和侧面额外增加大约50%的空间,然后从其中切割出一个倒三角形区域,并将其绘制到实际可见的画布中。

唯一的问题是,当涉及到计算角度等数学问题时,我很菜。


1
你有在线上的图形示例吗?我只是想更明确地了解您想要什么。谢谢。 - Castrohenge
3
这很有趣:http://acko.net/blog/projective-texturing-with-canvas - Josh Lee
1
让我明确一下。您想围绕X轴旋转3D视图,并且您想使用2D API进行操作,而不使用“各种疯狂的3D扭曲和旋转技巧”?这怎么可能实现呢? - Stefan Monov
1
不,我不想进行旋转。我只想将矩形纹理倾斜,使其看起来具有透视效果,方法是使顶部像素行比底部像素行更窄。这本身并不太难想出,但它还需要能够处理未完全居中的纹理,通过使一侧的角度与另一侧不同来实现。这就是我需要帮助的地方...我不擅长矢量匹配。 >.> - Stephen Belanger
用正确的变换矩阵,context.setTransform(....),这不应该很容易吗? - oberhamsi
显示剩余3条评论
2个回答

7

如果我理解正确,您只需要一个简单的梯形变换。如果是这样,也许这个或者这个链接可以帮助您。对于那些没有居中的图像,只需要额外进行菱形变换,据我所知,这在canvas上很容易实现。


4
你所谈论的内容可以用任何3D api来简单地完成。但是,由于你决定使用2D画布,所以必须在2D世界中完成所有工作,这意味着需要使用矩形、旋转、缩放、扭曲等方法。如其他答案提到的那样,也称为仿射变换。
虽然你想要使用2D实现这个目标是可能的,但你必须按照2D函数的思路去考虑。
1.创建初始图像。 2.从原始图像的底部添加一个切片到画布的底部,略微向左偏移,使图像中心与当前画布中心对齐。 3.轻微增加整个图像的比例。 4.重复此过程,直到到达图像的顶部。
伪代码应该像这样...
imgA = document.getElementById('source');

// grab image slices from bottom to top of image
for (var ix=height-slice_height;ix>=0;ix-=slice_height)
{

    // move a section of the source image to the target canvas
    ctx.drawImage(imgA, 0,ix,width,slice_height, 
         0-half_slice_width_increase,width,slice_height);
    // stretch the whole canvas
    ctx.scale(scale_ratio, 1);
}

这需要大量的微调,但这是一般解决方案。

  • scale_ratio 将是一个略大于1的数字,但非常接近1。
  • ctx 是标准的canvas 2D上下文。
  • half_slice_width_increase 是画布按比例缩放时增加的1/2数量。这可以使缩放后的图像保持居中。

为了看起来正确,您需要在添加图标叠加之前先转换背景瓷砖。


正如我在评论中所说,我需要它能够处理那些不完全居中的图像。弄清楚你发布了什么很容易,但是我遇到的困难是对于那些不居中的图像进行补偿。 - Stephen Belanger
我想我表达不够清楚,但最初的图像将在一个平面2D画布对象上生成。那是源头。然后,您可以取出完成的2D图像的切片,并通过向底部添加一条线来倾斜它,逐渐进行非常轻微的增加并重复操作,直到顶部。之后,在倾斜的地图上添加精灵。如果我有时间的话,我会尝试制作一个可工作的演示文稿。 - Great Turtle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接