2

わかりました、これは私が持っているものです。ライフ生成のコンウェイ ゲームからのライブ状態またはデッド状態を含む 1 次元ビットマップ (またはビット配列、ビットセット、ビット文字列ですが、今はビットマップと呼びます) があります。のセル(x, y)はビット at で表されy * map_width + xます。

これで、人生ゲームの「エンジン」が動作するようになりました。グラフィカルなものをレンダリングできればいいのですが。これには OpenGL が適していると思いましたが、どのように開始すればよいか、ビットマップを黒の 'n白いピクセル。

もしあなたが今、「馬鹿なopenglはダメだ...」と思っているなら、遠慮なく言ってください。私は変更を受け入れます。

編集

1 バイトあたり 8 ビットを格納するコンパクトな bitarray を使用し、マスキングを使用してそれらのバイトを取得することを忘れていました。これは私の手作りのライブラリです。

#include <stdint.h> // uint32_t
#include <stdlib.h> // malloc()
#include <string.h> // memset()
#include <limits.h> // CHAR_BIT

typedef uint32_t word_t;
enum {
    WORD_SIZE = sizeof(word_t), // size of one word in bytes
    BITS_PER_WORD = sizeof(word_t) * CHAR_BIT, // size of one word in bits
    MAX_WORD_VALUE = UINT32_MAX // max value of one word
};

typedef struct {
    word_t *words;
    int nwords;
    int nbytes;
} bitmap_t;

inline int WORD_OFFSET(int b) { return b / BITS_PER_WORD; }
inline int BIT_OFFSET(int b) { return b % BITS_PER_WORD; }

inline void setbit(bitmap_t bitmap, int n) { bitmap.words[WORD_OFFSET(n)] |= (1 << BIT_OFFSET(n)); }
inline void flipbit(bitmap_t bitmap, int n) { bitmap.words[WORD_OFFSET(n)] ^= (1 << BIT_OFFSET(n)); }
inline void clearbit(bitmap_t bitmap, int n) { bitmap.words[WORD_OFFSET(n)] &= ~(1 << BIT_OFFSET(n)); }
inline int getbit(bitmap_t bitmap, int n) { return (bitmap.words[WORD_OFFSET(n)] & (1 << BIT_OFFSET(n))) != 0; }

inline void clearall(bitmap_t bitmap) {
    int i;
    for (i = bitmap.nwords - 1; i >= 0; i--) {
        bitmap.words[i] = 0;
    }
}

inline void setall(bitmap_t bitmap) {
    int i;
    for (i = bitmap.nwords - 1; i >= 0; i--) {
        bitmap.words[i] = MAX_WORD_VALUE;
    }
}

bitmap_t bitmap_create(int nbits) {
    bitmap_t bitmap;
    bitmap.nwords = nbits / BITS_PER_WORD + 1;
    bitmap.nbytes = bitmap.nwords * WORD_SIZE;
    bitmap.words = malloc(bitmap.nbytes);

    if (bitmap.words == NULL) { // could not allocate memory
        printf("ERROR: Could not allocate (enough) memory.");
        exit(1);
    }

    clearall(bitmap);
    return bitmap;
}

void bitmap_free(bitmap_t bitmap) {
    free(bitmap.words);
}
4

4 に答える 4

2

これは私の OGL Game of Life 実装のコードです。

これにより、テクスチャがアップロードされます (データを更新するたびにこれを行います)。

glTexImage2D( GL_TEXTURE_2D, 0, 1, game->width, game->height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, game->culture[game->phase] );

game->culture[phase]char*サイズのタイプのデータ配列ですwidth * height (フェーズは、書き込まれている 2 つの交互の配列と読み取られている配列の間でトグルします)。

中古のためGL_LUMINANCE、カラーは白黒のみとなります。

また、これで四角形を設定する必要があります(すべてのフレームですが、これはすでに知っていると思います)

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);


    glBegin(GL_QUADS);                                  // Draw A Quad
        glVertex3f(-1.0f, 1.0f, 0.0f);                  // Top Left
        glTexCoord2i( 1, 0 );
        glVertex3f( 1.0f, 1.0f, 0.0f);                  // Top Right
        glTexCoord2i( 1, 1 );
        glVertex3f( 1.0f,-1.0f, 0.0f);                  // Bottom Right
        glTexCoord2i( 0, 1 );
        glVertex3f(-1.0f,-1.0f, 0.0f);                  // Bottom Left
        glTexCoord2i( 0, 0 );
    glEnd();

もちろん、バッファを使用して「モデル」を GPU メモリに保持することもできますが、クワッドが 1 つしかない場合は、実際には必要ありません。

于 2011-03-05T20:16:34.267 に答える
1

まず、2つのOpenGLテクスチャ間でピンポンすることにより、GPUでシミュレーション自体を実行することを検討してください。複雑な最適化ではないにしても、Conway'sLifeはGPUにとって非常に簡単なタスクです。2つのフレームバッファオブジェクトとシェーダーのある程度の理解が必要になります。

編集-1:フラグメントシェーダーの例(ブレインコンパイル済み)

#version 130
uniform sampler2D input;
out float life;
void main() {
    ivec2 tc = ivec2(gl_FragCoord);
    float orig = texelFetch(input,tc,0);
    float sum = orig+
        texelFetchOffset(input,tc,0,ivec2(-1,0))+
        texelFetchOffset(input,tc,0,ivec2(+1,0))+
        texelFetchOffset(input,tc,0,ivec2(0,-1))+
        texelFetchOffset(input,tc,0,ivec2(0,+1))+
        texelFetchOffset(input,tc,0,ivec2(-1,-1))+
        texelFetchOffset(input,tc,0,ivec2(-1,+1))+
        texelFetchOffset(input,tc,0,ivec2(+1,-1))+
        texelFetchOffset(input,tc,0,ivec2(+1,+1));
    if(sum<1.9f)
        life = 0.0f;
    else if(sum<2.1f)
        life = orig;
    else life = 1.0f;
}

頂点シェーダーは単純なパススルーです。

#version 130
in vec2 vertex;
void main() {
   gl_Position = vec4(vertex,0.0,1.0);
}
于 2011-03-06T21:25:47.723 に答える
0

古いバージョンの OpenGL は、中間テクスチャを必要とせずにビットマップを直接描画する機能を提供します。glBitmap画像を描画する他の方法と比較するとglBitmap、かなり遅いですが、控えめにしか使用しないため、それほど悪くはありません。

http://www.opengl.org/sdk/docs/man/xhtml/glBitmap.xml

glRasterPosビットマップはまたはを使用して配置されglWindowPosます。

http://www.opengl.org/sdk/docs/man/xhtml/glRasterPos.xml http://www.opengl.org/sdk/docs/man/xhtml/glWindowPos.xml

ビットマップには小さな落とし穴があります。glRasterPosまたはを使用して設定されたラスター位置glWindowPosがビューポートの外側にある場合、ビットマップがビューポートに到達したとしても、ビットマップのどの部分も描画されません。回避策については、 のリファレンス ページを参照glBitmapしてください。

于 2011-03-06T00:34:37.990 に答える
0

OpenGL を使用する場合、最も簡単な方法は、ビットマップをテクスチャとしてアップロードし、そのテクスチャでマップされたクワッドをレンダリングすることです。アップロード ビットは次のようになります。

glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, data);

0これは、すべてのセルが 1 バイトであり、値が黒と白であることを前提としています0xFF。一部の OpenGL バージョンでは、widthheightは 2 の累乗でなければならないことに注意してください。

于 2011-03-05T20:17:02.283 に答える