画布中类似Mode7的透视变换?

发布于 2024-09-25 19:26:01 字数 807 浏览 6 评论 0原文

我正在制作一个基于画布的游戏引擎,想知道是否有人有任何关于如何实现俯视视角的好信息。我正在寻找介于传统鸟瞰图和旧 SNES mode7 视图之间的某个位置。只需一个微小的角度即可产生 3D 幻觉。

我正在尝试找出解决视角倾斜的最佳方法。我不做旋转,所以 3D 矩阵的东西会太过分,但我需要能够以一致的角度渲染地图图层,如果角度是可调的那就太好了。我还需要处理深度扭曲。基本上,底部行像素的宽度和高度应该是 1:1,然后对于每一行,它会变小 5% 或类似的值。我想要的是能够提供一个大画布作为纹理,然后提供 0 到 90 之间的相机角度,其中 0 是完全水平的,90 是鸟瞰图。

谁有相关的教程或者示例代码吗?我在网上搜索了一下,但我发现的所有内容似乎要么不适合在这个特定的应用程序中使用,要么过于复杂,执行各种疯狂的 3D 倾斜和旋转操作。我想要的只是采用正常的平铺网格并将其向后倾斜一点,没有旋转或类似的复杂内容。

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

底部像素行的像素比为 1:1,上面的每一行在水平和垂直方向上逐渐变短。顶部中心区域的源纹理通常约为底部中心区域高度的一半,但它已垂直和水平缩小以适应透视。

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

唯一的问题是,在计算角度等方面,我的数学很糟糕。

I'm making a canvas-based game engine and am wondering if anyone has any good info on how to achieve an overhead view perspective. What I'm looking for is somewhere halfway between the traditional birds eye view and the old SNES mode7 view. Just a slight angle to give the illusion of 3D.

I'm trying to figure out what is going to be the best way to deal with the perspective skewing. I'm not doing rotations so 3D matrix stuff would be going overboard, but I need to be able to deal with rendering the map layers at a consistent angle and it'd be nice if the angle was adjustable. I also need to deal with the depth warp. Basically, the bottom row of pixels should be 1:1 pixel width and height, then for each row it'd get, for example, 5% smaller or something like that. What I'd like is to be able to supply a large canvas as a texture and then supply a camera angle between 0 and 90 where 0 is perfectly horizontal and 90 is birds eye view.

Anyone have any related tutorials or sample code? I've searched online a bit, but everything I've found seems to either be unsuitable for use in this particular application or overly complex, doing all sorts of crazy 3D skewing and rotation stuff. All I want is to take the normal tiled grid and lean it back a bit, no rotations or complicated stuff like that.

Here's an example of what I want;
Here's an example. http://img801.imageshack.us/img801/2176/perspectivesample.jpg

The bottom pixel row is 1:1 pixel ratio, and each row above that progressively gets shorter horizontally and vertically. The source texture of the top center region is normally about half the height of the bottom center region, but it has been shrunk vertically and horizontally to fit the perspective.

What I'm thinking might work best is to render the current viewport state to another canvas in flat, birds eye view, with approximately 50% extra space on the top and sides, then slice an upside triangular region from that and draw that to the actual visible canvas.

Only problem is, I suck at math when it comes to calculating angles and such.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

提赋 2024-10-02 19:26:01

如果我理解正确的话,你只想要一个简单的梯形变换。如果是这样,也许这个链接可以帮助您。对于不居中的图像,这只是一个额外的菱形变换,据我所知,这可以通过画布轻松实现。

if i understand you right, you just want a simple trapeze transformation. if so, maybe this or this link helps you out. for images that aren't centered it would just be an additional rhomboid tranformation, wich is easily possible with canvas, as far as i know.

蓝咒 2024-10-02 19:26:01

您所说的是可以使用任何 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。
  • ctx 是标准画布 2D 上下文
  • half_slice_width_increase 是数量的 1/2当按比例缩放时,画布会变大。这使缩放后的图像保持居中。

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

What you're talking about is something that can be done simply with any 3D api. However since you've decided to try to stick to 2D canvas, you have to do everything in the 2D world which means working with rectangles, rotation, scaling, skewing, etc. Also know as affine transformations as mentioned the other answer.

What you want to do is possible, but since you want to use 2D you have to think in terms of 2D functions.

  1. Generate your initial image.
  2. Add a slice from the bottom of the original image to the bottom of the canvas, very slightly positioned to the left so the center of the image matches up with the center of the current canvas.
  3. Very slightly increase the scale of the entire image
  4. Repeat until you get to the top of the image.

The Pseudo code would look like this...

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);
}

This will take lots of tweaking, but that is the general solution.

  • scale_ratio will be a number slightly larger, but very close to 1.
  • ctx is the standard canvas 2D context
  • half_slice_width_increase is the 1/2 the amount the canvas will grow when scaled by the scale ratio. This keeps the scaled image centered.

To look correct you would want to transform the background tiles first before you add the icon overlays.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文