繁体   English   中英

将纹理应用于对象时,Opengl颜色错误

[英]Opengl wrong colors when applying textures to objects

因此,当涉及将ppm纹理应用于四边形时,我正在做大事。 我的问题是颜色不正确。

一些行星的颜色

这是从水银到木星的几个行星。

唯一正确的颜色是地球。

我在线下载了纹理(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 ...等)。 现在我被困在这里..如何纠正纹理以显示行星的正确颜色?

这是水银纹理文件 在此输入图像描述

这是处理纹理的代码

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个数字:宽度,高度和最大值。 宽度和高度给出图像的尺寸,maxval给出图像的动态范围。

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

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

P6标头和有效载荷的确切定义如下(由man ppm ):

  • 用于识别文件类型的“幻数”。 ppm图像的幻数是两个字符“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只是为了返回EOF的value ,我相信如果你需要支持那些函数也可以正常读取P3文件正文中的字节。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM