2013-02-09 82 views
4

我有一些代碼在超過窗口中使用PyOpenGL顯示圖形。在視網膜Macbook Pro上,此窗口以低分辨率模式顯示,其中一個OpenGL像素由四個物理像素表示。如果它能夠以完整的原始分辨率顯示,會更好。MacOne視網膜顯示屏上的PyOpenGL

我的問題
有什麼辦法獲得Python中的Retina顯示屏的原始分辨率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() 
+0

你或許應該張貼一些代碼。 – djc 2013-02-11 10:06:01

+0

你以後在https://developer.apple.com/library/mac/#documentation/GraphicsAnimation/Conceptual/HighResolutionOSX/Introduction/Introduction.html在http://developer.apple.com證明什麼,更直接/library/mac/#documentation/graphicsimaging/conceptual/opengl-macprogguide/EnablingOpenGLforHighResolution/EnablingOpenGLforHighResolution.html。現在你需要將它映射到Python。 – mmgp 2013-02-14 14:29:18

+0

@Nathaniel所以問題是另一回事。它似乎並不像你都知道是需要什麼的,現在你做的僅僅是知道如何使用'所獲得NSOpenGLView'的事'從AppKit的進口NSOpenGLView'。 – mmgp 2013-02-14 14:47:31

回答

3

要正確實現您所處的分辨率,您需要使用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是由一些有意義像python或更換例如,python2.7)。現在你做了open dist/test1.app並且問題解決了(dist/test1.app將在更早的命令執行後被創建)。如果您使用此GLUT框架,您的應用程序可以選擇在對獲得的真正的屏幕像素分辨率的OpenGL上下文 http://iihm.imag.fr/blanch/software/glut-macosx/

+0

這看起來不錯。我已經授予您賞金,並且一旦我有機會測試它,我們將接受答案。 – Nathaniel 2013-02-17 06:18:45

+0

因此,在長時間的實際工作分心之後,我終於有機會嘗試了這一點。不幸的是,儘管'python test1.py'運行良好(但是分辨率很低),當執行'open dist/test1.app'的時候,我得到了一個與oh-so-useful錯誤「test1 Error」對話的對話框。有一個選項可以打開控制檯,但就我所見,控制檯日誌中沒有任何python。 – Nathaniel 2013-06-14 04:31:13

3

你可以得到GLUT的補丁版本,可選支持HiDPI從這裏開始。 你只需要改變顯示初始化代碼中的(無論是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支持。 如果您更願意構建自己的版本,還會提供補丁以及自行構建框架的說明。

打過補丁的版本還增加了鼠標滾輪支持,如果您需要它。