如何在 Mac OS 中的 NSOpenGLView 和全屏上下文之间共享纹理?

发布于 2024-10-19 17:17:44 字数 1694 浏览 2 评论 0原文

我正在开发一个使用 2D 纹理创建动画万花筒的应用程序。它开始显示到 NSOpenGLView。我正在添加一个切换到全屏模式的选项。

我更喜欢使用 OS 10.5 方法来全屏,这样我就可以支持 10.5,但我认为如果我使用“在 Mac OS X v10 中创建全屏应用程序”下的文档中描述的方法,我会面临同样的问题.6"。

NSOpenGLContext init 方法 initWithFormat:shareContext: 采用一个可选指针,指向“另一个 OpenGL 图形上下文,其纹理命名空间和显示列表要与接收者共享”。

我用来创建全屏 OpenGL 上下文的代码很简单:

NSOpenGLPixelFormatAttribute myAttributes[] =               // Pixel Format Attributes for the FullScreen NSOpenGLContext
{
    NSOpenGLPFAFullScreen,                                  // specify full-screen OpenGL context
    NSOpenGLPFAScreenMask,
    CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),   // specify main display
    NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute) 32,
    NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute) 0,
    NSOpenGLPFAStencilSize, 0,
    NSOpenGLPFADoubleBuffer,
    NSOpenGLPFAAccelerated,
    0
};

NSOpenGLPixelFormat *myPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:myAttributes];  // Create FullScreen NSOpenGLContext with these attributes


NSOpenGLContext *fullScreenContext = [[NSOpenGLContext alloc] initWithFormat:myPixelFormat shareContext: myContext]; // Create an NSOpenGLContext with the FullScreen pixel format.

但是,它似乎不起作用。

我的应用程序仅使用一种纹理,因此我一开始不使用 glGenTextures 和 glBindTexture。相反,我只是使用单个当前纹理作为上下文。

我尝试更改代码以使用 glGenTextures 创建命名纹理,希望在切换到全屏上下文后可以绑定命名纹理,但没有骰子。两种方法给出相同的结果 - 纹理在全屏上下文中不起作用。

我没有收到任何错误,但使用纹理绘图没有任何作用。

每次切换到全屏模式时,我都被迫重新创建纹理。这很糟糕,因为纹理可能非常大(取决于用户加载的图像有多大,直到最大纹理大小。)这迫使我将一个非常大的对象的两个副本加载到 VRAM 中。更糟糕的是,在某些情况下我必须进行字节混合才能获得正确的字节顺序。在大纹理上这需要几秒钟的时间,这会在进入全屏模式时造成“怀孕暂停”。

在 NSOpenGLView 和全屏 OpenGL 上下文之间共享纹理是否缺少一些技巧?

I am working on an app that uses 2D textures to create animated kaleidoscopes. It starts out displaying to an NSOpenGLView. I am adding an option to switch to full-screen mode.

I would prefer to use the OS 10.5 approach to full screen so I can support 10.5, but I think I would face the same issue if I was using the approach described in the docs under "Creating a Full-Screen Application in Mac OS X v10.6".

The NSOpenGLContext init method initWithFormat:shareContext: takes an optional pointer to "Another OpenGL graphics context whose texture namespace and display lists you want to share with the receiver".

The code I'm using to create the full screen OpenGL context is straightforward:

NSOpenGLPixelFormatAttribute myAttributes[] =               // Pixel Format Attributes for the FullScreen NSOpenGLContext
{
    NSOpenGLPFAFullScreen,                                  // specify full-screen OpenGL context
    NSOpenGLPFAScreenMask,
    CGDisplayIDToOpenGLDisplayMask(kCGDirectMainDisplay),   // specify main display
    NSOpenGLPFAColorSize, (NSOpenGLPixelFormatAttribute) 32,
    NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute) 0,
    NSOpenGLPFAStencilSize, 0,
    NSOpenGLPFADoubleBuffer,
    NSOpenGLPFAAccelerated,
    0
};

NSOpenGLPixelFormat *myPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:myAttributes];  // Create FullScreen NSOpenGLContext with these attributes


NSOpenGLContext *fullScreenContext = [[NSOpenGLContext alloc] initWithFormat:myPixelFormat shareContext: myContext]; // Create an NSOpenGLContext with the FullScreen pixel format.

However, it doesn't seem to work.

My app only uses one texture, so I started out not using glGenTextures and glBindTexture. Instead I just used the single current texture for the context.

I tried changing my code to create a named texture with glGenTextures, in the hopes that I could bind the named texture after switching to the full-screen context, but no dice. Both approaches give the same result - the texture does not work in the full screen context.

I don't get any errors, but drawing with a texture doesn't do anything.

I am forced to recreate my texture each time I switch to full-screen mode. This is bad because the textures are potentially very large (depending on how big an image the user loads, up to the max texture size.) That forces me to load two copies of a very large object into VRAM. Worse, I have to do byte-swizzling in some cases to get the byte order correct. That takes several seconds on a large texture, which makes for a "pregnant pause" when entering full-screen mode.

Is there some trick I'm missing to sharing textures between an NSOpenGLView and a full screen OpenGL context?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

随波逐流 2024-10-26 17:17:44

这些天我致力于 OSX 上的共享上下文,但苦于缺乏一个应该完成的事情清单以使其正常工作。我认为值得分享一些小事情或关键字,它们可以帮助找出您的案例中的问题所在。

建议:如果没有正确的检查工具(请参阅 khronos 或 NVidia 的开发人员网站),使用 DirectX 和 OpenGL 等绘图 API 可能会非常痛苦。一个合适的工具是您首先需要的。

  1. 您创建了一个新的 NSOpenGLContext,使用相同的像素格式对其进行初始化,并将其他上下文指示为共享资源的源。伟大的!
  2. 您应该使用 setOpenGLContext 方法将其分配给您的 NSOpenGLView。 (不需要 updatesetview 或我在网上看到的非常旧的帖子中的其他内容)
    • 如果您使用 xib 文件创建了窗口,则可以使用 NSOpenGLView 类的 awakeFromNib 方法来更改默认值上下文到刚刚创建的新上下文
    • 附加到视图的旧上下文将被自动销毁
    • 共享上下文中任何预先存在的资源也将被“导入”到新的上下文中。
  3. 调用[your_new_Context makeCurrentContext] - 我在awakeFormNib方法中完成了
  4. (这里我认为是@Duncan的问题),你需要设置所有渲染说明你需要。渲染状态不跨上下文共享!只有资源。这些是您想要设置的一些渲染状态(根据您的需要更改它们):

    glEnableVertexAttribArray(pgmImagePosition_);
    glEnableVertexAttribArray(pgmImageTextureCoord_);
    glEnable(GL_TEXTURE_2D);
    glDisable(GL_DITHER);
    glDisable(GL_ALPHA_TEST);
    glDisable(GL_BLEND);
    glDisable(GL_STENCIL_TEST);
    glDisable(GL_FOG);
    glDisable(GL_DEPTH_TEST);
    glPixelZoom(1.0,1.0);
    glClearColor(0.1, 0.1, 0.1, 1.0);

希望这会有所帮助。阅读 https://developer仍然建议使用 .apple.com/library/content/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_contexts/opengl_contexts.html

I worked on the shared context on OSX in these days, struggling for the absence of a checklist of thing that should be done in order to make it work. I think it's worth to share a couple of little things or keyword that can help to find out where the problem is in your case.

Advise: working with drawing API like DirectX and OpenGL without the right inspection tool (see khronos or NVidia for developer website) can be very painful. A right tool is the first thing you need.

  1. You created a new NSOpenGLContext initializing it with the same pixel format and inidicating the other context as source for sharing resources. Great!
  2. You should assign it to your NSOpenGLView using the setOpenGLContext method. (no need for update, setview or other things I saw around on the web in very old post)
    • if you've created your window using the xib files, you can use the method awakeFromNib of the NSOpenGLView class to change the default contextto the new one just created
    • the old context attached to the view will be automatically destroyed
    • any preexisitng resource in the shared context will be "imported" in the new one too.
  3. call [your_new_Context makeCurrentContext] - I did it in the awakeFormNib method
  4. (And here I think is the problem of @Duncan), you need to set all the rendering state you need. The rendering state are not shared accross context! Only the resources. Those are some of the render state you want to set (change them according to your needs):

    glEnableVertexAttribArray(pgmImagePosition_);
    glEnableVertexAttribArray(pgmImageTextureCoord_);
    glEnable(GL_TEXTURE_2D);
    glDisable(GL_DITHER);
    glDisable(GL_ALPHA_TEST);
    glDisable(GL_BLEND);
    glDisable(GL_STENCIL_TEST);
    glDisable(GL_FOG);
    glDisable(GL_DEPTH_TEST);
    glPixelZoom(1.0,1.0);
    glClearColor(0.1, 0.1, 0.1, 1.0);

Hope this may help. A reading of https://developer.apple.com/library/content/documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_contexts/opengl_contexts.html is still suggested.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文