- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在 Android 上的 OpenGL ES 2.0 中实现一个引擎。我有多个着色器,对象可以采用多个纹理。
我的目标是尽量减少对 OpenGL 的纹理绑定(bind)调用,因此我保留了每个着色器当前绑定(bind)纹理的列表,并且仅在纹理发生变化时调用 glBindTexture()
。
例如我有一个天空盒着色器,我只用它绘制一个对象(天空盒立方体),那么这个着色器在其生命周期内只需要绑定(bind)一个纹理。
当我用相同的纹理绘制多个对象时,也会有收获。
我的症状是,如果我在绘制之前不重新绑定(bind)天空盒纹理,则会在天空盒上使用不同的(先前绘制的)对象的纹理。这个先前绘制的对象使用不同的着色器。
那么假设当我再次使用着色器程序时纹理绑定(bind)会恢复是错误的吗?
ps.:我为天空盒使用单个 2d 纹理,而不是立方体贴图。
最佳答案
是的,假设在使用给定着色器程序时恢复纹理绑定(bind)是错误的。
纹理绑定(bind)状态完全独立于当前着色器程序。每个纹理单元 和目标 当前绑定(bind)一个纹理。假设您执行以下代码序列:
glActiveTexture(GL_TEXTURE7);
glBindTexture(GL_TEXTURE_2D, myTexId);
您正在将 ID 为 myTexId
的纹理绑定(bind)到纹理单元 7 的 2D 目标。此状态将一直保持,直到您将不同的纹理绑定(bind)到单元 7 的 2D 目标(或删除纹理), 完全独立于激活的着色器程序。
纹理和着色器程序之间的关系是通过将程序的采样器统一变量的值设置为纹理单元来建立的。继续上面的示例,您指定给定程序应通过以下方式使用此纹理:
// needed only once after linking the program
GLint texLoc = glGetUniformLocation(myProgId, "MySampler");
// use the texture bound to unit 7
glUseProgram(myProgId);
glUniform1i(texLoc, 7);
基于此,如果您想避免对纹理绑定(bind)进行冗余调用,则必须跟踪哪个纹理绑定(bind)到哪个单元。此信息需要“全局”维护,即独立于特定着色器程序。
请注意,统一值是每个程序,因此您不必在绑定(bind)特定程序后再次设置该值,除非您希望它从绑定(bind)到不同单元的纹理中采样。
为了减少需要绑定(bind)不同纹理的次数,您可以做的一件事是为每个着色器使用不同的纹理单元。作为一个简化的示例,想象这样一种情况,其中每个程序都使用一个纹理,并且每次使用该程序时都使用相同的纹理。然后,您可以为每个程序的采样器统一设置不同的值,并将每个程序使用的纹理绑定(bind)到相应的纹理单元。每当您调用 glUseProgram()
时,每个程序都会使用相应的纹理,而无需调用 glBindTexture()
。
当然,当程序使用多个纹理时,这会变得有点复杂,并且您确实希望为特定程序切换纹理。但是如果您以巧妙的方式管理纹理单元,您仍然可以大大减少纹理绑定(bind)操作的数量。这样做时,请记住纹理单元的数量是有限的。可以通过以下方式查询限制:
glGetIntegerv(MAX_TEXTURE_IMAGE_UNITS, ...);
ES 2.0 的限制可以低至 8。
或者,换个角度看同样的事情:如果你使用的纹理少于可用纹理单元的数量,你可以将每个纹理绑定(bind)到一个不同的纹理单元一次,然后通过纹理绑定(bind)完成。然后,您可以通过将每个着色器的采样器制服设置为具有所需纹理绑定(bind)的纹理单元来控制每个着色器在任何给定时间使用哪个纹理。
实际上,如果您的应用有些复杂,您很可能会混合使用这些方法。例如,您可以将一些经常使用的纹理始终绑定(bind)到一个固定的纹理单元,同时在必要时重新绑定(bind)其他纹理。
由于这听起来可能比实际情况更复杂,所以让我总结一下这些关系:
glUniform1i()
在特定程序处于 Activity 状态时调用,在着色器程序 和纹理单元 之间建立关系。。<glBindTexture()
在纹理单元 和纹理对象 之间建立关系。因此纹理单元在程序和纹理对象之间提供了一种间接级别,这解释了为什么纹理绑定(bind)状态不是特定程序的直接部分。
关于android - glUseProgram 之间的 OpenGL 纹理绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26053851/
我有一个未定义数量的显示上下文,每个都将显示一个纹理。当我调用 glGenTextures 时,我会在所有显示上下文中返回相同的名称。这会起作用吗?即使它们具有相同的名称,它们仍会存储和显示不同的纹理
我在 SVG 中看到过:文本填充是图像而不是颜色;我一直想知道使用 CSS3 是否可以实现这样的事情。 我浏览了整个网络,到目前为止只找到了基本上将图像覆盖在文本上的解决方法(请参阅 this ,这对
我是 WebGL 的新手。 :)我知道顶点数据和纹理不应该经常更新,但是当它们确实发生变化时,首选哪个:- 通过调用 gl.deleteBuffer 销毁先前的缓冲区 (static_draw) 并创
我需要将 GL_RGBA32F 作为内部格式,但我在 OpenGL ES 实现中没有得到它。相反,我只得到 GL_FLOAT 作为纹理数据类型。 OES_texture_float 规范没有说明里面的
当我执行某些几何体的渲染时,我可以在控制台中看到此警告: THREE.WebGLRenderer: Texture is not power of two. Texture.minFilter sho
我正在尝试使用阴影贴图实现阴影,因此我需要将场景渲染到单独的帧缓冲区(纹理)。我无法让它正常工作,因此在剥离我的代码库后,我留下了一组相对简单的指令,这些指令应该将场景渲染到纹理,然后简单地渲染纹理。
我在 XNA 中使用带有自定义着色器的标准 .fbx 导入器。当我使用 BasicEffect 时,.fbx 模型被 UV 正确包裹并且纹理正确。但是,当我使用我的自定义效果时,我必须将纹理作为参数加
如果我创建一个 .PNG 1024 x 1024 的纹理并在中间画一个 124 x 124 的圆,它周围是空的,它使用的 RAM 量是否与我画一个 124 x 的圆一样124 x 124 空间上的 1
我试图在 Android 中绘制一个地球仪,为此我使用了 OpenGL。然而,为了让它更容易理解,我将从制作一个简单的 3D 立方体开始。我使用 Blender 创建我的 3D 对象(立方体),并在我
文本本身的背景图像层是否有任何 JS/CSS 解决方案? 示例 最佳答案 检查这个http://lea.verou.me/2012/05/text-masking-the-standards-way/
非功能代码: if sprite.texture == "texture" { (code) } 当 Sprite 具有特定纹理时,我正在尝试访问 Sprite 的纹理以运行代码。目前纹理仅在我的
我正在尝试学习适用于 iOS 的 SceneKit 并超越基本形状。我对纹理的工作原理有点困惑。在示例项目中,平面是一个网格,并对其应用了平面 png 纹理。你如何“告诉”纹理如何包裹到物体上?在 3
基本上, 这有效: var expl1 = new THREE.ImageUtils.loadTexture( 'images/explodes/expl1.png' ); this.material
我正在尝试将各种场景渲染为一组纹理,每个场景都有自己的纹理到应该绘制的位置...... 问题: 创建 512 个 FBO,每个 FBO 绑定(bind)了 512 个纹理,这有多糟糕。只使用一个 FB
我正在使用文本 protobuf 文件进行系统配置。 我遇到的一个问题是序列化的 protobuf 格式不支持注释。 有没有办法解决? 我说的是文本序列化数据格式,而不是方案定义。 这个问题是有人在某
我想将我的 3D 纹理的初始化从 CPU 移到 GPU。作为测试,我编写了一个着色器将所有体素设置为一个常数值,但纹理根本没有修改。我如何使它工作? 计算着色器: #version 430 layou
我可以像这样用 JavFX 制作一个矩形: Rectangle node2 = RectangleBuilder.create() .x(-100) .
我在 iPhone 上遇到了 openGL 问题,我确信一定有一个简单的解决方案! 当我加载纹理并显示它时,我得到了很多我认为所谓的“色带”,其中颜色,特别是渐变上的颜色,似乎会自动“优化”。 只是为
假设我有一个域类 class Profile{ String name byte[] logo } 和一个 Controller : class ImageController {
我正在开发一款使用 SDL 的 2D 游戏。由于某些系统的 CPU 较弱而 GPU 较强,因此除了普通的 SDL/软件之外,我还有一个使用 OpenGL 的渲染器后端。 渲染器界面的简化版本如下所示:
我是一名优秀的程序员,十分优秀!