【问题标题】:OpenGL/Glut: how to create a checkboard textureOpenGL/Glut:如何创建棋盘纹理
【发布时间】:2015-10-12 15:32:24
【问题描述】:

我想创建一个纹理以应用于 Torus,如下所示:

这是我刚开始写的代码:

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 的原因... 你能帮忙吗? 这就是我使用该代码得到的结果:

【问题讨论】:

  • 但我不知道如何区分蓝色部分和红色部分 - 你能改写一下吗?我不知道这意味着什么。我认为fmod 等式看起来也很可疑,但也许其中有一些魔力。
  • 对不起...我的意思是我不知道何时以及如何绘制蓝色矩形以及如何以及何时绘制红色矩形...只是,我不知道该写什么在图像矩阵内部:(
  • 你知道怎么做(你发布的代码就是这样做的)。如果有的话,你不知道何时
  • 我认为它不起作用,因为我没有得到我在该图片中发布的结果......我得到了一些奇怪的东西
  • 我刚刚添加了另一张图片...

标签: opengl textures glut


【解决方案1】:

由于纹理通常是平方大小的 2 次方 * 2 次方,因此您可以将它们划分为每端的 n 个子正方形,其中 n 也是 2 的次方。这将保证纹理的平滑包裹。

任何其他数字都可能导致问题,因为该数字不能被它整除(2n 的因式分解只有 2s),或者它会以 a 的一部分结束正方形,否则您将放入纹理中的正方形的大小不会完全相等。

一维示例

让我们首先采用一维纹理。循环中的索引将在 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
        }
    }
}

这应该会产生条纹纹理。现在我们需要添加对行和列的实际依赖。

“如果”的条件变成真值表:

     | 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
        }
    }
}

【讨论】:

  • 我假设您在分配环面纹理坐标时没有问题,例如您使用的另一种纹理工作正常,只是在生成棋盘时遇到了问题。
  • 嗯,我或多或少地理解了你写的东西......它似乎工作,即使纹理非常“精细”,这意味着矩形非常小而且密集......
  • @LoryLory 然后将desiredSegmentCount 的值降低到 4 或 2。
  • 这正是我正在做的事情,但没有任何改变。如果你想看看我的代码,这里是pastebin.com/jbrD45rb in functon initMyProceduralTexture()
  • @LoryLory 哦,快,我犯了一个错误。编辑修复。它应该除以段大小,而不是模段大小。请告诉我它现在是否有效:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-19
  • 2012-05-05
  • 2016-03-06
  • 2011-08-13
  • 2021-07-07
  • 1970-01-01
  • 2018-03-31
相关资源
最近更新 更多