cocos2dのEAGLViewを透明化して、背景をカメラにする方法

はじめまして、cocos2d Advent Calendar 2011に参加させていただいてます、@kasajeiです。

5日目、@Seasonsさんからのバトンタッチで6日目を担当させて頂きます。前日の記事はこちらです。
cocos2dで非同期画像読み込みを超絶簡単に実装するCCResourceAsyncLoaderの紹介

僕はcocos2d歴はちょうど1.0vが出た時ぐらいなので、それほど長くはない新参者ですが、よろしくお願いします。

では早速EAGLViewを透明化して、背景をカメラにする方法を紹介したいと思います(「いつ使うんだ」というツッコミはなしで。。)

コードはすべて、GitHubのここに置いてありますので、ご自由にどうぞ。

cocos2dプロジェクトを作り縦向きに

まず、cocos2dプロジェクトを作りましょう。「alphaGLView」と命名しました。

さて、カメラが背景ということで、なんとなく縦向きに。

#if defined(__ARM_NEON__) || TARGET_IPHONE_SIMULATOR
#define GAME_AUTOROTATION kGameAutorotationNone // kGameAutorotationUIViewControllerから変更した
#if GAME_AUTOROTATION == kGameAutorotationUIViewController
	[director setDeviceOrientation:kCCDeviceOrientationPortrait];
#else
	[director setDeviceOrientation:kCCDeviceOrientationPortrait]; // LandscapeLeftから変更した
#endif

これで実行すると縦向きになりますね。

CameraViewControllerを作る

RootViewControllerにカメラの記述を書いてもいいのですが、あまり汚したくないのでCameraViewControllerを別に作ることにします。

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
@interface CameraViewController : UIViewController
{
    AVCaptureSession *_captureSession;
    AVCaptureStillImageOutput *_imageOutput;
}
@end
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {

        // Custom initialization
        _captureSession = [[AVCaptureSession alloc] init];
        AVCaptureDevice *videoCaptureDevice = nil;
        NSArray *cameraArray = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
        for (AVCaptureDevice *camera in cameraArray) {
            if (camera.position == AVCaptureDevicePositionBack) {
                videoCaptureDevice = camera;
            }
        }
        NSError *error = nil;
        AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoCaptureDevice error:&error];
        if (videoInput) {
            [_captureSession addInput:videoInput];
            [_captureSession beginConfiguration];
            _captureSession.sessionPreset = AVCaptureSessionPresetHigh;
            [_captureSession commitConfiguration];

            AVCaptureVideoPreviewLayer *previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_captureSession];
            previewLayer.automaticallyAdjustsMirroring = NO;
            previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
            previewLayer.frame = self.view.bounds;
            [self.view.layer insertSublayer:previewLayer atIndex:0];
        }else {
            // Handle the failure.
            NSLog(@"ERROR:%@", error);
        }

        _imageOutput = [[AVCaptureStillImageOutput alloc] init];
        [_captureSession addOutput:_imageOutput];
        for(AVCaptureConnection *connection in _imageOutput.connections){
            if (connection.supportsVideoOrientation) {
                //データの向きを横向きにする
                connection.videoOrientation = AVCaptureVideoOrientationPortrait;
            }
        }

        // キャプチャセッションを開始
        [_captureSession startRunning];
    }
    return self;
}

これで、CameraViewControllerのviewをaddSubViewすればカメラのプレビューが表示される状態になりました。

EAGLViewを透明化できるように設定する

まずはEAGLViewのpixelFormatをアルファを扱えるようにしましょう。RGB565からRGBA8にします。ただしこうすることによって使用メモリが増えてしまい、60fpsでは動かなくなってしまうので、30fpsぐらいに設定します。

EAGLView *glView = [EAGLView viewWithFrame:[window bounds] pixelFormat:kEAGLColorFormatRGBA8 depthFormat:0];

// 追加
CAEAGLLayer *layer = (CAEAGLLayer*)glView.layer;
layer.opaque = NO;

fpsを30にする。

[director setAnimationInterval:1.0/30]; // kEAGLColorFormatRGBA8に設定したのでfpsは30ぐらいにしておく
[director setDisplayFPS:YES];

RootViewControllerのviewにCameraViewControllerとEAGLViewを載せる

cocos2dの初期設定ではRootViewControllerのviewにEAGLViewが設定されています。

[viewController setView:glView];

つまり、RootViewController.viewがEAGLViewになってる状態です。これでは今回都合がわるいので、RootViewControllerのviewの上に、CameraViewController.viewとEAGLViewをのせようと思います。

上のほうで#import “CameraViewController.h”をお忘れなく。

// CameraViewController
CameraViewController *cameraViewController = [[CameraViewController alloc] init];
[viewController.view addSubview:cameraViewController.view];

// make the OpenGLView a child of the view controller
// [viewController setView:glView]; // viewControllerのviewをglViewにしている(今回はコメントアウト)
[viewController.view addSubview:glView]; // addSubViewでviewControllerのviewの上に載せることにする

HelloWorldLayerを透明化する

あとはHelloWorldLayerの初期化メソッドで透明化すればオッケー。

-(id) init
{
	// always call "super" init
	// Apple recommends to re-assign "self" with the "super" return value
	if( (self=[super init])) {
        // 背景を透明に
        glClearColor(0, 0, 0, 0);

		// create and initialize a Label
		CCLabelTTF *label = [CCLabelTTF labelWithString:@"Hello World" fontName:@"Marker Felt" fontSize:64];

		// ask director the the window size
		CGSize size = [[CCDirector sharedDirector] winSize];

		// position the label on the center of the screen
		label.position =  ccp( size.width /2 , size.height/2 );

		// add the label as a child to this Layer
		[self addChild: label];
	}
	return self;
}

実行!

これで、実行すると背景がカメラになっており、その上にHello Worldと表示されていると思います!

次のカレンダー

7日目の@hmbrwさんの記事はこちら。
FacebookのOAuth認証のライブラリ「Facebook Connect」をcocos2dで使用する方法(サンプル付き)

それでは、ありがとうございました!

Facebookでコメントをどうぞ。


cocos2dのEAGLViewを透明化して、背景をカメラにする方法” への1件のコメント

  1. ピンバック: lab » Blog Archive » FacebookのOAuth認証のライブラリ「Facebook Connect」をcocos2dで使用する方法(サンプル付き)

コメントをどうぞ

コメントをどうぞ

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>