在多个OpenGL-ES上下文中共享glProgram?

时间:2012-11-26 22:19:55

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

我有一个带有多个OpenGL-ES视图的iPad应用程序,它们使用OpenGL ES 2.0和自定义片段着色器。目前,为每个单独的OpenGL视图编译和链接着色器。我想编译和链接着色器一次,并为每个视图重用它们。从理论上讲,这只是一个问题

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");

}

2 个答案:

答案 0 :(得分:3)

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

答案 1 :(得分:1)

以下是EAGLSharegroup Class Reference关于分享的引用:

  

目前,sharegroup管理纹理,缓冲区,帧缓冲区和渲染缓冲区。

如您所见,未提及着色器/程序/管道。

但是引用Apple dev forum

  

共享着色器/程序/管道是合法的,但实际上同时使用同一程序是可以避免的。

     

问题是Uniform值是Program本身的属性,所以如果你使用来自多个线程的相同程序,那么违反规则就不会从一个线程修改一个对象而从另一个线程使用它。

     

如果用法没有重叠(例如,一个上下文产生程序,另一个上下文渲染),则应该可以正常工作。

为了测试着色器和管道的共享,我为iPad开发了一个简单的项目:https://github.com/Gubarev/shared-shaders-test。我可以确认共享有效!