OpenGL/Glut: 如何创建棋盘纹理
OpenGL/Glut: how to create a checkboard texture
我想创建一个纹理以应用于如下所示的圆环面:
这是我刚开始编写的代码:
void initMyProceduralTexture() {
GLubyte image[64][64][3];
int i, j, c, r, g, b;
glGenTextures( 1, &textureName[NUM_TEXTURES - 1] );
glBindTexture(GL_TEXTURE_2D, textureName[NUM_TEXTURES - 1]);
for(i=0;i<64;i++) {
for(j=0;j<64;j++) {
float a = floor(i * 8.0);
float b = floor(j * 8.0);
if (fmod(a,b) > 0.5 ) {
image[i][j][0]= (GLubyte) 255.0;
image[i][j][1]= (GLubyte) 127.5;
image[i][j][2]= (GLubyte) 127.5;
}
else {
image[i][j][0]= (GLubyte) 153.0;
image[i][j][1]= (GLubyte) 153.0;
image[i][j][2]= (GLubyte) 255.0;
}
}
}
glTexImage2D(GL_TEXTURE_2D,0,3,64,64,0,GL_RGB,GL_UNSIGNED_BYTE, image);
...
但我不知道如何区分蓝色部分和红色部分以及如何设置图像矩阵。我查看了 this 网站,这就是为什么我将该比例设置为 8.0...
你能帮忙吗?
这就是我用该代码得到的:
由于纹理通常是正方形大小的二次方 * 二次方,您可以在每一端将它们分成 n 个子方块,其中 n 也是二次方。这将保证纹理的平滑包裹。
任何其他数字都可能导致问题,因为该数字不能被它整除(2n 的因式分解只有 2),要么它会结束带有正方形的一部分,否则您将放入纹理中的正方形将不会具有完全相等的大小。
一维示例
我们先来一张一维贴图。循环中的索引将从 1 到例如 64 不等。我们只需要将该数字除以所需的段数即可得到一个段中所需的像素数:
int texSize = 64;
const int desiredSegmentCount = 8;
int segmentSize = texSize / desiredSegmentCount; // 8
现在,迭代时,我们可以通过索引除以段大小来获得段数:
for (int i = 0; i < texSize; ++i) {
const int segmentNum = i / segmentSize;
}
一旦我们有了段号,就可以很容易地评估它是奇数还是偶数,方法是 segmentNum % 2
(为清楚起见,可以选择添加 == 0
)。
因此,完整的循环看起来像:
for (int i = 0; i < texSize; ++i) {
const int segmentNum = i / segmentSize;
const bool isEven = (segmentNum % 2) == 0;
if (isEven) {
// output red pixel
} else {
// output blue pixel
}
}
扩展到二维
当我们添加另一个维度时,它只会变得稍微复杂一些。我们仍然可以假设尺寸将是数字,因为我们只处理正方形。循环需要跨越另一个维度:
for (int i = 0; i < texSize; ++i) {
for (int j = 0; j < texSize; ++j) {
const int segmentNum = i / segmentSize;
const bool isEven = (segmentNum % 2) == 0;
if (isEven) {
// output red pixel
} else {
// output blue pixel
}
}
}
这应该会产生条纹纹理。现在我们需要添加对行和列的实际依赖。
“如果”的条件变为真table:
| odd | even j
-----|------------------
odd | blue | red
even | red | blue
i
您应该立即将其识别为 XOR 运算,对于布尔值,它实际上与 (!=)
运算符相同。现在下面的代码应该非常清楚了:
for (int i = 0; i < texSize; ++i) {
for (int j = 0; j < texSize; ++j) {
const int segmentNumI = i / segmentSize;
const int segmentNumJ = j / segmentSize;
const bool isEvenI = (segmentNumI % 2) == 0;
const bool isEvenJ = (segmentNumJ % 2) == 0;
const bool redPixel = isEvenI != isEvenJ;
if (redPixel) {
// output red pixel
} else {
// output blue pixel
}
}
}
我想创建一个纹理以应用于如下所示的圆环面:
这是我刚开始编写的代码:
void initMyProceduralTexture() {
GLubyte image[64][64][3];
int i, j, c, r, g, b;
glGenTextures( 1, &textureName[NUM_TEXTURES - 1] );
glBindTexture(GL_TEXTURE_2D, textureName[NUM_TEXTURES - 1]);
for(i=0;i<64;i++) {
for(j=0;j<64;j++) {
float a = floor(i * 8.0);
float b = floor(j * 8.0);
if (fmod(a,b) > 0.5 ) {
image[i][j][0]= (GLubyte) 255.0;
image[i][j][1]= (GLubyte) 127.5;
image[i][j][2]= (GLubyte) 127.5;
}
else {
image[i][j][0]= (GLubyte) 153.0;
image[i][j][1]= (GLubyte) 153.0;
image[i][j][2]= (GLubyte) 255.0;
}
}
}
glTexImage2D(GL_TEXTURE_2D,0,3,64,64,0,GL_RGB,GL_UNSIGNED_BYTE, image);
...
但我不知道如何区分蓝色部分和红色部分以及如何设置图像矩阵。我查看了 this 网站,这就是为什么我将该比例设置为 8.0...
你能帮忙吗?
这就是我用该代码得到的:
由于纹理通常是正方形大小的二次方 * 二次方,您可以在每一端将它们分成 n 个子方块,其中 n 也是二次方。这将保证纹理的平滑包裹。
任何其他数字都可能导致问题,因为该数字不能被它整除(2n 的因式分解只有 2),要么它会结束带有正方形的一部分,否则您将放入纹理中的正方形将不会具有完全相等的大小。
一维示例
我们先来一张一维贴图。循环中的索引将从 1 到例如 64 不等。我们只需要将该数字除以所需的段数即可得到一个段中所需的像素数:
int texSize = 64;
const int desiredSegmentCount = 8;
int segmentSize = texSize / desiredSegmentCount; // 8
现在,迭代时,我们可以通过索引除以段大小来获得段数:
for (int i = 0; i < texSize; ++i) {
const int segmentNum = i / segmentSize;
}
一旦我们有了段号,就可以很容易地评估它是奇数还是偶数,方法是 segmentNum % 2
(为清楚起见,可以选择添加 == 0
)。
因此,完整的循环看起来像:
for (int i = 0; i < texSize; ++i) {
const int segmentNum = i / segmentSize;
const bool isEven = (segmentNum % 2) == 0;
if (isEven) {
// output red pixel
} else {
// output blue pixel
}
}
扩展到二维
当我们添加另一个维度时,它只会变得稍微复杂一些。我们仍然可以假设尺寸将是数字,因为我们只处理正方形。循环需要跨越另一个维度:
for (int i = 0; i < texSize; ++i) {
for (int j = 0; j < texSize; ++j) {
const int segmentNum = i / segmentSize;
const bool isEven = (segmentNum % 2) == 0;
if (isEven) {
// output red pixel
} else {
// output blue pixel
}
}
}
这应该会产生条纹纹理。现在我们需要添加对行和列的实际依赖。
“如果”的条件变为真table:
| odd | even j
-----|------------------
odd | blue | red
even | red | blue
i
您应该立即将其识别为 XOR 运算,对于布尔值,它实际上与 (!=)
运算符相同。现在下面的代码应该非常清楚了:
for (int i = 0; i < texSize; ++i) {
for (int j = 0; j < texSize; ++j) {
const int segmentNumI = i / segmentSize;
const int segmentNumJ = j / segmentSize;
const bool isEvenI = (segmentNumI % 2) == 0;
const bool isEvenJ = (segmentNumJ % 2) == 0;
const bool redPixel = isEvenI != isEvenJ;
if (redPixel) {
// output red pixel
} else {
// output blue pixel
}
}
}