5

我有一个带有多个使用 OpenGL ES 2.0 和自定义片段着色器的 OpenGL-ES 视图的 iPad 应用程序。目前,着色器已针对每个单独的 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");

}
4

2 回答 2

7

以下是EAGLSharegroup 类参考中关于共享的引用:

目前,共享组管理纹理、缓冲区、帧缓冲区和渲染缓冲区。

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

然而,这里是来自Apple 开发论坛的引述:

共享 Shaders/Programs/Pipelines 是合法的,但实际上要避免同时使用同一个 Program。

问题是 Uniform 值是程序本身的属性,因此如果您从多个线程中使用同一个程序,这将违反禁止从一个线程修改对象同时从另一个线程使用它的规则。

如果使用不重叠(例如,一个上下文生成程序,另一个渲染),那应该可以正常工作。

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

于 2014-05-08T12:46:59.790 回答
5

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

于 2012-11-26T23:12:26.947 回答