2011-10-12 86 views
18

我正在尋找轉換我的OpenGL呈現代碼以利用GLKit(即異步紋理加載和由GLKView/Controller提供的自動化)的幾個功能。但是,看起來這些類主要是爲了適應使用動畫循環渲染的人而設計的,而我正在使用按需渲染。此外,一些渲染是針對紋理,而不是GLKView的幀緩衝區,所以我應該只是尋找GLKView的子類並添加其他FBO?使用GLKit的按需OpenGL ES呈現

是否有這種設置的建議方法?我希望沿着線的東西:

  • 設置視圖控制器的preferredFramesPerSecond0,或者只是 暫停幀更新?
  • 忽略glkViewControllerUpdateglkView:drawInRect:方法 只需繪製我所需要的,當我需要它時。
  • 使用視圖的爲了 顯示幀setNeedsDisplay與通常的UIView(做我需要調用bindDrawable因爲我 將被渲染到紋理呢?)。

如果這不是新API的設計目標,那麼這可能是不值得的。我希望文檔比現在更徹底。也許,當API已經「成熟」一點......

感謝

+0

您仍然可以與GLKit一起渲染到第二個FBO。 http://mickyd.wordpress.com/2012/05/20/creating-render-to-texture-secondary-framebuffer-objects-on-ios-using-opengl-es-2/ – MickyD

回答

22

我最終使用的方法是不打擾GLKViewController,但直接使用GLKView直接在UIViewController子類下。

顯然,GLKViewController適用於需要爲應用程序(如遊戲)提供一致渲染循環的用戶。沒有它,繪製到GLKView就像調用[glkView setNeedsDisplay]一樣簡單。請確保將enableSetNeedsDisplay設置爲YES以啓用此行爲。

如果你是仍想利用一個GLKViewController的,你可以在viewWillAppear禁用動畫渲染循環,像這樣:

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; // setPaused automatically set to NO in super's implementation 

    [self setPaused:YES]; 
} 

此外,設置resumeOnDidBecomeActiveNO防止視圖控制器從自動再次恢復。

然而,使用帶有GLKView的普通UIViewController是完全可以接受的,而且我已經看到它被蘋果工程師推薦爲執行按需繪製的適當方式。

+0

如果您能澄清哪些方法enableSetNeedsDisplay和resumeOnDidBecomeActive需要如上所述進行設置,將會有所幫助,因爲您沒有將它們置於viewWillAppear(BOOL)動畫中。謝謝。 –

+0

創建視圖/視圖控制器時設置這些屬性。例如,如果你在代碼中創建了'GLKViewController',可能會在你的'alloc' /'init'後面設置它。如果你在界面構建器中創建它,那麼在視圖控制器中實現'-awakeFromNib'方法可能是一個好的選擇。一般而言,像這樣的屬性應該在/創建對象之後但在使用之前設置。 – Stuart

+0

您是否有可用的開源代碼顯示此示例?謝謝 – aehlke

3

我只是轉換我的代碼使用EAGLContext經理,我自己滾使用GLKit類的更多樣本將被提供。

你建議你可以「......修改.. glkView:drawInRect:方法,並在需要時畫出你需要的東西」。這在性能方面似乎是一個明智的選擇;我假設(雖然沒有嘗試過),如果你只是沒有指定GLKViewDelegate或提供GLKView的子類別drawInRect:定義,則不會發生動畫循環渲染。你有嘗試過嗎?

另一種方法是簡單地創建一些@property (assign, nonatomic) BOOL shouldUpdate;MyController : GLKViewController <GLKViewDelegate>類只會更新,如果有事可做:

[self setDelegate:self]; // in init or awakeFromNib or other.. 

-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect { 
    if ([self shouldUpdate]) { ... 

我敢肯定你的想法,它幾乎不複雜。

值得一提的一件事:官方API文檔聲明viewDidLoad應該用於您的初始GL設置的GLKViewController。我有這個問題;由於某種原因,我的glCreateShader調用始終返回零。這可能是由於我在初始化後設置了EAGLContext;自從我在Storyboard中創建控制器後,我無法將其作爲參數init傳遞。但是,代碼沒有任何邏輯錯誤,所以如果遇到類似問題,我會提供這個友好的警告。我的解決辦法很簡單,就是在我drawInRect如下:

-(void)glkView:(GLKView *)view drawInRect:(CGRect)rect { 
    if ([self initialGLSetupDone] == NO) { 
     [self beforeFirstRender]; 
     [self setInitialGLSetupDone:YES]; 
    } 
    // .. rest of render code goes here. 
} 

顯然,這是不理想有一個IF中有不必要的,但它是一個簡單的解決方案。

如果您嘗試更新以使用GLKit,請告訴我。

+0

關於'viewDidLoad'問題,您必須在創建着色器之前設置'EAGLContext',正如您注意到的那樣。在設置GL代碼的其餘部分之前,在'viewDidLoad'中也可以做到這一點。看看Xcode中的'OpenGL Game'模板項目,瞭解如何執行此設置的一個很好的例子。 – Stuart

+0

感謝您的閂鎖提示。比試圖手動繪製CAEAGLLayer或其他解決方法要容易得多。 –

1

您創建GLKView後,加入這一行:

glkView.enableSetNeedsDisplay = TRUE;

(正因爲如此,沒有人會重繪自動視圖)

當你要重新繪製,插入此行:

[glkView setNeedsDisplay]; 

...然後drawInRect例程將只被調用一次。

希望它有幫助。

+1

-1。這是不正確的 - 將'enableSetNeedsDisplay'設置爲'NO' **禁用**'GLKView''setNeedsDisplay'方法。當使用GLKViewController時,這個屬性會自動設置爲NO,因此,在setNeedsDisplay「mode」中繪製時,您需要手動將其設置爲「YES」。 – Stuart

+1

更正了此回覆... – rodamn

相關問題