2

I work on AudioVisualizer in objective c on Mac OS. I have 2 NSWindows what has NSOpenGLView in it.

enter image description here

If open only 1 NSWindow with NSOpenGLView, it shows shapes without any issues.

But if open 2 NSWindows what has NSOpenGLView on it, only one GLView draws a shape, but the shape is not matched with its audio when play other audio in other NSWindow.

In NSOpenGLViews, it calls redraw method exactly whenever CADisplayLink needs display.

Here is the part related with OpenGLContext.

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

And here is redraw method

[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];

And here is redrawWithPoints Method

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

I want to show different Audio Visualizers in different NSOpenGLViews at same time.

Is it possible to do with OpenGL?

Mark
  • 271
  • 1
  • 9

2 Answers2

1

You're drawing using a vertex buffer object and vertex array buffer, but you don't appear to be sharing between the two contexts. That means that when you use the vertex buffer object in the second context, its ID doesn't exist in that context. However, if you use the first context as the shareContext: parameter to the second view's creation of the NSOpenGLContext, then you can share objects between contexts.

It can help to add calls to glGetError() periodically in your code to alert you to issues like this.

user1118321
  • 25,567
  • 4
  • 55
  • 86
  • Thank you @user1118321. so you mean I need to share OpenGLContext between NSOpenGLViews? If you have any example, please share. – Mark Apr 24 '18 at 09:06
  • Thank you for your help. @user1118321 I created OpenGLContextManager for sharing. By using it, created only one openGLContext and used it on the other NSOpenGLViews. – Mark Apr 24 '18 at 09:51
  • That could work. Instead what I meant was that all the contexts would be in the same share group. Not that one context would be shared between all views, but that they would all be created in the same share group. See [here](https://developer.apple.com/library/content/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_contexts/opengl_contexts.html#//apple_ref/doc/uid/TP40001987-CH216-SW7) for details. – user1118321 Apr 24 '18 at 16:03
1

Based on reply of @user1118321, I made NSOpenGLContextManager for managing OpenglContext.

@interface GOOpenGLContextManager : NSObject

+ (GOOpenGLContextManager*) shared;

@property (nonatomic, strong) NSOpenGLContext* context;

@end

By using it, in All NSOpenGLViews, used only one shared NSOpenGLContext.

Here is the code what I have used.

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

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

It works like a charm.

Mark
  • 271
  • 1
  • 9