【问题标题】:How can I use a 3-D texture in iOS?如何在 iOS 中使用 3-D 纹理?
【发布时间】:2012-02-11 15:56:45
【问题描述】:

我在 OpenGL ES 2.0 中找不到来自 OpenGL 的 glTexImage3D() 函数。那么如何使用 3-D 纹理,例如:.tga 文件?

有人知道如何在 OpenGL ES 2.0 中使用 3-D 纹理吗?

【问题讨论】:

    标签: iphone ios opengl-es opengl-es-2.0


    【解决方案1】:

    OpenGL ES 1.x 和 2.x 不强制要求支持 3d 纹理 - 参见例如glBindTexture 的规范手册页,其中仅列出了 GL_TEXTURE_2DGL_TEXTURE_CUBE_MAP 作为目标 - 而且 iOS 硬件没有提供任何合适的扩展。

    我能想出的最佳解决方案是将 3d 纹理打包成 2d 纹理,因此您可以说是 128x128x128 3d 纹理,然后将其布置为 128 个单独的 128x128 图像单个 2d 纹理上的 16x8 网格。因此 2d 纹理为 2048x1024 像素,接近 iPhone 4 和 iPad 2 代设备以及之前的 ES 2.0 兼容 iOS 设备的硬件限制。

    然后,您将 3d 纹理坐标提供给片段着色器,就像有一种方法可以在本地索引 3d 纹理一样,但需要快速计算一下以将其折叠为 2d。

    所以,在 128x128x128 的例子中,你会做类似的事情(编码在这里,正如我所说,未经测试,):

    texPos.x = sourceVarying.x / 16.0; // because we've packed 16 source images across,
    texPos.y = sourceVarying.y / 8.0;  // and 8 images down
    
    // we'll multiply z by 16 since then, logically, the integer part is
    // how many tiles across to index, and the decimal part is now many
    // tiles down to index
    texPos.z *= 16.0;
    
    // figure out how many tiles across to index, with each tile being
    // 1.0 / 16.0 in size
    texPos.x += floor(texPos.z) / 16.0;
    
    // remove the integer part of z, then multiply by 8 to do much what
    // we just did to y
    texPos.z = fract(texPos.z) * 8.0;
    texPos.y += floor(texPos.z) / 8.0;
    
    // now load the appropriate sample from texPos.xy
    

    这可能不是实现这一目标的最有效方法,它是为(相对)清晰而编写的。您还看到了每个纹理读取依赖的显着性能劣势(即,GPU 无法预测片段着色器之外的访问,从而导致严重的管道困难)。但这要与使用 3d 纹理贴图以外的其他东西所必须花费的任何成本进行权衡。

    还请注意,您正在执行一个与特定 z 切片相关联的访问。因此,您只能在至少一个维度上进行GL_NEAREST 类型的采样,除非您想进行两个样本并以更高的成本自己混合结果。我也没有对钳位做任何事情,你很可能想要解决这个问题。

    Datanwolf(+1,顺便说一句)关于 mipmapping 是一个问题也是完全正确的;我最终只是禁用了它。


    2013 年末附录:在撰写本文时,iOS 7、iPhone 5s、第二代 iPad Mini 和 iPad Air 都支持 ES 3.0。 3.0 引入了GL_TEXTURE_3D 目标。因此,您可以直接在这些设备上使用 3d 纹理,并且可能在所有未来的 iOS 设备上使用。而且,据记录,它在 Android 上也有类似的可用性,所有最近的 Nexus 设备、HTC One、一些最近的三星和其他设备都支持它。

    【讨论】:

    • 感谢您的回答!事实上,我不确定我需要的是 3d 纹理。这是我第一次使用opengl es 做一些工作。我接受了一个项目,我需要在屏幕上渲染一座房子。当我打开 .obj 文件时,我发现每个 vt 都有三个组件,而不仅仅是 vt。如果我忽略 vt 的第三个分量,纹理会很奇怪。也许我不必使用 3d 纹理?我把纹理图像放在下面。也许你们专家知道我需要什么。 ww2.sinaimg.cn/large/991557bagw1dpytx071d5j.jpg 以及最终效果ww4.sinaimg.cn/large/991557bagw1dpyu275vz4j.jpg
    • 看起来像普通的二维纹理;你还记得 OBJ 存储 y 纹理坐标的方式与 OpenGL 是相反的,所以你需要在你的管道中的某个地方做一个快速的 1-y 吗?
    • 呃……我没有那样做!谢谢!我会试试的!
    • @Tommy 这取决于您使用的创作工具。 Maya 至少 可能 3ds max 和 Blender 也使用左下角 (0,0) 的 OpenGL convention(D3D 的惯例是左上角有 (0,0) )
    【解决方案2】:

    我在 OpenGL ES 2 中找不到 glTexImage3D 函数

    因为 OpenGL-ES 不支持 3D 纹理。想一想:3D 纹理比 2D 纹理需要更多的内存。而内存是嵌入式/移动设备上非常稀缺的资源,这正是 ES 的目标。

    我想也许有人知道使用 3d 纹理的算法?

    与其说是算法问题,不如说是资源有限的问题。理论上,您可以使用多个纹理单元/采样器在那里上传图层,并在着色器中进行插值。但这会缺乏深度 mipmaping。

    3d 纹理,例如:.tag 文件?

    标签文件?抱歉,我不知道这种格式。你能给我一个阅读链接吗?谷歌没有找到有用的信息。你是说 TGA 吗?

    【讨论】:

    • 感谢您的回答!事实上,我不确定我需要的是 3d 纹理。这是我第一次使用opengl es 做一些工作。我接受了一个项目,我需要在屏幕上渲染一座房子。当我打开 .obj 文件时,我发现每个 vt 都有三个组件,而不仅仅是 vt。如果我忽略 vt 的第三个分量,纹理会很奇怪。也许我不必使用 3d 纹理?我把纹理图像放在下面。也许你们专家知道我需要什么。 ww2.sinaimg.cn/large/991557bagw1dpytx071d5j.jpg 以及最终效果ww4.sinaimg.cn/large/991557bagw1dpyu275vz4j.jpg
    • @Ning:第三个组件w 就像一个缩放参数。你不需要它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-02-14
    • 1970-01-01
    • 2011-03-25
    • 2019-04-21
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多