[英]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行之前,從“#”到下一行末尾的字符是注釋,並被忽略。
這表明,而不是使用fgets
和sscanf
(老實說,通常是解析的更好的想法,特別是使用面向行的輸入),你應該考慮使用帶有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.