2011-03-05 24 views
2

好的,這就是我所擁有的。我有一個1d位圖(或bitarray,bitset,bitstring,但我現在稱之爲位圖),其中包含康威生活遊戲中的活狀態或死狀態。位於(x, y)處的單元由位於y * map_width + x的位表示。渲染位圖/ bitarray到2D平面的最佳方式(使用OpenGL)

現在我有我的遊戲「引擎」工作,如果我現在可以渲染一些圖形的東西,這將是很好的。我認爲OpenGL會是一個不錯的選擇,但我不知道該如何開始,並且如果有任何特定的函數或着色器(我知道關於着色器沒有什麼),它可以高效地將位圖渲染成黑色的2d平面'n白色像素。

如果你現在認爲「不,你傻瓜opengl是不好的... ...」,隨時可以說,我願意改變。

EDIT

我忘了說,我使用的緊湊bitarray存儲每字節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); 
} 

回答

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]是兩個交替的陣列之間大小width * height(相切換的char*類型的數據陣列正被寫入分成讀取)。

因爲使用了GL_LUMINANCE,顏色將只有黑色和白色。

此外,還需要建立與此rectagle(每幀,但我想你已經知道這一點)

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內存,但只有一個四元組沒有必要。

+0

由於我存儲8位在一個字節中是否需要在將其提供給OpenGL之前將其轉換爲每字節一位或者它是否具有可以理解屏蔽存儲的模式? – orlp 2011-03-05 20:23:56

+0

@nightcracker看到這個問題我問我什麼時候做我的GoL http://stackoverflow.com/questions/327642/opengl-and-monochrome-texture – 2011-03-05 20:27:53

+0

你的問題幾乎是我的問題:)謝謝。雖然我有點擔心,因爲這會將內存使用量增加8倍。感謝上帝,我將應用程序模塊化,但我可以輕鬆更改系統。 – orlp 2011-03-05 20:32:20

0

如果你堅持使用OpenGL,最簡單的方法就是將你的位圖上傳爲紋理,然後渲染一個用該紋理映射的四元組。上載位將是這個樣子:

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

這是假定每一個細胞是單字節,與黑色的價值00xFF爲白色。請注意,在某些OpenGL版本中,widthheight必須是2的冪。

0

的OpenGL老版本提供的功能直接繪製位圖,而不需要一箇中介質地:glBitmap相比其他方法繪製圖像glBitmap是相當緩慢的,但由於人使用它僅僅微這並不壞。

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

位圖使用glRasterPosglWindowPos放置。

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

位圖有一個小陷阱:如果光柵位置使用glRasterPosglWindowPos是沒有位圖的一部分被繪製的視區之外,即使把手伸進視口設置;有關解決方法,請參閱glBitmap的參考頁面。

1

首先考慮通過在2個OpenGL紋理之間進行乒乓來在GPU上進行仿真。如果不是一些複雜的優化 - 康威的生活是一個非常簡單的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); 
} 
+0

再次閱讀我的問題:「(我知道關於着色器__nothing__」)。雖然我很樂意學習:) – orlp 2011-03-09 12:52:29

+0

@nightcracker。那將是一個很好的開始;) – kvark 2011-03-09 14:25:07

+0

任何建議? (儘管我認爲從shader開始會錯位,我可以使用basecode來工作(所以我可以編譯:D),但我甚至無法讓commanderz的片段工作)。 – orlp 2011-03-09 14:49:13