Hi,
i just started to learn OpenGL. I used a tutorial for the beginning and worte starting from it my own program (not allowed to post lins. When it is done it’ll display a msh file including the textures, bumpmaps, normalmaps, specmaps,… and display a lot of information.
But my texture projection does not what it should do.
I have a hardcoded cube with simple texture projection. But for some reason the RGB colours are swap R=B and B=R. But as you can see in the hex editor and at the debug values of the vector, the values are read in correctly RGB (i used that small 10x10 texture). The result is shown at the upper left corner. What the hell happend??
I tried a bigger texture 256x256 (attention now the upper colour from the source is red not blue!!) and the texture is shown a bit better. Only the Colors R and B are swapped and the first row looks wired. Any ideas about that??
[ATTACH=CONFIG]1400[/ATTACH]
And here is my code: main.cpp
#ifndef _DEBUG
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
#endif // DEBUG
#include <iostream>
#include <Windows.h>
#include <gl\glut.h>
#include "typedefs.h"
#include "tga.h"
#include "texture.h"
void init(void)
{
glClearColor(0.3000, 0.4000, 1.0000, 0.0000); // This clear the background color to dark blue
glShadeModel(GL_SMOOTH); // Type of shading for the polygons
glViewport(0, 0, screen_width, screen_height); // Viewport transformation
// Projection transformation
glMatrixMode(GL_PROJECTION); // Specifies which matrix stack is the target for matrix operations
glLoadIdentity(); // We initialize the projection matrix as identity
gluPerspective(45.0f, (GLfloat)screen_width / (GLfloat)screen_height, 1.0f, 1000.0f); // We define the "viewing volume"
glEnable(GL_DEPTH_TEST); // We enable the depth test (also called z buffer)
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Polygon rasterization mode (polygon filled)
glEnable(GL_TEXTURE_2D);
cube.id_texture = 1; // LoadBitmap("texture1.bmp");
try
{
TextureTGA texture("3x3H.tga");
glBindTexture(GL_TEXTURE_2D, cube.id_texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); // If the u,v coordinates overflow the range 0,1 the image is repeated
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // The magnification function ("linear" produces better results)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); //The minifying function
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); // We don't combine the color with the original surface color, use only the texture map.
glTexImage2D(GL_TEXTURE_2D, 0, texture.hasAlpha() ? GL_RGBA : GL_RGB, texture.getWidth(), texture.getHeight(), 0, texture.hasAlpha() ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, texture.getData().data());
gluBuild2DMipmaps(GL_TEXTURE_2D, texture.hasAlpha() ? GL_RGBA : GL_RGB, texture.getWidth(), texture.getHeight(), texture.hasAlpha() ? GL_RGBA : GL_RGB, GL_UNSIGNED_BYTE, texture.getData().data());
}
catch (std::invalid_argument e)
{
MessageBox(NULL, e.what(), "MeshViewer 2.0 Error", MB_OK | MB_ICONERROR);
exit(0);
}
}
void resize(int width, int height)
{
screen_width = width; // We obtain the new screen width values and store it
screen_height = height; // Height value
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // We clear both the color and the depth buffer so to draw the next frame
glViewport(0, 0, screen_width, screen_height); // Viewport transformation
glMatrixMode(GL_PROJECTION); // Projection transformation
glLoadIdentity(); // We initialize the projection matrix as identity
gluPerspective(45.0f, (GLfloat)screen_width / (GLfloat)screen_height, 1.0f, 1000.0f);
glutPostRedisplay(); // This command redraw the scene (it calls the same routine of glutDisplayFunc)
}
void keyboard(unsigned char key, int x, int y)
{
switch (key)
{
case ' ':
rotation_x = 0;
rotation_y = 0;
rotation_z = 0;
translate = -50;
break;
case 't': case 'T':
if (filling == 0)
{
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Polygon rasterization mode (polygon filled)
filling = 1;
}
else
{
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Polygon rasterization mode (polygon outlined)
filling = 0;
}
break;
case 'r': case 'R':
glClearColor(1.0000, 0.0000, 0.0000, 0.0000);
break;
case 'g': case 'G':
glClearColor(0.0000, 1.0000, 0.0000, 0.0000);
break;
case 'b': case 'B':
glClearColor(0.0000, 0.0000, 1.0000, 0.0000);
break;
case '+':
translate++;
//glTranslatef(0.0, 0.0, translate);
break;
case '-':
translate--;
//glTranslatef(0.0, 0.0, translate);
break;
}
}
void keyboard_s(int key, int x, int y)
{
switch (key)
{
case GLUT_KEY_UP:
rotation_x++;
break;
case GLUT_KEY_DOWN:
rotation_x--;
break;
case GLUT_KEY_LEFT:
rotation_y++;
break;
case GLUT_KEY_RIGHT:
rotation_y--;
break;
}
}
void mouse(int button, int state, int x, int y)
{
std::cout << "mouse action: " << button << ", " << state << ", " << x << ", " << y << std::endl;
}
void display(void)
{
int l_index;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // This clear the background color to dark blue
glMatrixMode(GL_MODELVIEW); // Modeling transformation
glLoadIdentity(); // Initialize the model matrix as identity
glTranslatef(0.0, 0.0, translate); // We move the object 50 points forward (the model matrix is multiplied by the translation matrix)
if (rotation_x > 359) rotation_x = 0;
if (rotation_y > 359) rotation_y = 0;
if (rotation_z > 359) rotation_z = 0;
glRotatef(rotation_x, 1.0, 0.0, 0.0); // Rotations of the object (the model matrix is multiplied by the rotation matrices)
glRotatef(rotation_y, 0.0, 1.0, 0.0);
glRotatef(rotation_z, 0.0, 0.0, 1.0);
glBindTexture(GL_TEXTURE_2D, cube.id_texture);
glBegin(GL_TRIANGLES); // GlBegin and glEnd delimit the vertices that define a primitive (in our case triangles)
for (l_index = 0; l_index < 12; l_index++)
{
int knotA = cube.polygon[l_index].a;
int knotB = cube.polygon[l_index].b;
int knotC = cube.polygon[l_index].c;
// knot a from polygon l_index
glTexCoord2f(cube.mapcoord[knotA].u,
cube.mapcoord[knotA].v);
glVertex3f(cube.vertex[knotA].x,
cube.vertex[knotA].y,
cube.vertex[knotA].z);
// knot b from polygon l_index
glTexCoord2f(cube.mapcoord[knotB].u,
cube.mapcoord[knotB].v);
glVertex3f(cube.vertex[knotB].x,
cube.vertex[knotB].y,
cube.vertex[knotB].z);
//knot c from polygon l_index
glTexCoord2f(cube.mapcoord[knotC].u,
cube.mapcoord[knotC].v);
glVertex3f(cube.vertex[knotC].x,
cube.vertex[knotC].y,
cube.vertex[knotC].z);
}
glEnd();
glFlush(); // This force the execution of OpenGL commands
glutSwapBuffers(); // In double buffered mode we invert the positions of the visible buffer and the writing buffer
}
int main(int argc, char** argv)
{
// We use the GLUT utility to initialize the window, to handle the input and to interact with the windows system
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(screen_width, screen_height);
glutInitWindowPosition(0, 0);
glutCreateWindow("MeshViewer 2.0 pre-alpha");
glutDisplayFunc(display);
glutIdleFunc(display);
glutReshapeFunc(resize);
glutKeyboardFunc(keyboard);
glutSpecialFunc(keyboard_s);
glutMouseFunc(mouse);
init();
glutMainLoop();
return 0;
}
texture.cpp
#include "texture.h"
#include <iostream>
#include <fstream>
#include <Windows.h>
TextureTGA::TextureTGA(const char * filePath)
{
std::fstream fsPicture(filePath, std::ios::in | std::ios::binary);
if (!fsPicture.is_open())
throw std::invalid_argument(std::string("file not found: ") += filePath);
OutputDebugStringW(L"read in picture header");
std::uint8_t ui8x18Header[18] = { 0 };
fsPicture.read(reinterpret_cast<char*>(&ui8x18Header), sizeof(ui8x18Header));
ui32IDLength = ui8x18Header[0];
bColorTabel = ui8x18Header[1] == 1;
ui32PicType = ui8x18Header[2];
ui32PaletteBegin = ui8x18Header[4] * 0xFF + ui8x18Header[3];
ui32PaletteLength = ui8x18Header[6] * 0xFF + ui8x18Header[5];
ui32PaletteBpP = ui8x18Header[7];
ui32Width = ui8x18Header[13] * 0xFF + ui8x18Header[12];
ui32Height = ui8x18Header[15] * 0xFF + ui8x18Header[14];
ui32BpP = ui8x18Header[16];
ui32Attribut = ui8x18Header[17];
ui32Size = ui32Width * ui32Height * ui32BpP/8;
bCompressed = ui32PicType == 9 || ui32PicType == 10;
vui8Pixels.resize(ui32Size);
std::cout << "Header
"
<< "ID länge: " << ui32IDLength << std::endl
<< "Farbtabelle: " << (int)bColorTabel << std::endl
<< "Bildtype: " << ui32PicType << std::endl
<< "Palletenbegin: " << ui32PaletteBegin << std::endl
<< "Palletenlängen: " << ui32PaletteLength << std::endl
<< "Bits pro Palleteneintrag: " << ui32PaletteBpP << std::endl
<< "Breite: " << ui32Width << std::endl
<< "Höhe: " << ui32Height << std::endl
<< "Bit pro Pixel: " << ui32BpP << std::endl
<< "Bild Attribute: " << ui32Attribut << std::endl;
fsPicture.seekg(ui32IDLength + ui32PaletteLength, std::ios_base::cur);
if (ui32PicType == 2) // not compressed
{
if (ui32BpP == 24) // 24 bit = no alpha
{
fsPicture.read(reinterpret_cast<char*>(vui8Pixels.data()), ui32Size);
}
else if (ui32BpP == 32) // 32 bit = alpha
{
fsPicture.read(reinterpret_cast<char*>(vui8Pixels.data()), ui32Size);
}
else // that shouldn't happen
{
fsPicture.close();
throw std::invalid_argument("Invaild File Format! Required 24 or 31 Bit Image.");
}
}
else if (ui32PicType == 10) // compressed
{
if (ui32BpP == 24) // 24 bit = no alpha
{
}
else if (ui32BpP == 32) // 32 bit = alpha
{
}
else // that shouldn't happen
{
fsPicture.close();
throw std::invalid_argument("Invaild File Format! Required 24 or 31 Bit Image.");
}
}
else // not practable Image type
{
fsPicture.close();
throw std::invalid_argument("Invaild File Format! Required 24 or 31 Bit Image.");
}
/*
//fix color mix
std::uint8_t temp;
std::uint32_t it = 0;
while (it + 2 < ui32Size)
{
temp = vui8Pixels[it];
vui8Pixels[it] = vui8Pixels[it + 2];
vui8Pixels[it + 2] = temp;
ui32BpP == 32 ? it += 2 : it += 3;
}*/
fsPicture.close();
}
TextureTGA::~TextureTGA()
{
}
std::vector<std::uint8_t> TextureTGA::getData() const
{
return vui8Pixels;
}
bool TextureTGA::hasAlpha() const
{
return ui32BpP == 32;
}
std::uint32_t TextureTGA::getWidth() const
{
return ui32Width;
}
std::uint32_t TextureTGA::getHeight() const
{
return ui32Height;
}
std::uint32_t TextureTGA::getSize() const
{
return ui32Size;
}
i wrote this simple work around for the correct colour, but i don’t think it’s a good idea to work with an workaround. The values in the vector are one pixel after the other rgb. So why does OpenGL display it as bgr even when i wrote that it is RGB format??