在 OpenGL ES 中渲染时编译着色器是一种好的/有效的做法吗?

Jan*_*n_K 5 android opengl-es samsung-mobile glsles

系统:安卓4.03,OpenGL ES 2.0

问题:在第一帧已经用另一个程序/着色器渲染后调用 glAttachShader 时,某些设备 (Galaxy S3) 会因“GL_INVALID_VALUE”错误而崩溃(错误堆栈中没有更多详细信息)。其他设备(华硕 eee TF101)完全没问题。错误并不总是发生,有时它也是“GL_INVALID_ENUM”。如果我在第一次调用 onDrawFrame 时强制编译所有着色器,则它适用于所有(我的)设备。

问题: 是否存在 openGL(ES) 机器无法编译着色器的状态?绑定缓冲区、纹理或启用的属性数组是否可能干扰将着色器附加到程序?如果是这样,在附加着色器和链接程序之前必须确保的理想状态是什么?在其他对象已经用其他着色器渲染之后编译着色器是否有效?

背景:我正在开发一个 Android 库,它将允许我以更面向对象的方式使用 openGL 图形(使用“场景”、“材料”、“模型”等对象),最终轻松编写游戏。场景、模型等是在与 GL 上下文不同的线程中创建的。只有当 onDrawFrame 遇到这些对象之一时,它才会在正确的线程中进行缓冲区对象绑定、纹理绑定和着色器编译。我想避免在我的代码开头编译所有着色器。根据材质、模型和场景的要求组装着色器源(例如:材质:包括凹凸贴图,模型:包括矩阵调色板撇脂,场景:包括雾)。当模型从场景中移除时,我将再次删除着色器 - 如果我添加另一个模型,

在这一点上,我试图在不发布代码的情况下尽可能简洁 - 您可以想象从这个库中提取相关部分是很困难的。

Jan*_*n_K 0

如果您复制Android开发包附带的BasicGLSurfaceView示例代码来启动您的项目,那么首先调用

checkGlError
Run Code Online (Sandbox Code Playgroud)

是在附加顶点着色器之后。但是,您可能很早就使用过无效值或枚举,或者在代码中的不同位置使用过无效值或枚举。但这只能通过 glAttachShader 之后的调用来获取。

就我而言,我删除了仍然链接为帧缓冲区的渲染目标的纹理。我的旧 Android 设备运行速度较慢,在删除之前编译了着色器,我的新设备以某种方式设法调用

glFramebufferTexture2D
Run Code Online (Sandbox Code Playgroud)

在编译着色器之前。整个事情在某种程度上与queueEvent和我对线程安全的理解不佳有关。

感谢 TraxNet 和 Prateek Nina 的努力。