【问题标题】:How can I programmatically render fullscreen openGL at a specific resolution?如何以特定分辨率以编程方式呈现全屏 openGL?
【发布时间】:2013-08-30 08:29:21
【问题描述】:

我正在开发一个 OSX/Cocoa 图形应用程序(出于性能原因),当用户选择“全屏”模式时,我希望以 640x480 的分辨率进行渲染。值得一提的是,内容是使用 openGL 绘制的自定义 NSView。

我了解,与其实际更改用户的分辨率,不如更改后缓冲区(如此处另一个 SO 问题所述:Programmatically change resolution OS X)。

根据该建议,我最终使用以下两种方法(见下文)在全屏和窗口之间切换。问题是,当我全屏显示时,内容确实以 640x480 渲染但没有缩放(IE 看起来好像我们停留在窗口的分辨率并“放大”到渲染的 640x480 角落)。

我可能在这里遗漏了一些明显的东西 - 我想我可以根据实际的屏幕分辨率将渲染转换为“居中”它,但这似乎过于复杂?

- (void)goFullscreen{

  // Bounce if we're already fullscreen
  if(_isFullscreen){return;}

  // Save original size and position
  NSRect frame = [self.window.contentView frame];
  original_size = frame.size;
  original_position = frame.origin;

  NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                         [NSNumber numberWithBool:NO],NSFullScreenModeAllScreens,
                         nil];

  // In lieu of changing resolution, we set the backbuffer to 640x480
  GLint dim[2] = {640, 480};
  CGLSetParameter([[self openGLContext] CGLContextObj], kCGLCPSurfaceBackingSize, dim);
  CGLEnable ([[self openGLContext] CGLContextObj], kCGLCESurfaceBackingSize);

  // Go fullscreen!
  [self enterFullScreenMode:[NSScreen mainScreen] withOptions:options];
  _isFullscreen=true;

}


- (void)goWindowed{

  // Bounce if we're already windowed
  if(!_isFullscreen){return;}

  // Reset backbuffer
  GLint dim[2] = {original_size.width, original_size.height};
  CGLSetParameter([[self openGLContext] CGLContextObj], kCGLCPSurfaceBackingSize, dim);
  CGLEnable ([[self openGLContext] CGLContextObj], kCGLCESurfaceBackingSize);

  // Go windowed!
  [self exitFullScreenModeWithOptions:nil];
  [self.window makeFirstResponder:self];
  _isFullscreen=false;

}

更新

现在做一些类似于以下 datenwolf 建议的事情,但不使用 openGL(对非 gl 内容有用)。

// Render into a specific size
renderDimensions = NSMakeSize(640, 480);
NSImage *drawIntoImage = [[NSImage alloc] initWithSize:renderDimensions];
[drawIntoImage lockFocus];
[self drawViewOfSize:renderDimensions];
[drawIntoImage unlockFocus];
[self syphonSendImage:drawIntoImage];

// Resize to fit preview area and draw
NSSize newSize = NSMakeSize(self.frame.size.width, self.frame.size.height);
[drawIntoImage setSize: newSize];
[[NSColor blackColor] set];

[self lockFocus];
[NSBezierPath fillRect:self.frame];
[drawIntoImage drawAtPoint:NSZeroPoint fromRect:self.frame operation:NSCompositeCopy fraction:1];
[self unlockFocus];

【问题讨论】:

    标签: macos cocoa opengl


    【解决方案1】:

    使用附加了所需目标分辨率的纹理的 FBO,并以所述分辨率渲染到该 FBO/纹理。然后切换到主帧缓冲区并使用之前渲染的纹理绘制一个全屏四边形。使用您最喜欢的任何放大滤镜。如果你想拿出大炮,你可以在片段着色器中实现一个 Lancosz / sinc 插值器来放大中间纹理。

    【讨论】:

    • 这几乎肯定会起作用,并且它确实回答了书面问题(谢谢)。我现在可能会以这种方式解决我的问题(并接受答案),但我想把这个问题留得更久一点,以防其他人想参与进来。我认为理想情况下我更愿意 1. 理解为什么后缓冲解决方案无法正常工作,并且 2. 能够以“可可方式”执行此操作,因此我可以在另一个使用 CG 而不是 GL 的相关项目中使用它。
    • 我用一个例子更新了这个问题,说明如何在可可中做功能等效的事情(对非 GL 内容有用)。它工作得很好,但有点慢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多