gpt4 book ai didi

c++ - 将纹理应用于对象时 Opengl 颜色错误

转载 作者:行者123 更新时间:2023-11-30 01:55:43 25 4
gpt4 key购买 nike

因此,在将 ppm 纹理应用于四边形时,我遇到了一些困难。我的问题是颜色不“正确”。

colors of a few planets

这是从水星到木星的几颗行星。

唯一正确的颜色是地球。

我在线下载了纹理(jpegs),然后从 linux 命令行转换它们

jpegtopnm Mercury.jpg > Mercury.ppm

我对您在上面看到的所有图像都这样做了。

一开始颜色都是反的所以我改了

 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ImgWidth, ImgHeight, 0, GL_RGB,
GL_UNSIGNED_BYTE, TexBits);

 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ImgWidth, ImgHeight, 0, GL_BGR,
GL_UNSIGNED_BYTE, TexBits);

并且修复了反转的颜色(r 而不是 b ... 等)。现在我被困在这里.. 我该如何修正纹理以显示行星的正确颜色?

这是 Mercurial 纹理文件 enter image description here

这是处理纹理的代码

void read_file(const char * filename)
{
FILE *infile;
char buf[80];
char string[256];
unsigned char *texImage;
int i, temp;
GLubyte *sp;
if ( (infile = fopen(filename, "rb")) == NULL)
{
printf("File open error\n");
exit(1);
}
fgets(string, 256, infile);


fgets(string, 256, infile);
while (string[0] == '#')
fgets(string, 256, infile);

sscanf(string, "%d %d", &ImgWidth, &ImgHeight);


if (TexBits != 0)
free(TexBits);

TexBits = (GLubyte *) calloc(ImgWidth * ImgHeight * 3, sizeof(GLubyte));

for (i = ImgHeight - 1; i >= 0; i--)
{
sp = TexBits + i * ImgWidth * 3;
fread (sp, sizeof(GLubyte), ImgWidth * 3, infile);
}
fclose(infile);
}
void bindTexture()
{
glGenTextures(10, texName);

glBindTexture(GL_TEXTURE_2D, texName[1]);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
read_file("Mercury.ppm");
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, ImgWidth, ImgHeight, 0, GL_BGR,
GL_UNSIGNED_BYTE, TexBits);

///// rest of planets in order.. ( same code for each of them )
}

void drawCircle(GLfloat size, GLfloat offset, GLint r)
{
quadratic=gluNewQuadric();

gluQuadricDrawStyle(quadratic, GLU_FILL);
gluQuadricTexture(quadratic, GL_TRUE);
gluSphere(quadratic, size, r, r);
}

void display(void)
{
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

/* mercury */
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, texName[1]);
glColor4f(1.0, 1.0, 1.0, 1.0);
DrawPlanet(-17.0f, -4.0f, -9.0f, zAxis, .7f, .3f, 25);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);


// rest of code is similar to the one above
}

我发现很难弄清楚为什么颜色是亮绿色而不是每个行星的实际颜色。程序似乎有棕色问题。有什么想法吗?

最佳答案

P6 PPM 文件的标题中有 3 个数字:宽度、高度和最大值。 width 和 height 给出了图像的尺寸,maxval 给出了图像的动态范围。

在上面的代码中,您扫描图像尺寸,但不扫描 maxval。不保证 maxval 与图像尺寸在同一行。

因此,在您开始读取图像时,P6 的 maxval 作为图像信息的一部分被读入,移动所有字节,并旋转明显的 R、G 和 B 值。

P6 header 和 payload 的确切定义如下(由 man ppm 提供):

  • 用于识别文件类型的“魔数(Magic Number)”。 ppm 图像的魔数(Magic Number)是“P6”这两个字符。

  • 空格(空格、TAB、CR、LF)。

  • 宽度,格式为十进制的 ASCII 字符。

  • 空格。

  • 高度,同样以 ASCII 十进制表示。

  • 空格。

  • 最大颜色值 (Maxval),同样以 ASCII 十进制表示。必须小于 65536。

  • 换行符或其他单个空白字符。

  • 宽度 * 高度像素的栅格,以正常的英语阅读顺序在图像中继续。每个像素都是按顺序排列的红色、绿色和蓝色样本的三元组。每个样本用 1 或 2 个字节以纯二进制表示。如果 Maxval 小于 256,则为 1 个字节。否则,它是 2 个字节。最高有效字节在前。

  • 在 maxval 行之前,从“#”到下一个行尾的字符是注释,将被忽略。

这表明,而不是使用 fgetssscanf (老实说,这通常是解析的更好主意,尤其是对于面向行的输入),您应该考虑使用 fgetc() 的循环。和一个小型状态机,以确保您对可能遇到的任何 P6 文件都完全健壮。

这样的事情可能会起作用:

int get_pnm_header(FILE *f)
{
int ch;

if ((ch = fgetc(f)) != 'P')
return -1; // not a PNM file

if ((ch = fgetc(f)) < '1' || ch > '6')
return -1; // not a PNM file

return ch - '0';
}

int get_ppm_integer(FILE *f)
{
int in_comment = 0;
int in_value = 0;
int value = 0;
int ch;

while ((ch = fgetc(f)) != EOF)
{
if (ch == '#')
in_comment = 1;

if (in_comment)
{
in_comment = ch != '\n';
continue;
}

if (isdigit(ch))
in_value = 1;

if (in_value)
{
if (!isdigit(ch))
{
if (!isspace(ch)) /* consume first WS after value */
ungetc(ch, f); /* If not WS, put it back (might be '#' for a comment) */
return value;
}

value = (value * 10) + ch - '0';
continue;
}

if (!isspace(ch))
{
fprintf(stderr, "Warning: unexpected character '%c' in P6 header\n", ch);
}
}
fprintf(stderr, "Warning: EOF encountered reading P6 header\n");
return -1;
}

然后在您的代码中进一步向下:

int pnm_type = get_pnm_header(infile);

if (pnm_type != 6)
// report an error about unexpected file type

ImgWidth = get_ppm_integer(infile);
ImgHeight = get_ppm_integer(infile);
ImgMaxval = get_ppm_integer(infile);

if (ImgMaxval != 255)
// report an error about unsupported maxval

int r = fread((void *)TexBits, 3, ImgHeight * ImgWidth, infile);

if (r != ImgHeight * ImgWidth)
// report an error about a short file.

如果修改get_ppm_integer返回value在 EOF 上,我相信该函数也可以正确读取 P3 正文中的字节。文件,如果您需要支持这些文件。

关于c++ - 将纹理应用于对象时 Opengl 颜色错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20444839/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com