我使用OpenGL在几个不同的对象中绘制数组。每个对象都绘制不同的数据,但对于每个对象,数据的容器/位置在程序的整个生命周期内保持不变。 OpenGL告诉我我有许多冗余状态调用:
其中,我只是明确地调用glUniformMatrix4fv和glUniform4fv。在看到这个之后,我试图移动它们,所以它们只在OpenGL的设置过程中调用,但是数组没有被绘制。
目前,这是每次重绘时调用的示例:
glBindVertexArrayOES(_vertexArray);
glUseProgram(_program);
glUniformMatrix4fv(_mvpMatrixHandle,1,0,_mvpMatrix.m);
glUniform4fv(_colorHandle,1,colors);
glDrawArrays(GL_TRIANGLE_FAN,0,4);
的问题:
因为我传递给这些函数的变量的容器和位置,每次我为某个给定对象绘制数组时,还是只需要在程序开头只调用一次这些函数?如果是这样,我该怎么做?
如何消除我未明确调用的其他冗余状态调用?
答案 0 :(得分:2)
如果值未更改,则传递给着色器的任何数据只能传递一次。虽然完全有可能,但我建议你不要这么做,因为这样的代码难以维护。如果在某些时候你选择更改矩阵,那么它将给你重组的麻烦。所以只有在非常晚的开发状态才这样做,而且只有当你需要获得性能时才会这样做(不过这会产生很大的不同)。还有其他方法来处理这些事情,但是第一次......
如果在移动矩阵调用时未绘制对象,则表示矩阵未正确设置或更多可能的情况是您在调用之前忘记使用着色器程序。 (glUseProgram(_program);
)
因为你说你自己没有绑定缓冲区并且仍然得到冗余警告,你可能正在使用一些更高级别的工具,例如GLKView(控制器),它在内部为你做。您将无法丢失这些警告,我建议您根本不要使用这些工具。从GLKit中唯一有用的是矩阵和我的经验中的一些向量运算。
关于你的冗余电话以及其他方式"有些人要做的是检查发送到着色器的当前状态,并比较新值是否与当前值不同。这并不像看起来那么容易,因为一些值应该是每个着色器和一些每个上下文。例如,如果启用Alpha混合,它将影响所有着色器,您应该检查并在上下文对象上分配值。另一方面,如果要设置矩阵等制服,则应检查并在正在使用的着色器上进行分配。这需要一些工作但是值得获得一个漂亮的干净代码:您应该为着色器对象和上下文对象创建包装器。这些参数在分配时也应该带有某些参数的状态,并在分配之前检查新值:
- (void)setMatrix:(GLKMatrix4)matrix
{
if(memcmp(currentMatrix.m, matrix.m, sizeof(matrix.m)) != 0) { // will return 0 if they are the same
memcpy(currentMatrix.m, matrix.m, sizeof(matrix.m)); // copy the new data
glUniformMatrix4fv(_mvpMatrixHandle, 1, 0, matrix.m); // send data to shader
}
}
然后应该对您正在使用的所有呼叫执行此操作。即使您每次都调用它们,它也会阻止任何冗余调用,但由于内存比较,会在CPU上产生很小的开销。这仍然是非常小的开销。