Рисуйте разные фигуры в NSOpenGLView в разных NSWindow

Я работаю над AudioVisualizer в объективе c на Mac OS. У меня есть 2 NSWindows, в которых есть NSOpenGLView.

введите здесь описание изображения

Если открыть только 1 NSWindow с NSOpenGLView, он показывает фигуры без проблем.

Но если открыть 2 NSWindows, на которых есть NSOpenGLView, только один GLView рисует фигуру, но форма не сопоставляется с ее звуком при воспроизведении другого звука в другом NSWindow.

В NSOpenGLViews метод перерисовки вызывается именно тогда, когда CADisplayLink требуется отображение.

Вот часть, связанная с OpenGLContext.

self.openGLContext = [[NSOpenGLContext alloc] initWithFormat:self.pixelFormat
                                                shareContext:nil];

А вот и метод redraw

[self.openGLContext makeCurrentContext];
[self.openGLContext lock];

[self redrawWithPoints:self.info->points
            pointCount:self.info->pointCount
            baseEffect:self.baseEffect
    vertexBufferObject:self.info->vbo
     vertexArrayBuffer:self.info->vab
          interpolated:self.info->interpolated
              mirrored:self.shouldMirror
                  gain:self.gain];

[self.openGLContext flushBuffer];
[self.openGLContext unlock];
[NSOpenGLContext clearCurrentContext];

А вот метод redrawWithPoints

glClear(GL_COLOR_BUFFER_BIT);
GLenum mode = interpolated ? GL_TRIANGLE_STRIP : GL_LINE_STRIP;
float interpolatedFactor = interpolated ? 2.0f : 1.0f;
float xscale = 2.0f / ((float)pointCount / interpolatedFactor);
float yscale = 1.0f * gain;
GLKMatrix4 transform = GLKMatrix4MakeTranslation(-1.0f, 0.0f, 0.0f);
transform = GLKMatrix4Scale(transform, xscale, yscale, 1.0f);
baseEffect.transform.modelviewMatrix = transform;
glBindBuffer(GL_ARRAY_BUFFER, vbo);
[baseEffect prepareToDraw];
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition,
                      2,
                      GL_FLOAT,
                      GL_FALSE,
                      sizeof(GOAudioPlotGLPoint),
                      NULL);
glDrawArrays(mode, 0, pointCount);
if (mirrored)
{
    baseEffect.transform.modelviewMatrix = GLKMatrix4Rotate(transform, M_PI, 1.0f, 0.0f, 0.0f);
    [baseEffect prepareToDraw];
    glDrawArrays(mode, 0, pointCount);
}


glFlush();

Я хочу одновременно показывать разные аудиовизуализаторы в разных NSOpenGLViews.

Можно ли сделать с OpenGL?


person PassionMobile    schedule 23.04.2018    source источник


Ответы (2)


Вы рисуете, используя объект буфера вершин и буфер массива вершин, но, похоже, вы не разделяете эти два контекста. Это означает, что когда вы используете объект буфера вершин во втором контексте, его идентификатор не существует в этом контексте. Однако, если вы используете первый контекст в качестве параметра shareContext: для создания второго представления NSOpenGLContext, вы можете совместно использовать объекты между контекстами.

Периодически добавляйте вызовы glGetError() в свой код, чтобы предупреждать вас о подобных проблемах.

person user1118321    schedule 24.04.2018
comment
Спасибо, @user1118321. так вы имеете в виду, что мне нужно разделить OpenGLContext между NSOpenGLViews? Если у вас есть пример, поделитесь. - person PassionMobile; 24.04.2018
comment
Спасибо за помощь. @user1118321 user1118321 Я создал OpenGLContextManager для совместного использования. Используя его, создал только один openGLContext и использовал его в других NSOpenGLViews. - person PassionMobile; 24.04.2018
comment
Это может сработать. Вместо этого я имел в виду, что все контексты будут в одной и той же группе общего доступа. Не то, чтобы один контекст был общим для всех представлений, а чтобы все они были созданы в одной и той же группе общего доступа. См. здесь для подробностей. - person user1118321; 24.04.2018

Основываясь на ответе @user1118321, я сделал NSOpenGLContextManager для управления OpenglContext.

@interface GOOpenGLContextManager : NSObject

+ (GOOpenGLContextManager*) shared;

@property (nonatomic, strong) NSOpenGLContext* context;

@end

Используя его, во всех NSOpenGLViews используется только один общий NSOpenGLContext.

Вот код, который я использовал.

    self.openGLContext = [[NSOpenGLContext alloc] initWithFormat:self.pixelFormat
                                                    shareContext:[OpenGLContextManager shared].context];

    if ([OpenGLContextManager shared].context ==  nil) {
        [OpenGLContextManager shared].context = self.openGLContext;
    }

Работает как часы.

person PassionMobile    schedule 24.04.2018