揭秘OpenGL红宝书中棋盘生成程序(一)

2014-11-24 12:08:21 · 作者: · 浏览: 0

OpenGL红宝书中在内存中生成图像时,多次提到了一个生成黑白棋盘的例子。相关代码如下:
[cpp]
#define checkImageWidth 64
#define checkImageHeight 64
GLubyte checkImage[checkImageWidth][checkImageHeight][3];

......

void makeCheckImage(void)
{
int i, j, c;

for (i = 0; i < checkImageHeight; i++) {
for (j = 0; j < checkImageWidth; j++) {
c = ((((i & 0x8) == 0) ^ ((j & 0x8)) == 0)) * 255;
checkImage[i][j][0] = (GLubyte) c;
checkImage[i][j][1] = (GLubyte) c;
checkImage[i][j][2] = (GLubyte) c;
}
}
}

......

void display()
{
......
glDrawPixels(checkImageWidth, checkImageHeight, GL_RGB, GL_UNSIGNED_BYTE, checkImage);
......
}
checkImage的类型为GLubyte,对应于unsigned char,是8位的无符号整数,使用1字节来表示颜色的RGB值。
R: {1 1 1 1 1 1 1 1}
G: {0 0 0 0 0 0 0 0}
B: {1 1 1 1 1 1 1 1}
数组在内存中二进制的表示:

第1列 第2列 第64列
第1行 {1 1 1 1 1 1 1 1} {1 1 1 1 1 1 1 1} {1 1 1 1 1 1 1 1} {1 1 1 1 1 1 1 1} …… {0 0 0 0 0 0 0 0}
第2行 {0 0 0 0 0 0 0 0} {0 0 0 0 0 0 0 0} {0 0 0 0 0 0 0 0} {0 0 0 0 0 0 0 0} …… {1 1 1 1 1 1 1 1}
第3行 {1 1 1 1 1 1 1 1} {1 1 1 1 1 1 1 1} {1 1 1 1 1 1 1 1} {1 1 1 1 1 1 1 1} …… {0 0 0 0 0 0 0 0}

……

第64行 ……

下面看数组间的规律。

checkImage[0][0][0] = 0, checkImage[0][0][1] = 0, checkImage[0][0][2] = 0
checkImage[0][1][0] = 0, checkImage[0][1][1] = 0, checkImage[0][1][2] = 0
checkImage[0][2][0] = 0, checkImage[0][2][1] = 0, checkImage[0][2][2] = 0
checkImage[0][3][0] = 0, checkImage[0][3][1] = 0, checkImage[0][3][2] = 0
checkImage[0][4][0] = 0, checkImage[0][4][1] = 0, checkImage[0][4][2] = 0
checkImage[0][5][0] = 0, checkImage[0][5][1] = 0, checkImage[0][5][2] = 0
checkImage[0][6][0] = 0, checkImage[0][6][1] = 0, checkImage[0][6][2] = 0
checkImage[0][7][0] = 0, checkImage[0][7][1] = 0, checkImage[0][7][2] = 0

checkImage[0][8][0] = FF, checkImage[0][8][1] = FF, checkImage[0][8][2] = FF
checkImage[0][9][0] = FF, checkImage[0][9][1] = FF, checkImage[0][9][2] = FF
checkImage[0][10][0] = FF, checkImage[0][10][1] = FF, checkImage[0][10][2] = FF
checkImage[0][11][0] = FF, checkImage[0][11][1] = FF, checkImage[0][11][2] = FF
checkImage[0][12][0] = FF, checkImage[0][12][1] = FF, checkImage[0][12][2] = FF
checkImage[0][13][0] = FF, checkImage[0][13][1] = FF, checkImage[0][13][2] = FF
checkImage[0][14][0] = FF, checkImage[0][14][1] = FF, checkImage[0][14][2] = FF
checkImage[0][15][0] = FF, checkImage[0][15][1] = FF, checkImage[0][15][2] = FF

checkImage[0][16][0] = 0, checkImage[0][16][1] = 0, checkImage[0][16][2] = 0
checkImage[0][17][0] = 0, checkImage[0][17][1] = 0, checkImage[0][17][2] = 0
checkImage[0][18][0] = 0, checkImage[0][18][1] = 0, checkImage[0][18][2] = 0
checkImage[0][19][0] = 0, checkImage[0][19][1] = 0, checkImage[0][19][2] = 0
checkImage[0][20][0] = 0, checkImage[0][20][1] = 0, checkImage[0][20][2] = 0
checkImage[0][21][0] = 0, checkImage[0][21][1] = 0, checkImage[0][21][2] = 0
checkImage[0][22][0] = 0, checkImage[0][22][1] = 0, checkImage[0][22][2] = 0
checkImage[0][23][0] = 0, checkImage[0][23][1] = 0, checkImage[0][23][2] = 0

……

checkImage是一个3维数组,第1维表示行,第2维表示列,第3维表示像素颜色的RGB值。一个FF为8位,因此第3维的3个FF可表示24位的真彩。

从上可看出,每隔8列,则在checkImage的值则在0与FF之间切换,即在黑白之间切换。即,对于第0行,0至7列为黑,8至15列为白,16至23列为黑。由于checkImageWidth值为64,因此可产生 64 / 8 = 8 的黑白格。如果需要修改颜色,则将第3维的数值改为相应的值即可。

为何要每隔8列才切换黑白?每隔1列也可以,但在高分辨率的显示器下面非常不明显。因此这个8列,实际上控制着黑白格的宽度。

同理,每隔8行,则在黑白间切换。这就产生了错落有致的正方形黑白格。

需要注意的是,glDrawPixels函数虽然依次读取数据数值,但却是从最下面的1行开始绘制的。即checkImage[0][x][x]对于于最下面第1行,checkImage[1][x][x]对于于最下面第