3

在对 Python 中的固定功能管道速度很慢感到沮丧之后,我开始研究着色器来绘制游戏的视差背景。但是,我找不到任何简单的方法来纹理绘制的顶点。

我目前有一个带有顶点数组的 PyOpenGL 顶点缓冲区对象,每个顶点都是这样的: [x, y, z, texX, texY, texID]

我使用 getAttribLocation/glEnableVertexAttribArray 将这些传递给着色器。我不确定它是否有效,因为着色器当前没有编译,但是在我添加我可能很糟糕的纹理代码之前,彩色顶点的工作一直正常。

我想要的是用着色器绘制一个纹理模型,具有多个纹理,但模型是平面背景。这是一个大的(1600x800 左右)图像,分为 256x256 纹理和四边形。(附带的问题:是有更多的小多边形更好,所以屏幕外的多边形更少,还是大多边形更好,所以纹理绑定更少?)

因为它是多个相关的纹理,所以我想在着色器中完成这一切,而不必为 CPU 上的每个块绑定纹理,所以我认为发送带有顶点数据的纹理数据是最好的,但我无法做到工作。

有人可以给我一个简单的例子,说明顶点和片段着色器相互作用以制作具有不同纹理的多个多边形吗?

编辑:着色器、vbo 和这里的东西:http://pastebin.com/3LaYiyvh着色器现在可以编译,但三角形是不可见的。

编辑:到了!不知道最后是什么破解了它,但这是程序: http: //pastebin.com/k87sfiEf 我认为这有点像,只要你在开始时绑定所有纹理,着色器就可以在它们之间交换。但我不确定。另外值得注意的是,将大背景分割成更小的块来绘制是个坏主意,因为在绘制时会交换纹理。浪费空间的大纹理很好,地图集更好!

4

3 回答 3

2

在对 Python 中的固定功能管道速度很慢感到沮丧之后,我开始研究着色器来绘制游戏的视差背景。

如果固定功能对您来说很慢,那么使用着色器不会使其更快。

可能你只是在做一些根本错误的事情,比如使用即时模式,或者根本没有硬件加速(由于缺乏正确安装的驱动程序或类似的东西)。

于 2012-03-03T01:31:04.743 回答
1

有人可以给我一个简单的例子,说明顶点和片段着色器相互作用以制作具有不同纹理的多个多边形吗?

谷歌获取 GLSL 教程。例子以前写过,没有理由只为你再写一次。或者下载 NVidia OpenGL SDK,并检查它。OpenGL.org 也推荐书籍。“橙皮书”涵盖了着色器。

分为 256x256

传统上建议做相反的事情 - 尽可能使用所有纹理并将它们组合成单个“图集”纹理,最好是 16384x16384 之类的 - 以最大限度地减少状态切换。

我想要的是用着色器绘制一个纹理模型,具有多个纹理,但模型是平面背景。这是一张大(1600x800 左右)图像

自 Riva TNT 2 pro 以来,1600x800 将完全适合几乎所有硬件的纹理。如果您关心“浪费”的纹理内存,那么许多卡都支持非 2 次幂纹理。但是,非 2 次方纹理通常有限制,并且在某些硬件(某些 ati 卡 + 驱动程序)上使用这种纹理会导致 fps 出现俯冲。即从 200..400 到 40。这是不值得的。在具有 256MB 虚拟内存的硬件上,未使用的 40% 纹理是微优化。再说一次,如果您对 vram 的使用感到吝啬,您可以使用纹理图集,并用有用的东西填充“浪费”的空间。另外,请记住,您永远不知道驱动程序使用视频内存的效率如何。

我想在着色器中完成这一切,而不必为 CPU 上的每个块绑定纹理,

你不能那样做。着色器不绑定纹理。他们使用已经绑定的纹理。

我不确定它是否有效,因为着色器当前没有编译,

好吧,让他们编译并再次询问。如果没有看到您的着色器或错误消息,就不可能为您提供帮助。您知道着色器编译器会产生错误消息,对吗?

在对 Python 中的固定功能管道很慢感到沮丧之后

考虑切换到编译语言,如 C 或 C++。您可以在 C/C++ 应用程序(“地牢爬行者”)中使用原始固定函数 opengl 轻松获得每秒 200..400 帧,而无需使用缓冲区或显示列表 -如果您使用正确的算法来去除隐藏表面(并且禁用 vsync)并且你的纹理是mip映射的。众所周知的“固定功能”应用程序包括 Quake 1..3、Half-Life 1、Cube 和许多其他速度极快的游戏。这意味着 - 如果它很慢,那是你的错。

与 C/C++ 不同,Python 具有更大的函数调用开销——执行字节码,从列表/元组中提取未知类型的值(可以包含“任何东西”),然后将其作为浮点数转储到 glVertex3f 之类的东西中,最后将其转发到本机API 调用将比没有中间步骤的类似 C/C++ 调用慢。您可以通过使用显示列表或缓冲区对象来抵消这种情况,但对我来说这不值得。但是,为特定任务使用特定语言是个人喜好问题。

- 编辑 -

但是,如果着色器无法绑定纹理,那么多重纹理如何工作?

有 N 个纹理阶段(至少 2 - se glGet/GL_MAX_TEXTURE_COORDS/GL_MAX_TEXTURE_UNITS),您一次设置多个纹理。见glActiveTexture如果没有着色器(固定功能),您可以使用glTexEnv为每个阶段指定颜色操作。使用着色器,您可以设置多个纹理,使用glUniform1i/glUniform1v指定哪个采样器使用哪个纹理阶段,然后使用 Sampler2D 和类似函数在着色器中从它们中读取数据。着色器无法切换​​纹理。它可以使用您的程序已经设置的纹理。着色器对着色器之外的任何纹理一无所知。从技术上讲,着色器甚至不知道“纹理”它具有用于读取数据的“采样器”。

还是纹理采样?着色器必须能够在选择/更改纹理方面做一些工作......

着色器根本不切换或选择纹理。这部分由您的程序完成。有关更多信息,请阅读您的 opengl/glsl 版本的 OpenGL 规范和 GLSL 规范。两者都可以从 opengl.org 网站的“文档”菜单下载。

正如我已经说过的,此时您需要 GLSL 教程或书籍。两者都很容易找到。获取其中任何一个并继续阅读它,直到你“得到”它。目前,您似乎没有完成作业并尝试使用书籍或教程制作简单的着色器。如果你找不到一本书,那么 NVidia OpenGL SDK 有很多示例(在 C/C++ 中,但转换它们并不难)。

于 2012-03-03T06:25:01.577 回答
1

也许您可以在我的Minecraft 地图博客文章中找到一些有用的东西。所有示例都使用 Python、Pygame 和 PyOpenGL。他们在片段着色器中做了很多事情。他们只使用微不足道的几何:只有一个四边形。

根据您的描述,听起来您使用一个大纹理比使用多个小纹理要好得多。但是,在某些情况下,拥有大量小纹理并在着色器中在它们之间进行选择确实有意义。阵列纹理 在这种情况下很有用,因为它们不会遇到使用纹理图集时可能遇到的过滤和钳位问题。(事实上​​,我博客中的示例使用了纹理图集,并且在缩小到远处时会遇到一些 mip-mapping 问题。我最近一直在使用数组纹理来解决这个问题。)

于 2012-03-03T14:59:34.840 回答