Macbook视网膜显示器上的PyOpenGL

时间:2013-02-09 02:29:08

标签: python osx-lion glut retina-display pyopengl

我有一些代码在过剩窗口中使用PyOpenGL显示图形。在视网膜Macbook Pro上,此窗口以低分辨率模式显示,其中一个OpenGL像素由四个物理像素表示。如果它以完整的原始分辨率显示会更好。

我的问题
有没有办法在Retina显示器上用Python获取原生分辨率OpenGL上下文,使用过剩或其他?

问题示例
下面是PyOpenGL程序的最小工作示例。没有什么特别之处 - 任何有效的PyOpenGL代码都会展示这个问题。这是屏幕截图的放大细节。请注意,构成白色三角形的像素是OS X小部件像素大小的四倍。这是不是专门为Retina设备设计的程序的默认设置。我想知道如何为PyOpenGL程序关闭它。

enter image description here

以下是代码:

from OpenGL.GL import *
from OpenGL.GLUT import *
from OpenGL.GLU import *

import os

def initFunc():
    glDisable(GL_DEPTH_TEST)
    glClearColor(0.0, 0.0, 0.0, 0.0)
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluOrtho2D(0.0, 400.0, 0.0, 400.0)

def displayFunc():
    glClear(GL_COLOR_BUFFER_BIT)
    glColor3f(1.0, 1.0, 1.0)
    glBegin(GL_TRIANGLES)
    glVertex2f(10.0, 10.0)
    glVertex2f(10.0, 100.0)
    glVertex2f(100.0, 100.0)
    glEnd()
    glFlush()

if __name__ == '__main__':
    glutInit()
    glutInitWindowSize(400,400)
    glutCreateWindow("GL test")
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB)
    glutDisplayFunc(displayFunc)
    initFunc()
    os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "Python" to true' ''')
        # prevent GL window from appearing behind other applications
    glutMainLoop()

3 个答案:

答案 0 :(得分:5)

要正确达到您所需的分辨率,您需要使用NSView,然后指示视图应使用最佳分辨率(这也意味着您不再使用GLUT)。由于这不在OpenGL的范围之内,并且您希望使用Python,因此您需要使用一些与py2app一起访问这些对象的包(但不需要完整的py2app build)。

要根据您的需要访问NSView或更具体的NSOpenGLView,需要pyobjc。以下代码导入Cocoa(由pyobjc提供)仅为了清楚起见,可以通过AppKit访问相同的对象。代码创建NSWindow,然后创建一个视图,定义在需要时调用的drawRect。解决解决问题的单行是:view.setWantsBestResolutionOpenGLSurface_(True)

import Cocoa
from OpenGL.GL import *
from OpenGL.GLU import *

class GLView(Cocoa.NSOpenGLView):
    def initWithFrame_(self, frame):
        format = Cocoa.NSOpenGLPixelFormat.alloc().initWithAttributes_((0, ))
        view = super(GLView, self).initWithFrame_pixelFormat_(frame, format)
        view.setWantsBestResolutionOpenGLSurface_(True)

        view.openGLContext().makeCurrentContext()
        glDisable(GL_DEPTH_TEST)
        glClearColor(0.0, 0.0, 0.0, 0.0)
        glMatrixMode(GL_PROJECTION)
        glLoadIdentity()
        gluOrtho2D(0.0, 1.0, 0.0, 1.0)
        return view

    def drawRect_(self, bounds):
        glClear(GL_COLOR_BUFFER_BIT)
        glColor3f(1.0, 1.0, 1.0)
        glBegin(GL_TRIANGLES)
        glVertex2f(0.1, 0.1)
        glVertex2f(0.1, 0.9)
        glVertex2f(0.9, 0.9)
        glEnd()
        glFlush()


class AppDelegate(Cocoa.NSObject):
    def windowWillClose_(self, notification):
        app.terminate_(self)

app = Cocoa.NSApplication.sharedApplication()

rect = Cocoa.NSMakeRect(0, 0, 300, 300)
winflags = Cocoa.NSTitledWindowMask | Cocoa.NSClosableWindowMask
win = Cocoa.NSWindow.alloc().initWithContentRect_styleMask_backing_defer_(
        rect, winflags, Cocoa.NSBackingStoreBuffered, False)
delegate = AppDelegate.alloc().init()
win.setDelegate_(delegate)
view = GLView.alloc().initWithFrame_(rect)
win.setContentView_(view)
win.makeKeyAndOrderFront_(None)

app.run()

如果您尝试运行此代码,它将运行正常,但您不会注意到有关分辨率问题的任何差异。要解决这个问题,您需要构建一个简单的setup.py,假设上面的代码保存在名为test1.py的文件中:

from distutils.core import setup
import py2app
setup(app=["test1.py"])

然后运行mypythonexecutable setup.py py2app -A(当然,mypythonexecutable替换为有意义的内容,例如pythonpython2.7。现在你执行open dist/test1.app并解决问题(在执行前面的命令后将创建dist/test1.app)。

答案 1 :(得分:3)

您可以从此处获得可选择支持HiDPI的GLUT修补版本: http://iihm.imag.fr/blanch/software/glut-macosx/

如果您使用此GLUT框架,您的应用程序可能会选择以实际屏幕像素分辨率获取OpenGL上下文。 您只需要更改代码中的显示初始化(无论是C,Python / PyOpenGL还是与GLUT框架链接的任何内容):

glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE)

为:

glutInitDisplayString("rgba double hidpi")

修补版本优雅地处理具有不同后备存储比例因子的多个屏幕,并为期望以像素指定的大小或尺寸的各种函数提供一致的行为(即glutInitWindowSize, glutReshapeWindow, glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT)和光标的位置传递给事件回调)。

此版本的GLUT也完全向后兼容其他决定不选择加入HiDPI支持的应用程序。 如果您希望构建自己的版本,还会提供修补程序以及自行构建框架的说明。

如果需要,补丁版本还会添加鼠标滚轮支持。

答案 2 :(得分:1)

我猜你必须使用一些PyObjC绑定来获取Glut创建的NSWindow,然后调整比例因子。以下是Objective C部分的一些信息:http://supermegaultragroovy.com/2012/10/24/coding-for-high-resolution-on-os-x-read-this/