2013-12-07 27 views
1

因此,當涉及將ppm紋理應用到四邊形時,我有一些粗糙的內容。我的問題是顏色不「正確」。Opengl在將紋理應用到對象時出現錯誤的顏色

colors of a few planets

下面是對木星汞幾個行星。

唯一正確的顏色是地球。

我下載的紋理在線(JPEG文件),然後從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 ... ECT)。現在我被困在這裏了......如何糾正紋理以顯示行星的正確顏色?

這裏是水銀紋理文件 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 
    } 

我發現它很難搞清楚爲什麼顏色是鮮豔的顏色的綠色,而不是代碼每個星球的實際顏色..看來,該計劃是棕色問題..任何想法?

+1

你確定你的文件都是'P6',對嗎?並有一個最大值(在維度線上的第三個數字)爲255?我不知道'GLubyte'是什麼,但我知道最大值<= 255的P6每個像素只有1個字節,所以如果'GLubyte'不是1個字節,這可能是一個問題。在任何情況下,P6中的像素順序都是紅色,綠色和藍色。 –

+0

這不是我的問題的解決方案,但它確實解決了我的問題。我做了一些打印語句來獲取標題信息,以便爲您拍攝它的屏幕截圖。我遇到過我沒有將255從混音中拉出來,因此它將255中的一些存儲在我的字節中它搞砸了顏色..我把它拉出來,並將bgr更改爲rgb,它完美的工作! – DWolf

+0

然後我會寫一個答案。 :-) –

回答

4

P6 PPM文件的標題中有3個數字:寬度,高度和最大值。寬度和高度給出圖像的尺寸,而maxval給出圖像的動態範圍。

在上面的代碼中,掃描圖像尺寸,但不掃描maxval。 maxval不能保證與圖像尺寸在同一行。

因此,在開始讀取圖像的位置,P6的maxval作爲圖像信息的一部分被讀入,移動所有字節並旋轉表觀R,G和B值。

的P6頭和有效負載的確切定義如下(的man ppm提供):

  • A「幻數」用於識別文件類型。 ppm圖像的幻數是兩個字符「P6」。

  • 空格(空白,TAB,CR,LF)。

  • 寬度,格式爲十進制的ASCII字符。

  • 空白。

  • 高度,再次以ASCII十進制表示。

  • 空白。

  • 最大顏色值(Maxval),再次以ASCII十進制表示。必須小於65536.

  • 換行符或其他單個空格字符。

  • 寬度*高度像素的光柵,按正常英語閱讀順序在圖像中進行。每個像素都是紅色,綠色和藍色樣本的三元組。每個採樣都以純二進制表示1或2個字節。如果Maxval小於256,則爲1個字節。否則,它是2個字節。最重要的字節是第一個。

  • 字符從「#」到最後一行之前的下一行,是註釋並被忽略。

這表明,而不是使用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文件正文中的字節,如果您需要支持這些文件。

+0

添加了一個小錯誤修復來處理在頭部有'123#comment'的情況,我不是100%確定是合法的,但似乎可能是這樣,至少對於maxval之前的值'。 –