Feeds:
投稿
コメント

Archive for the ‘プログラミング雑記’ Category

まずは簡単にトライアングルを1万枚ほどレンダリングするサンプルプログラムを作ってみましょう 😀

Xcode4のOpenGL ES Applicationテンプレートに以下の変更を行います。

== EAGLView.h

@interface EAGLView : UIView {
@private
    // The pixel dimensions of the CAEAGLLayer.
    GLint framebufferWidth;
    GLint framebufferHeight;

    // The OpenGL ES names for the framebuffer and renderbuffer used to render to this view.
    GLuint defaultFramebuffer, colorRenderbuffer;

    // @fujita-y 深度バッファ用定義をここに追加
    GLuint depthRenderbuffer;
    // @fujita-y end
}

== EAGLView.m

- (void)createFramebuffer
{
    if (context && !defaultFramebuffer) {
        [EAGLContext setCurrentContext:context];

        // Create default framebuffer object.
        glGenFramebuffers(1, &defaultFramebuffer);
        glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer);

        // Create color render buffer and allocate backing store.
        glGenRenderbuffers(1, &colorRenderbuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
        [context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer *)self.layer];
        glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &framebufferWidth);
        glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &framebufferHeight);

        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRenderbuffer);

        // @fujita-y 深度バッファの作成をここに追加
        glGenRenderbuffers(1, &depthRenderbuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, framebufferWidth, framebufferHeight);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);
        // @fujita-y end

        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
            NSLog(@"Failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
    }
}

- (void)deleteFramebuffer
{
    if (context) {
        [EAGLContext setCurrentContext:context];

        if (defaultFramebuffer) {
            glDeleteFramebuffers(1, &defaultFramebuffer);
            defaultFramebuffer = 0;
        }

        if (colorRenderbuffer) {
            glDeleteRenderbuffers(1, &colorRenderbuffer);
            colorRenderbuffer = 0;
        }

        // @fujita-y 深度バッファのデリートをここに追加
        if (depthRenderbuffer) {
            glDeleteRenderbuffers(1, &depthRenderbuffer);
            depthRenderbuffer = 0;
        }
        // @fujita-y end

    }
}

== notepad_sampleViewController.h(このファイル名は作成したプロジェクトの名前+"ViewController.h"になります)

// @fujita-y GLfloatの乱数その1
static GLfloat random_zero_one() // 0.0 .. 1.0
{
    return (float)rand() / (float)RAND_MAX;
}

// @fujita-y GLfloatの乱数その2
static GLfloat random_delta() // -0.025 .. 0.025
{
    return (random_zero_one() - 0.5) * 0.5;
}

// @fujita-y drawFrameを書き換え(OpenGL ES2必須)
- (void)drawFrame
{
    [(EAGLView *)self.view setFramebuffer];

    static GLfloat *vertices;
    const int numTriangles = 10000;
    const int numVertices = numTriangles * 3;
    const int numFloats = numVertices * 3;

    // ここで GLfloat *vertices に三角板のデータを用意します。作成するのは最初の一回だけです。
    if (vertices == NULL) {
        vertices = malloc(sizeof(GLfloat) * numFloats);
        for (int i = 0; i < numTriangles; i++) {
            GLfloat cx = random_zero_one() - 0.5;
            GLfloat cy = random_zero_one() - 0.5;
            GLfloat cz = random_zero_one() - 0.5;
            // vertex 1
            vertices[i * 9 + 0] = cx + random_delta();
            vertices[i * 9 + 1] = cy + random_delta();
            vertices[i * 9 + 2] = cz + random_delta();
            // vertex 2
            vertices[i * 9 + 3] = cx + random_delta();
            vertices[i * 9 + 4] = cy + random_delta();
            vertices[i * 9 + 5] = cz + random_delta();
            // vertex 3
            vertices[i * 9 + 6] = cx + random_delta();
            vertices[i * 9 + 7] = cy + random_delta();
            vertices[i * 9 + 8] = cz + random_delta();
        }
    }

    glClearColor(0.2f, 0.1f, 0.2f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glUseProgram(program);
    glVertexAttribPointer(ATTRIB_VERTEX, 3, GL_FLOAT, 0, 0, vertices);
    glEnableVertexAttribArray(ATTRIB_VERTEX);
    glDrawArrays(GL_TRIANGLES, 0, numVertices);

    [(EAGLView *)self.view presentFramebuffer];
}

== Shader.vsh

attribute vec4 position;
varying vec4 colorVarying;

void main()
{
    gl_Position = position;
    colorVarying = abs(gl_Position);
}

で、これをiPod touch 3Gで実行するとCoreAnimationのフレームレートが30fps・・・この段階では目眩のするような遅さです・・・が、最終的には下のような1万5千トライアングルのモデルにアンチエイリアスをかけても60fpsでグリグリ回るようになるのです 🙂

[Y.FUJITA::NOTEPAD::YPSILONより転載]

Read Full Post »

さて、OpenGL ES2の性能テストをすることにしたわけですが、まずテスト用のモデルを用意しないといけません。ここでは、あまり深く考えずに「ジーラ君」を採用しました:)

「ジーラ君」とはこんなモデルですhttps://lwpinball.wordpress.com/2010/12/08/iphone/

さて「ジーラ君」はLightWave3Dで作ったモデルなので、このデータをOpenGL ES2でレンダリングできるデータに変換しないといけません。ここではBlenderを使いました。BlenderはプラグインをPythonで書く事ができる素敵仕様だからです 😀

まずBlenderのプラグインの中からWavefront .obj fileへの出力を行うものを探して、これを少し書き換えてCのstaticデータを書き出すようにします。

次にXcodeに用意されているOpenGL ES Applicationテンプレートを使ってアプリを作り、これを書き換えて「ジーラ君」がiPhoneの画面に出るようにします。この時点では色も質感も無い石膏像のような表示でしたが、かかった時間は1日ちょっと。まずは快調な滑り出しです 😉

でも、この調子が続いていたのなら12月8日の私の写真があんな小汚くならなかったんだよな~ 😦

つづく

[Y.FUJITA::NOTEPAD::YPSILONより転載]

Read Full Post »

Pinball Tristanの開発過程を思い出しながらiOSのゲーム開発について少し書いてみようと思います。

まず最初に行ったのがOpenGL ES2の性能テストです。ピンボールゲームの場合は60FPSの維持が最優先ですので、そのために3Dモデルの最適化が必要になるのですが、それにはドロップフレーム無しでデバイスが描画できるポリゴンやテクスチャの量を知りたくなるのです。最初は簡単に済むと思っていたのですが・・・これが思ったより大変でした・・・開始早々いきなり想定外 😦

つづく

[Y.FUJITA::NOTEPAD::YPSILONより転載]

Read Full Post »

プロトタイプのデザインに使うツールは人それぞれだと思いますが、私は最初の平面デザインにはPhotoshopを使っています。ちなみにパスで書かれた部分はそのまま物理エンジンへの入力データにもなります。- YFujita

Read Full Post »

Shibuya.lisp テクニカルトーク #1の発表から戻って来ました。
初回の開催とは思えないスムースな運営ですばらしいイベントでした。この記念すべき第一回にトーカーとして参加できたのは幸せなことだと感じています。

リトルウイングをご存知の方もいらっしゃって、発表の待ち時間に発表台の横のテーブルで「デスセーブ」や「バンバック」のやりかたを見せたりもしてたんですが・・・あれはピンボールを知らない方には奇妙な光景だったでしょうね ^^;

ピンボールの説明にはプロジェクターの解像度に一番マッチするモンスターフェアーを使いました。頂いた質問に「Ypsilonを組み込むことにより”逆重力”や”30マルチボール”などのカスタマイズがユーザーサイドで出来るようになります」と答えたときに会場のあちらこちらで反応を頂けたのはうれしかったですね 😀

その後の懇親会もおおいに盛り上がり楽しかったです 🙂
帰りは山手線・総武線の最終接続になりました。乗るのは久しぶりでした。
時間思い出せてよかったです(汗

Read Full Post »

イプシロンのバージョン0.9.6-update2をリリースしました。これまで見つかったすべてのバグを修正しています。

今回REPLの実装に改良を加えてemacsなどを使ったインタラクティブなTop-level programの開発が行いやすくしてみました。またバグの修正に伴いエラーメッセージなどに特殊な名前の識別子が現れて見づらくなっていたものも直しています。PLT R6RS test suite revision 11530では8931個のすべてのテストをパスしています。

– Fujita

Read Full Post »

8/30日(土)に行われるLightweight Language Futureのセッションにイプシロン(Ypsilon)の開発者として出演することになりました。

http://ll.jus.or.jp/2008/program/create

このセッションの出演者は、わたしと

  • Larry Wallさん(Perl開発者)
  • まつもとゆきひろさん(Ruby開発者)
  • 住井英二郎さん(MinCaml開発者)
  • ひげぽんさん(mosh開発者)
  • 司会の今泉貴史さん

の予定です。初めてお会いする方ばかりで楽しみです 😀

今回ウィキペディアの軽量プログラミング言語を見て初めてSchemeがLightweight Languageに分類されていることを知りました 😀

つまり、ピンボール用のドメイン固有言語を開発する目的で軽量プログラミング言語のScheme(R6RS)をリアルタイムシステム向けに実装したのがイプシロン(Ypsilon)ということですね。そしてイプシロン(Ypsilon)の実装にはマルチパラダイムプログラミング言語C++を使用していると・・・ 😛

ところで東京は久しぶりです。日曜日はピンボールを遊びに行こうと思っています。 🙂

— fujita

Read Full Post »

イプシロンのバージョン0.9.6をリリースしました。これまで見つかったすべてのバグを修正しています。またPLT R6RS test suite revision 11016(今日の時点での最新版)の8886個のすべてのテストをLinux, Windows Vista, MacOS Xでクリアしました 😀

ご協力頂いた方々にあらためて感謝いたしております m(_ _)m

R6RS test suiteのアナウンスです(PLTのMatthew Flattさんの投稿):
http://groups.google.com/group/comp.lang.scheme/browse_thread/thread/a7d691b5ca87b94f/6bb6e09f1d39d828

Ypsilon 0.9.6のアナウンスです:
http://groups.google.com/group/comp.lang.scheme/browse_thread/thread/626eb3564323c213

「Ypsilon 0.9.6 – The implementation of R6RS Scheme Programming Language for real-time applications.」は http://code.google.com/p/ypsilon/ からダウンロードすることができます。

– Fujtia

Read Full Post »

Ypsilon 0.9.5-update2をリリースしました。今回のアップデートでかなりのバグを取ることができたと思います。ご協力頂いた方々に感謝いたしております。最近アナウンスされたPLTのR6RS test suiteを動かしてみたところ、98.9%のカバー率になりました。 🙂

今回のリリースでは、とても見つけにくいコンカレントGCのバグを2つ消すことができたのが個人的には嬉しいです。これはWilliam D Clingerさんからメールで教えて頂いたR6RS Benchmarksの中のgcbenchというテストプログラムで発覚しました。御大に感謝です!:D

Ypsilon 0.9.5-update2は http://code.google.com/p/ypsilon/ からダウンロードすることができます。現在、MacOS X, Windows Vista, Linuxがサポートされています。

— Fujtia

Read Full Post »

Ypsilonのバグフィックス版をリリースしました。皆様のご協力のおかげで思ったより早く安定してきたと思います。コメントやバグレポートをお送り頂いた方々に感謝いたしております m(_ _)m

こういったソフトウエアのデバッグは一人では難しいものです。なぜならテスト用のプログラムが偏ったものになるからです。これはプログラマーがそれぞれ自分のコーディングスタイルを持っていることに起因します。「こんな使い方あったのか〜」という発見があり、そしてその中にバグが潜んでいることもしばしばです 😛

最近そんな例に関連する投稿がcomp.lang.schemeにありました。

(define (((f x) y) z) (+ x y z))

というプログラムはR6RS Schemeではエラーにしなければなりません。でも、これが使えると便利そうなんだけど・・・ そういう場合R6RSでは下記のようにポータブルに実現することができます。

(library (define+)
 (export (rename (define+ define)))
 (import (rnrs))
 (define-syntax define+
  (syntax-rules ()
   ((_ (f . args) . body)
    (define+ f (lambda args . body)))
   ((_ var val)
    (define var val)))))
(import (define+))
(define (((f x) y) z) (+ x y z))
(define g ((f 1) 2))
(g 3) ;=> 6

でも、私は自分のプログラムではこういう書き方はしません・・・で、この使い方にはバグが潜んでいたわけですね(汗
もしも私が一人でデバッグしていたら、これって何時まで潜んでいたことやら 😦

Read Full Post »

Older Posts »