OpenGL 3D纹理和在四边形的部分映射

3

我正在制作一个类似Minecraft的地形引擎,以学习一些OpenGL和3D知识,除了FPS我不太满意,其他都运行良好。

About 66 fps with 50k vertices/frame

当前情况:我目前只绘制可见面并使用视锥剔除,方块位于16x16x32的方块块中(现阶段)。

我为每个块使用6个显示列表,一个用于每个面(左、右、前、后、上、下),这样不会逐个绘制方块,而是一次性绘制整个块的一个面。

使用这种方法,我可以获得约20-100fps的帧率,这并不好。分析表明,我向图形卡发送了约100k个顶点,并且一旦我看向天空,顶点数降至10k以下,我的帧率就达到了200+fps,所以我想这就是我的瓶颈。

我想做什么:由于少即是多,我找到了这个链接:http://ogre3d.org/forums/viewtopic.php?f=2&t=60381&p=405688#p404631

据我所了解,Kojack使用巨大平面的3D网格,并从2D纹理图集中绘制纹理到这些巨大平面的特定位置。他说他使用一个256x256x256的3D纹理和绿色和蓝色通道来映射到2D纹理图集。
他的方法对于平面总计有一定数量的顶点,如果我的地图被应用,则有时是无用的,但仍然比我现在拥有的要少。 我的问题:我什么也没听懂:(,我想尝试他的方法,但我不明白他到底做了什么,主要是因为我缺乏对3D纹理的经验(我想象一个像素块)。他如何将纹理从纹理图集映射到平面的一部分,并使用某些3D纹理映射...
有人能解释一下Kojack做了什么或指向一些有帮助的地方吗,即使谷歌现在也没有任何帮助。

1
我不知道什么是着色器,所以我猜我没有使用它们,但我广泛使用glVertex3f,所以我想应该是固定功能。 - Solenoid
1
硬件配置:P4 3GHz 处理器,搭载 ATI Radeon X1600 显卡。Minecraft 至少以 200FPS 运行。 - Solenoid
1
是的,如果你没有使用着色器,Kojack的方法就不适用了。 - genpfault
1
用两个三角形,我得到了约650fps = 1.5ms/帧。我还测试了8个三角形(总是每个三角形的所有顶点都在屏幕上),得出类似的数据,因此对于低数量的三角形(带有纹理),大约需要1.5ms。 - Solenoid
1
从你的截图来看,我猜想你是在每个立方体面显示列表中进行单一纹理绑定?大概总共有6个吧? - genpfault
显示剩余6条评论
2个回答

4
这是对你问题的回答。首先,他将场景视为一个256 x 256 x 256个立方体的立方体。对于每个轴,他在每个轴值处渲染256个正方形(每个由两个三角形组成),每个正方形都与该轴值的整个立方体大小相同(即从0,0,0到0,256,256,然后从1,0,0到1,256,256,依此类推,直到256,0,0到256,256,256)。然后他以相反的法线方向做同样的事情,以总共512个正方形/1024个三角形来完成。该过程针对y和z重复进行,总共3072个三角形和3072个顶点(顶点仅出现在256 x 256 x 256立方体的边缘上)。
现在是纹理的部分。实际上,他正在绘制每个立方体,但通过使纹理在该位置透明来使一些立方体不可见。他有两个纹理,一个256 x 256 x 256的3D纹理和一个由较小纹理组成的16 x 16 纹理图集。为了绘制纹理,首先他使用他正在绘制的立方体的坐标作为3D纹理中的纹理坐标。因此,如果他正在绘制位置为42、7、13的立方体,则3D纹理坐标为42、7、13。在3D纹理内,他存储的只是对应于要绘制的纹理图集中子纹理的u、v坐标的绿色和蓝色值。因此,在他的例子中,3D纹理中的颜色为R = 0(未使用),G = 2,B = 4,A = 0(未使用)。他使用2和4作为u、v坐标,然后在纹理图集的位置2、4绘制纹理。由于纹理图集基本上只是一个巨大的纹理,对应于16 x 16(256)个较小的纹理,只绘制其中一个较小的纹理(在这种情况下,2和4将被除以16转换为纹理坐标,因此它们变成2/16 = 0.125和4/16 = 0.25。这些对应于图集中位置2、4的子纹理的0,0,该子纹理的1,1位于0.125 + 1/16和0.25 + 1/16。这些坐标用于给立方体贴上纹理。
如果他想挖出一个立方体,他只需要更改存储在该点处的3D纹理的值,使其指向图集中的透明子纹理。因此,如果纹理图集中的0,0是完全透明的子纹理,则可以将该位置处的3D纹理设置为R = 0(未使用),G = 0,B = 0,A = 0(未使用)。

谢谢,但那太理论化了。我不明白的是3D纹理:他将那个3D纹理的一部分映射到这3072个正方形中的每一个,从3D到2D,然后他使用某种特定纹理的着色器(我需要再读一些)。他如何只修改纹理的一部分?我找不到任何可以做到这一点的函数 - 还是它只适用于我不熟悉的3D纹理? - Solenoid
3D纹理仅用于查找。他将子立方体的位置视为3D纹理中的纹理坐标,从而获得颜色RGBA,其中他仅使用GB值作为2D纹理图集的查找。 - Jackson Pope

2
尝试将您的面部纹理放入纹理集中。每个面绑定一个纹理太多了。

1
谢谢,那就是瓶颈所在。现在我一直以大约100 FPS的速度运行。虽然不是非常出色,但比之前好多了。我还想尝试Kojack的方法。 - Solenoid

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