2012-11-26 106 views
0

我有一个使用OpenGL ES 2.0和自定义片段着色器的多个OpenGL-ES视图的iPad应用程序。目前,着色器会针对每个单独的OpenGL视图进行编译和链接。我想编译和链接着色器一次,并重新使用它们的每个视图。在理论上,这应该仅仅是调用在多个OpenGL-ES上下文中共享glProgram?

gluseProgram(gProgramHandle);

在我的render()方法

,呈现之前的事,和装载gProgramHandle一次,对吗?但这不起作用。当我切换到使用单个gProgramHandle(在初始化时设置为-1)时,只有一个OpenGL视图有效,其他视图显示为深绿色的矩形。我究竟做错了什么?

- (void)loadShaders 
{ 
    if (gProgramHandle == -1) 
{ 
    NSLog(@"Compiling shaders..."); 

    GLuint vertexShader = [self compileShader:@"AIMGsiVertexShader" withType:GL_VERTEX_SHADER]; 
    GLuint fragmentShader = [self compileShader:@"AIMGsiFragmentShader" withType:GL_FRAGMENT_SHADER]; 

    gProgramHandle = glCreateProgram(); 
    glAttachShader(gProgramHandle, vertexShader); 
    glAttachShader(gProgramHandle, fragmentShader); 
    glLinkProgram(gProgramHandle); 

    GLint linkSuccess; 
    glGetProgramiv(gProgramHandle, GL_LINK_STATUS, &linkSuccess); 
    if (linkSuccess == GL_FALSE) 
    { 
      // If there was an error when compiling the gsls shaders, report the compile error and quit. 
     GLchar messages[256]; 
     glGetProgramInfoLog(gProgramHandle, sizeof(messages), 0, &messages[0]); 
     NSString *messageString = [NSString stringWithUTF8String:messages]; 
     NSLog(@"%@", messageString); 
     exit(1); 
    } 

    NSLog(@"Done compiling and linking shaders."); 
} 

    // We can efficiently switch between shaders by calling glUseProgram() to use the program with the shaders we want to use. 
glUseProgram(gProgramHandle); 

    // Gradient map values are sent in this vector: numValuesInCache, factor, offset 
_gradientValsUniform = glGetUniformLocation(gProgramHandle, "GradientVals"); 
_numColorsInGradient = glGetUniformLocation(gProgramHandle, "NumColorsInCache"); 
_gradientColorsArray = glGetUniformLocation(gProgramHandle, "ColorsArray"); 


_positionSlot = glGetAttribLocation(gProgramHandle, "Position"); 

glEnableVertexAttribArray(_positionSlot); 

_projectionUniform = glGetUniformLocation(gProgramHandle, "Projection"); 
_modelViewUniform = glGetUniformLocation(gProgramHandle, "Modelview"); 

_texCoordSlot = glGetAttribLocation(gProgramHandle, "TexCoordIn"); 
glEnableVertexAttribArray(_texCoordSlot); 
_textureUniform = glGetUniformLocation(gProgramHandle, "Texture"); 

} 

回答

3

您不能跨上下文共享程序。 GL上下文是状态信息的集合,程序是该状态的一部分。我会质疑每个观点是否需要自己的背景,这可能不是必要的。如果在主线程上完成所有渲染,则在视图之间共享上下文,并在每个视图的每次绘制调用中设置所需的状态。如果您在多个线程上渲染,请查看使用[[EAGLContext alloc] initWithAPI:... sharegroup:...]创建上下文,并从您的主要上下文中传入共享组。

+0

太棒了,非常感谢你! –

+0

在OpenGL ES 2.0中共享着色器/程序/管道是合法的。 – Vlad

+0

你的意思是“分享”?在这种情况下,在上下文之间共享着色器/程序时,我发现很难看到这将是非法的,除非你有许可的着色器禁止它,这看起来很奇怪。 – combinatorial

1

下面是引自EAGLSharegroup Class Reference共享一下:

目前,sharegroup管理纹理缓冲器,帧缓存,和renderbuffers。

正如您所看到的着色器/程序/管道未提及。

但是这里是引自Apple dev forum

是合法的分享着色器/程序/管道,但实际上使用相同的计划,同时要避免的东西。

问题是统一值是程序本身的属性,所以如果您从多个线程使用相同的程序,将违反从一个线程修改对象时使用另一个线程的规则。

如果用法不重叠(例如一个上下文产生程序,另一个上下文呈现),那么应该可以正常工作。

为了测试着色器和流水线的共享我为iPad开发了简单的项目:https://github.com/Gubarev/shared-shaders-test。我可以确认分享的作品!

相关问题