2

好的,这就是我所拥有的。我有一个 1d 位图(或位数组、位集、位串,但我现在称它为位图)包含来自康威生命生成游戏的活状态或死状态。at 的单元格(x, y)由 at 的位表示y * map_width + x

现在我的生活游戏“引擎”开始工作了,如果我现在可以渲染一些图形的东西就好了。我认为 OpenGL 将是一个不错的选择,但我不知道我应该如何开始,以及是否有任何特定的函数或着色器(我对着色器一无所知)可以有效地将位图渲染到具有黑色 'n 的 2d 平面白色像素。

如果您现在认为“不,您的白痴 opengl 很糟糕……”,请随意说出来,我愿意进行更改。

编辑

我忘了说我使用了一个紧凑的位数组,每个字节存储 8 位,并使用掩码来检索这些字节。这是我手工制作的图书馆东西:

#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 (正在写入和读取的两个交替数组之间的相位切换)。

因为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 内存中,但这对于只有一个四边形并不是真正必要的。

于 2011-03-05T20:16:34.267 回答
1

首先考虑通过在 2 个 OpenGL 纹理之间进行乒乓操作在 GPU 上进行模拟。如果不是一些复杂的优化 - Conway's Life 对于 GPU 来说是一项非常简单的任务。它将需要 2 个帧缓冲区对象和对着色器的一些了解。

Edit-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,最简单的方法是将您的位图作为纹理上传,然后渲染与该纹理映射的四边形。上传位看起来像这样:

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

这假定每个单元格都是一个字节,具有0黑色和0xFF白色的值。请注意,在某些 OpenGL 版本上,width必须height是 2 的幂。

于 2011-03-05T20:17:02.283 回答
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 回答