23. 另一种砖块墙面:纹理映射

23.Another Brick In The Wall: Texture Mapping

In our last post, we drew a 3D view of being in a maze-like grid of blocks. But all the walls were of single uniform colour, which is quite dull. The early 3D games that used our 3D technique, raycasting, almost immediately switched to using images for the walls rather than plain colours. These images were referred to as textures, and the technique for drawing them is known as texture mapping.

在我们上篇帖子里,我们绘制了一个迷宫网格中的3D场景。但是所有的墙壁都是单一颜色的,看起来很古板。在早期使用3D技术的3D游戏中,光线投射法几乎都是使用图像而不是单一的颜色来表示墙壁。这些图像被叫做纹理,绘制它们的技术被叫做纹理映射。

Texture mapping with raycasting is actually very simple. The idea is that each wall-block being drawn has an image on it. While drawing the wall-block pixel-by-pixel in 3D, texture mapping amounts to finding the corresponding pixel in the source image to use. We can label the face of each of the blocks in the world as having coordinates somewhere between (0, 0) and (1, 1):

基于光线投射法的纹理映射非常简单。原理是每个被绘制的墙壁方块上都有一个图像。3D场景中在逐个像素地绘制墙壁方块的同时,纹理映射要在源图像中找到对应的像素去使用。我们可以为世界中每个方块的表面用坐标来进行标记,其值在(0,0)和(1,1)之间。

The challenge is then for a given pixel, such as the red circle in the picture above, to find out which texture coordinates to use. These coordinates are typically labelled (u, v) to avoid confusion with other (x, y) coordinates. In raycasting, it’s quite easy to determine the (u, v). The u component is a matter of recording where exactly on the wall the ray hit. We already record the x and y coordinate of impact, and we know which face we hit. The u coordinate is just the fractional part of the appropriate x or y coordinate. If the ray hits the horizontal face of a block at (x, y) = 3.45, 6.00 then the u coordinate is 0.45.

挑战在于接下来对于给定的像素,如同在上图中红色括号所标示的,去找到哪些纹理坐标去使用。这些坐标可以典型性地标记为(u,v)以避免和其他(x,y)坐标相混淆。在光线投射法里,要确定(u,v)是非常容易的。u分量记录了光线触碰墙壁的确切位置。我们已经记录了碰触时的x和y坐标,同时我们知道碰触的是哪个表面。u坐标正好是恰当的x或y坐标值的小数部分。如果光线碰触到位于(x,y)=3.45,6.00方块的水平表面则u坐标值是0.45.

As for the v coordinate: that is the relative height within the block we are currently drawing. In each column, we already know how tall the block appears. So the v coordinate is just a proportion of that total block height as we draw downwards.

再看看v坐标:那是我们当前正在绘制方块内的相关高度。在每一列里,我们已经知道方块显示出来有多高。于是v坐标正好是我们往下绘制时整个方块高度的比率。

Once we know the (u, v) coordinates, we just pick out the appropriate pixel from our texture image. If our texture is 256 by 256, and our (u, v) = (0.45, 0.29), then we use the pixel at (115, 74). (This is called nearest-neighbour texture mapping, and is fastest, but it can look a bit “jagged”. Most games now use some form of linear texture mapping that looks smoother)

一旦我们知道(u,v)坐标值,我们只需要从纹理图像中取出合适的像素去绘制。如果我们的纹理大小是256乘256的,并且(u, v) = (0.45, 0.29),于是我们使用(115,74)处的像素。(这被称作最邻近纹理映射法,速度最快,但是看起来会有一些“锯齿”。现在大部分游戏使用一些线性纹理映射的方式以便看起来更平滑些)

Here’s the code:

代码如下:

 for (int wallY = 0; wallY <= 2 * height; wallY++)
 {
    double v = (double)wallY / (double)(2 * height);
    double u = r.getImageOffset();
                
    GreenfootImage texture = ((RaycastingWorld)getWorld()).getTextureFor(r.getX(), r.getY());
                
    Color c = texture.getColorAt((int)(u * (texture.getWidth() - 1)), (int)(v * (texture.getHeight() - 1)));
                
    int y = img.getHeight()/2 - height + wallY;
    if (y >= 0 && y < img.getHeight())
    {
        img.setColorAt((int)column, y, c);
    }
 }

Here’s the texture:

这儿是纹理:

And here’s a screenshot of what it looks like when used for texture-mapping:

这儿是使用纹理映射时的截屏效果:

You can play with the scenario yourself to see what it looks like as you turn round.

你可以自己玩一下游戏剧本去看看当你转向时看起来会是怎样的

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值