2015-06-14 6 views
0

Я пытаюсь запрограммировать простую игру на C++, используя OpenGL для графики. В моей игре у меня есть объекты, которые отображаются на экране как белый квадрат. Я хотел бы иметь возможность привязывать изображение как текстуру к этим объектам, чтобы я мог визуализировать изображение на экране вместо белого квадрата. Нет никакого ограничения на формат изображения, хотя я использовал .png или .bmp для тестирования.Невозможно отобразить текстуру на квадрате

Один из моих классов объектов, Character.h, хранит переменную-член GLuint *, называемую _texture, и переменную-член unsigned char *, называемую _data (как дескриптор изображения и пиксельные данные, соответственно). В Character.h эта функция предназначена для привязки изображения в качестве текстуры к объекту Характер:

void loadTexture(const char* fileName) 
    { 
     /* read pixel data */ 
     FILE* file; 
     file = fopen(fileName, "rb"); 
     if (file == NULL) {cout << "ERROR: Image file not found!" << endl;} 
     _data = (unsigned char*)malloc(_dimension * _dimension * 3); 
     fread(_data, _dimension * _dimension * 3, 1, file); 
     fclose(file); 
     /* bind texture */ 
     glGenTextures(1, &_texture); // _texture is a member variable of type GLuint 
     glBindTexture(GL_TEXTURE_2D, _texture); 
     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, _dimension, _dimension, 0, GL_RGB, GL_UNSIGNED_BYTE, _data); // _dimension = 64.0f. 
    } 

После того как изображение связано, я затем пытаться визуализировать объект символов с помощью этой функции (что является статическая функция находится в отдельном классе):

static void drawTexturedRectangle(float x, float y, float w, float h, GLuint texture, unsigned char* data) 
    { 
     /* fractions are calculated to determine the position onscreen that the object is drawn at */ 
     float xFraction = (x/GlobalConstants::SCREEN_WIDTH) * 2; 
     float yFraction = (y/GlobalConstants::SCREEN_HEIGHT) * 2; 
     float wFraction = (w/GlobalConstants::SCREEN_WIDTH) * 2; 
     float hFraction = (h/GlobalConstants::SCREEN_HEIGHT) * 2; 
     glEnable(GL_TEXTURE_2D); 
     glClear(GL_COLOR_BUFFER_BIT); 
     glBindTexture(GL_TEXTURE_2D, texture); 
     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, w, h, 0, GL_RGB, GL_UNSIGNED_BYTE, data); 
     glPushMatrix(); 
     glEnable(GL_BLEND); 
     glBegin(GL_QUADS); 
     glTexCoord2f(0.0f, 0.0f); glVertex2f(xFraction, yFraction); // bottom left corner 
     glTexCoord2f(0.0f, 1.0f); glVertex2f(xFraction, yFraction + hFraction); // top left corner 
     glTexCoord2f(1.0f, 1.0f); glVertex2f(xFraction + wFraction, yFraction + hFraction); // top right corner 
     glTexCoord2f(1.0f, 0.0f); glVertex2f(xFraction + wFraction, yFraction); // bottom right corner 
     glEnd(); 
     glDisable(GL_BLEND); 
     glPopMatrix(); 
    } 

Независимо от того, сколько я возиться с этим, я не могу получить мою программу, чтобы сделать что-нибудь другое, чем делают простой белый квадрат с текстурой не на нем. Я проверил, чтобы переменные file, _texture, _dimension и _data содержали значения. Может ли кто-нибудь определить, что я могу делать неправильно?

+0

Я не думаю, что это причина вашей проблемы, но вы не должны называть 'glTexImage2D' каждый раз, когда хотите нарисовать текстуру - вы вызываете ее один раз, при загрузке текстуры. После этого вы можете отбросить данные из клиентской памяти, потому что вы передали его OpenGL, который будет управлять им, и вам нужно будет снова привязать текстуру, чтобы сообщить OpenGL, что вы хотите использовать. – orost

+0

Я не знаю остальной части вашего кода, но постараюсь убедиться, что у вас есть один вызов 'glEnable (GL_TEXTURE_2D);', прежде чем вы вызовете функцию 'loadTexture()'. – aslg

ответ

0

Я не думаю, что вы можете просто ввести необработанный файл в файл glTexImage2D, за исключением случаев, если вы храните файлы текстур в этом формате (что вы, вероятно, не используете). glTexImage2D ожидает огромные байты массива (представляющие цвета texel), но форматы файлов обычно не хранят изображения, подобные этому. Даже bmp имеет в нем некоторую информацию заголовка.

Используйте стороннюю библиотеку загрузчика изображений, такую ​​как DevIL или SOIL, чтобы загрузить текстуры! Эти библиотеки могут конвертировать наиболее распространенные форматы файлов изображений (png, jpg, tga, ...) в поток байтов, который вы можете ввести в OpenGL!

На боковой ноте: После вызова glTexImage2D (..., данных) содержимое данных копируется в память графического процессора (VRAM). С этого момента вам нужно привязать текстуру только с помощью id, так как она уже находится в VRAM. Вызов glTexImage2D() в каждом кадре будет загружать всю текстуру в каждый кадр в vram, что приведет к большому штрафу за производительность.

+0

Большое спасибо agnu17! Я получил его для работы с использованием ПОЧВЫ. Метод loadTexture просто становится: _texture = SOIL_load_OGL_texture (fileName, SOIL_LOAD_AUTO, SOIL_CREATE_NEW_ID, SOIL_FLAG_INVERT_Y); Я читал, что это может работать только с 8-битными .png по любой причине. – tomdunkle0

Смежные вопросы