在不同的NSWindow上的NSOpenGLView上绘制不同的形状

时间:2018-04-23 17:40:15

标签: objective-c macos opengl audio nsopenglview

我在Mac OS上的目标c中使用AudioVisualizer。 我有2个NSWindows,里面有NSOpenGLView。

enter image description here

如果仅使用NSOpenGLView打开1 NSWindow,它会显示没有任何问题的形状。

但是如果打开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?

2 个答案:

答案 0 :(得分:1)

您正在使用顶点缓冲区对象和顶点数组缓冲区进行绘制,但您似乎并未在两个上下文之间共享。这意味着当您在第二个上下文中使用顶点缓冲区对象时,其ID不会存在于该上下文中。但是,如果您使用第一个上下文作为shareContext:的第二个视图创建的NSOpenGLContext参数,那么您可以在上下文之间共享对象。

您可以在代码中定期添加对glGetError()的来电,以提醒您注意此类问题。

答案 1 :(得分:1)

根据@ 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;
    }

它就像一个魅力。