2011-10-12 44 views
18

Tôi đang xem xét chuyển đổi mã kết xuất OpenGL của mình để tận dụng một số tính năng của GLKit (cụ thể là tải kết cấu không đồng bộ và tự động được cung cấp bởi GLKView/Controller). Tuy nhiên, có vẻ như các lớp được thiết kế chủ yếu để phù hợp với mọi người bằng cách sử dụng vòng lặp hoạt ảnh, trong khi tôi đang làm việc với kết xuất theo yêu cầu. Ngoài ra, một số rendering là một kết cấu chứ không phải là framebuffer của GLKView, vì vậy tôi nên tìm cách chỉ phân lớp GLKView và thêm FBO bổ sung?Hiển thị OpenGL ES theo yêu cầu sử dụng GLKit

Có cách tiếp cận được khuyến nghị cho loại thiết lập này không? Tôi mong chờ một cái gì đó dọc theo dòng:

  • Đặt điều khiển quan điểm của preferredFramesPerSecond-0, hoặc chỉ tạm dừng cập nhật khung?
  • Bỏ qua các phương pháp glkViewControllerUpdate hoặc glkView:drawInRect: và chỉ vẽ những gì tôi cần, khi tôi cần.
  • Sử dụng của xem setNeedsDisplay như với một bình thường UIView để để hiển thị khung (sao tôi cần phải gọi bindDrawable cho rằng tôi sẽ được render với một kết cấu không?).

Có lẽ nó không đáng để thử nếu đây không phải là API mới được thiết kế để làm gì? Tôi muốn tài liệu hướng dẫn kỹ hơn một chút. Có lẽ nhiều mẫu sẽ được cung cấp khi API đã 'trưởng thành' một chút ...

Cảm ơn

+0

bạn vẫn có thể hiển thị với FBO thứ cấp cùng với GLKit. http://mickyd.wordpress.com/2012/05/20/creating-render-to-texture-secondary-framebuffer-objects-on-ios-using-opengl-es-2/ – MickyD

Trả lời

22

Cách tiếp cận mà tôi đã sử dụng là không bận tâm với số GLKViewController, nhưng chỉ sử dụng GLKView ngay dưới lớp con UIViewController.

Rõ ràng, GLKViewController được thiết kế để sử dụng cho những người cần vòng lặp hiển thị nhất quán cho các ứng dụng như trò chơi. Nếu không có nó, vẽ đến GLKView cũng đơn giản như gọi số [glkView setNeedsDisplay]. Hãy chắc chắn đặt enableSetNeedsDisplay thành YES để kích hoạt hành vi này.

Nếu bạn vẫn muốn sử dụng một GLKViewController, bạn có thể vô hiệu hóa các hoạt hình render vòng lặp trong viewWillAppear như vậy:

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

    [self setPaused:YES]; 
} 

Ngoài ra, thiết resumeOnDidBecomeActive-NO để ngăn chặn bộ điều khiển nhìn từ khôi phục lại tự động .

Sử dụng đồng bằng UIViewController với GLKView là hoàn toàn có thể chấp nhận được, và tôi đã thấy kỹ sư Apple khuyên dùng như là một cách thích hợp để thực hiện vẽ theo yêu cầu.

+0

Nó sẽ giúp nếu bạn có thể làm rõ trong đó phương pháp enableSetNeedsDisplay và resumeOnDidBecomeActive cần phải được thiết lập như đã đề cập, vì bạn không đặt chúng trong hoạt ảnh viewWillAppear (BOOL). Cảm ơn. –

+0

Đặt các thuộc tính này khi bạn tạo bộ điều khiển chế độ xem/chế độ xem. Ví dụ, nếu bạn tạo 'GLKViewController' trong mã, có thể đặt nó trên dòng sau' alloc'/'init' của bạn. Nếu bạn tạo nó trong trình xây dựng giao diện, thì việc thực hiện phương thức '-awakeFromNib' trong bộ điều khiển khung nhìn của bạn có thể là một nơi tốt cho nó. Nói chung, các thuộc tính như thế này nên được đặt sau/khi đối tượng được tạo nhưng trước khi nó được sử dụng. – Stuart

+0

Bạn có sẵn mã nguồn mở để hiển thị mẫu này không? Cảm ơn – aehlke

3

Tôi vừa mới chuyển đổi mã của tôi từ việc sử dụng một trình quản lý EAGLContext Tôi cuộn mình để sử dụng các lớp GLKit.

Bạn đề nghị bạn có thể "..đăng nhập .. glkView:drawInRect: phương pháp và chỉ cần vẽ những gì [bạn cần, khi tôi cần nó". Điều này có vẻ như một lựa chọn hợp lý hiệu suất-khôn ngoan; Tôi giả sử (mặc dù chưa thử) nếu bạn chỉ đơn giản là không chỉ định một GLKViewDelegate hoặc cung cấp một phân lớp GLKView với drawInRect: được xác định sau đó sẽ không hiển thị vòng lặp hoạt ảnh nào xảy ra. Bạn đã thử điều này chưa?

Việc thay thế sẽ chỉ đơn giản là tạo ra một số @property (assign, nonatomic) BOOL shouldUpdate; trong lớp MyController : GLKViewController <GLKViewDelegate> của bạn mà sẽ chỉ cập nhật nếu có cái gì đó để làm:

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

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

tôi chắc chắn bạn sẽ có được ý tưởng, nó hầu như không phức tạp.

Một điều đáng nhắc đến: tài liệu API chính thức nêu rõ rằng viewDidLoad nên được sử dụng trong GLKViewController để thiết lập GL ban đầu. Tôi đã có vấn đề với điều này; vì một số lý do, các cuộc gọi glCreateShader của tôi luôn trả về 0. Điều này có thể là do cài đặt của tôi EAGLContext sau khi khởi tạo; Tôi không thể chuyển nó thành thông số init vì tôi đã tạo bộ điều khiển trong Bảng phân cảnh. Tuy nhiên, không có gì sai về mặt logic với mã, vì vậy tôi đưa ra cảnh báo thân thiện này trong trường hợp bạn gặp phải sự cố tương tự. Giải pháp của tôi chỉ đơn giản là để có những điều sau đây trong drawInRect tôi:

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

Rõ ràng nó không phải là lý tưởng để có một IF trong đó không cần thiết, nhưng đó là một giải pháp dễ dàng.

Hãy cho tôi biết làm thế nào nó đi nếu bạn cố gắng cập nhật để sử dụng GLKit.

+0

Liên quan đến 'viewDidLoad' vấn đề, 'EAGLContext' của bạn phải được thiết lập trước khi tạo ra các shaders của bạn, như bạn nhận thấy chính mình. Không có hại trong việc làm điều này trong 'viewDidLoad' quá, trực tiếp trước khi bạn thiết lập phần còn lại của mã GL của bạn. Hãy xem dự án mẫu 'OpenGL Game' trong Xcode để biết ví dụ về cách thực hiện thiết lập này. – Stuart

+0

Cảm ơn lời khuyên về chốt. Dễ dàng hơn nhiều so với cố gắng vẽ thủ công CAEAGLLayer hoặc các cách giải quyết khác. –

1

Sau khi bạn đã tạo ra GLKView, thêm dòng này:

glkView.enableSetNeedsDisplay = TRUE;

(Bởi vì điều này, không ai sẽ vẽ lại quan điểm tự động)

Khi bạn muốn vẽ lại, chèn dòng này:

[glkView setNeedsDisplay]; 

... sau đó drawInRect thường lệ sẽ chỉ được gọi một lần.

Hy vọng điều đó sẽ hữu ích.

+1

-1. Điều này là không chính xác - thiết lập 'enableSetNeedsDisplay' thành' NO' ** vô hiệu hóa ** 'phương thức' setNeedsDisplay' của GLKView'. Thuộc tính này được tự động đặt thành 'NO' khi sử dụng một' GLKViewController', và do đó, trên thực tế, _required_ bạn tự đặt nó thành 'YES' khi vẽ trong setNeedsDisplay" mode ". – Stuart

+1

Sửa trả lời này ... – rodamn

Các vấn đề liên quan