I have everything working except for one thing, does not want to show the texture! Though you shit, the whole Net break, I did not change the current code. So the main question, why do not display the texture. Although the version of GLUT had no such problems?
Example code:
A. The button downloads the texture:
[spoiler]
Code: Select all
void gameInterface::onOpenClick( wxCommandEvent& event )
{
wxString caption = wxT("Открыть файл");
wxString wildcard =
wxT("Файлы рисунков (*.tga,*.jpeg,*.png,*.bmp)|*.tga;*.jpeg;*.png;*.bmp|TGA файлы (*.tga)|*.tga|JPEG файлы (*.jpeg)|*.gpeg|PNG файлы (*.png)|*.png|BMP файлы (*.bmp)|*.bmp");
wxString defaultDir = wxT("\Pictures");
wxString defaultFilename = wxEmptyString;
wxFileDialog dialog(NULL, caption, defaultDir, defaultFilename,
wildcard, wxID_OPEN);
if (dialog.ShowModal() == wxID_OK){
GLuint* IDt = wxLoadImage(dialog.GetPath());
if(IDt){
if(PAR::TexImage != NULL)
glDeleteTextures(1, PAR::TexImage);
PAR::TexImage = IDt;
m_statusBar1->SetLabelText(wxT("Рисунок успешно загружен!"));
}
}
}
At first I thought that maybe I have it wrong ship, but I used 3 razdnyh function. Including the one I used in the GLUT version (can only load TGA files)
Taken my function:
[spoiler]
Code: Select all
GLuint* wxLoadImage(wxString path){
GLuint* ID=new GLuint[1];
glGenTextures( 1, &ID[0] );
glBindTexture( GL_TEXTURE_2D, *ID );
// the first time, init image handlers (remove this part if you do it somewhere else in your app)
static bool is_first_time = true;
if(is_first_time)
{
wxInitAllImageHandlers();
is_first_time = false;
}
// check the file exists
if(!wxFileExists(path))
{
wxMessageBox( _("Failed to load resource image") );
exit(1);
}
wxImage* img=new wxImage( path );
int imageWidth=img->GetWidth();
int imageHeight=img->GetHeight();
int textureWidth;
int textureHeight;
glPixelStorei(GL_UNPACK_ALIGNMENT, 1 );
/*
* Many graphics card require that textures be power of two.
* Below is a simple implementation, probably not optimal but working.
* If your texture sizes are not restricted to power of 2s, you can
* of course adapt the bit below as needed.
*/
float power_of_two_that_gives_correct_width=std::log((float)imageWidth)/std::log(2.0);
float power_of_two_that_gives_correct_height=std::log((float)imageHeight)/std::log(2.0);
// check if image dimensions are a power of two
if( (int)power_of_two_that_gives_correct_width == power_of_two_that_gives_correct_width &&
(int)power_of_two_that_gives_correct_height == power_of_two_that_gives_correct_height)
{
// note: must make a local copy before passing the data to OpenGL, as GetData() returns RGB
// and we want the Alpha channel if it's present. Additionally OpenGL seems to interpret the
// data upside-down so we need to compensate for that.
GLubyte *bitmapData=img->GetData();
GLubyte *alphaData=img->GetAlpha();
int bytesPerPixel = img->HasAlpha() ? 4 : 3;
int imageSize = imageWidth * imageHeight * bytesPerPixel;
GLubyte *imageData=new GLubyte[imageSize];
int rev_val=imageHeight-1;
for(int y=0; y<imageHeight; y++)
{
for(int x=0; x<imageWidth; x++)
{
imageData[(x+y*imageWidth)*bytesPerPixel+0]=
bitmapData[( x+(rev_val-y)*imageWidth)*3];
imageData[(x+y*imageWidth)*bytesPerPixel+1]=
bitmapData[( x+(rev_val-y)*imageWidth)*3 + 1];
imageData[(x+y*imageWidth)*bytesPerPixel+2]=
bitmapData[( x+(rev_val-y)*imageWidth)*3 + 2];
if(bytesPerPixel==4) imageData[(x+y*imageWidth)*bytesPerPixel+3]=
alphaData[ x+(rev_val-y)*imageWidth ];
}//next
}//next
// if yes, everything is fine
glTexImage2D(GL_TEXTURE_2D,
0,
bytesPerPixel,
imageWidth,
imageHeight,
0,
img->HasAlpha() ? GL_RGBA : GL_RGB,
GL_UNSIGNED_BYTE,
imageData);
textureWidth = imageWidth;
textureHeight = imageHeight;
delete [] imageData;
}
else // texture is not a power of two. We need to resize it
{
int newWidth=(int)std::pow( 2.0, (int)(std::ceil(power_of_two_that_gives_correct_width)) );
int newHeight=(int)std::pow( 2.0, (int)(std::ceil(power_of_two_that_gives_correct_height)) );
//printf("Unsupported image size. Recommand values: %i %i\n",newWidth,newHeight);
GLubyte *bitmapData=img->GetData();
GLubyte *alphaData=img->GetAlpha();
int old_bytesPerPixel = 3;
int bytesPerPixel = img->HasAlpha() ? 4 : 3;
int imageSize = newWidth * newHeight * bytesPerPixel;
GLubyte *imageData=new GLubyte[imageSize];
int rev_val=imageHeight-1;
for(int y=0; y<newHeight; y++)
{
for(int x=0; x<newWidth; x++)
{
if( x<imageWidth && y<imageHeight ){
imageData[(x+y*newWidth)*bytesPerPixel+0]=
bitmapData[( x+(rev_val-y)*imageWidth)*old_bytesPerPixel + 0];
imageData[(x+y*newWidth)*bytesPerPixel+1]=
bitmapData[( x+(rev_val-y)*imageWidth)*old_bytesPerPixel + 1];
imageData[(x+y*newWidth)*bytesPerPixel+2]=
bitmapData[( x+(rev_val-y)*imageWidth)*old_bytesPerPixel + 2];
if(bytesPerPixel==4) imageData[(x+y*newWidth)*bytesPerPixel+3]=
alphaData[ x+(rev_val-y)*imageWidth ];
}
else
{
imageData[(x+y*newWidth)*bytesPerPixel+0] = 0;
imageData[(x+y*newWidth)*bytesPerPixel+1] = 0;
imageData[(x+y*newWidth)*bytesPerPixel+2] = 0;
if(bytesPerPixel==4) imageData[(x+y*newWidth)*bytesPerPixel+3] = 0;
}
}//next
}//next
// set texture parameters as you wish
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // GL_LINEAR
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // GL_LINEAR
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D,
0,
img->HasAlpha() ? 4 : 3,
newWidth,
newHeight,
0,
img->HasAlpha() ? GL_RGBA : GL_RGB,
GL_UNSIGNED_BYTE,
imageData);
textureWidth=newWidth;
textureHeight=newHeight;
delete [] imageData;
}
return ID;
}
I altered the function:
[spoiler]
Code: Select all
GLuint* wxLoadImage(wxString path){
GLuint* ID=new GLuint[1];
// хотим построить текстуры в i-м элементе массива (указать OpenGL на доступную память)
glGenTextures( 1, &ID[0] );
// Создание текстуры
glBindTexture( GL_TEXTURE_2D, *ID ); // определяем тип построенной текст-ры (2D текстура) (создание текстуры, кот. будет сохранена в этой памяти)
// Проверка правильности пути(сущ. файла)
if(!wxFileExists(path)) {
wxMessageBox( _("Не удалось загрузить изображение") );
return NULL;
}
wxImage* img=new wxImage( path );
int imageWidth=img->GetWidth();
int imageHeight=img->GetHeight();
int bytesPerPixel = img->HasAlpha() ? 4 : 3;
// ф-я управляет хранением пикселей, устанавливаем параметр выравнивания всех строк развертки
glPixelStorei(GL_UNPACK_ALIGNMENT, 1 );
// Многие видеокарты требуют, чтобы текстура была степенью двойки.
float power_of_two_that_gives_correct_width=std::log((float)imageWidth)/std::log(2.0);
float power_of_two_that_gives_correct_height=std::log((float)imageHeight)/std::log(2.0);
bool step2 = (int)power_of_two_that_gives_correct_width == power_of_two_that_gives_correct_width &&
(int)power_of_two_that_gives_correct_height == power_of_two_that_gives_correct_height;
GLubyte *imageData;
GLubyte *bitmapData=img->GetData();
GLubyte *alphaData=img->GetAlpha();
// Только если нет альфа канала, т.к. GetData не возвращает альфа канал
if(step2 && alphaData==NULL) {
imageData = img->GetData();
goto toEnd;
}
int imageSize = imageWidth * imageHeight * bytesPerPixel;
imageData = new GLubyte[imageSize];;
int rev_val=imageHeight-1;
// проверяем, является ли изображение степенью двойки
int x,y;
if(step2){
for(y=0; y<imageHeight; y++){
for(x=0; x<imageWidth; x++){
imageData[(x+y*imageWidth)*bytesPerPixel+0]=
bitmapData[( x+(rev_val-y)*imageWidth)*3];
imageData[(x+y*imageWidth)*bytesPerPixel+1]=
bitmapData[( x+(rev_val-y)*imageWidth)*3 + 1];
imageData[(x+y*imageWidth)*bytesPerPixel+2]=
bitmapData[( x+(rev_val-y)*imageWidth)*3 + 2];
imageData[(x+y*imageWidth)*bytesPerPixel+3]=
alphaData[ x+(rev_val-y)*imageWidth ];
}//next
}//next
} else {
// Новые размеры текстыры
int newWidth=(int)std::pow( 2.0, (int)(std::ceil(power_of_two_that_gives_correct_width)) );
int newHeight=(int)std::pow( 2.0, (int)(std::ceil(power_of_two_that_gives_correct_height)) );
for(y=0; y<imageHeight; y++){
for(x=0; x<imageWidth; x++){
imageData[(x+y*newWidth)*bytesPerPixel+0]=
bitmapData[( x+(rev_val-y)*imageWidth)*3 + 0];
imageData[(x+y*newWidth)*bytesPerPixel+1]=
bitmapData[( x+(rev_val-y)*imageWidth)*3 + 1];
imageData[(x+y*newWidth)*bytesPerPixel+2]=
bitmapData[( x+(rev_val-y)*imageWidth)*3 + 2];
if(bytesPerPixel==4) imageData[(x+y*newWidth)*bytesPerPixel+3]=
alphaData[ x+(rev_val-y)*imageWidth ];
}
}
for(y = imageHeight; y<newHeight; y++){
for(x = imageWidth; x<newWidth; x++){
imageData[(x+y*newWidth)*bytesPerPixel+0] = 0;
imageData[(x+y*newWidth)*bytesPerPixel+1] = 0;
imageData[(x+y*newWidth)*bytesPerPixel+2] = 0;
if(bytesPerPixel==4) imageData[(x+y*newWidth)*bytesPerPixel+3] = 0;
}//next
}//next
imageWidth = newWidth;
imageHeight= newHeight;
}//if
toEnd:
glTexImage2D(GL_TEXTURE_2D,
0,
bytesPerPixel,
imageWidth,
imageHeight,
0,
img->HasAlpha() ? GL_RGBA : GL_RGB,
GL_UNSIGNED_BYTE,
imageData);
delete [] imageData;
return ID;
}
рабочая функция c TGA файлами:
[spoiler]
Code: Select all
#include <iostream>
#include <fstream>
// Структурная инфо о файле TGA
using namespace std;
#pragma pack(push,1)
struct TGAHEADER {
GLbyte identsize; // размер ID field that follows header (0)
GLbyte colorMapType; // 0 = None, 1 = paletted
GLbyte imageType; // 0 = none, 1 = индекс, 2 = rgb, 3 = серый, +8=rle // RLE - кодирование длин серий(метод сжатия)
unsigned short colorMapStart; // First colour map entry
unsigned short colorMapLength; // Number of colors
unsigned char colorMapBits; // bits per palette entry
unsigned short xstart; // image x origin
unsigned short ystart; // image y origin
unsigned short width; // ширина в пикселях
unsigned short height; // высота в пикселях
GLbyte bits; // количество бит на пиксель (8 16, 24, 32)
GLbyte descriptor; // дескриптор рисунка
};// TGAHEADER
#pragma pack(pop)
// ф-я загрузки текстур
GLbyte * bLoadTGA(const char *fileName, GLint *iWidth, GLint *iHeight, GLint *iComponents, GLenum *eFormat) {
ifstream iFile; // ссылка на тип файла
TGAHEADER tgaHeader; // TGA file header
unsigned long lImageSize; // размер текстуры в байтах
GLbyte *pBits = NULL; // ссылка на биты данных
// Открытие файла
iFile.open(fileName,ios::in | ios::binary);
if(!iFile.is_open()){
cout<<"Невозможно открыть файл";
return NULL;
}
// Запись структуры TGA (binary)
// &tgaHeader - указатель на область данных в которую записываются данные, считанные из файла
// 18/* sizeof(TGAHEADER)*/ - количество байтов
// 1 - количество блоков, считываемых при чтении
// iFile - указатель на открытый файл
//fread(&tgaHeader, 18/* sizeof(TGAHEADER)*/, 1, iFile);
iFile.read((char *) &tgaHeader,sizeof(TGAHEADER));
// Получаем ширину и высоту текстуры
*iWidth = tgaHeader.width;
*iHeight = tgaHeader.height;
*eFormat = GL_BGR_EXT; // формат информации о текселях
*iComponents = GL_RGB8; // внутренний формат данных изображения
lImageSize = tgaHeader.width * tgaHeader.height * tgaHeader.bits / 8; // ширина * высота * кол. байтов
// Динамическое выделение памяти
pBits = new GLbyte [lImageSize]; // возвр. указатель на первый бит выделенной памяти
if(pBits == NULL)
return NULL;
// Запись битов текстуры из файла в выделеную память
iFile.read((char *) pBits, lImageSize);
if( pBits == NULL){
delete [] pBits; // освобождаем выделенную память
return NULL; // ошибка
}
// Устанавливаем формат OpenGL для пикселей
switch(tgaHeader.bits)
{
case 24:
*eFormat = GL_BGR_EXT;
*iComponents = GL_RGB8;
break;
case 32:
*eFormat = GL_BGRA_EXT;
*iComponents = GL_RGBA8;
break;
case 8:
*eFormat = GL_LUMINANCE;
*iComponents = GL_LUMINANCE8;
break;
};
// закрытие файла
iFile.close();
// возвращаем биты данных
return pBits;
}
Finally rendenga function and initialization:
[spoiler]
Code: Select all
#include "GameGLPane.h"
static const int cColumns = 5; // количество колонок
static const int cRows = 5; // количество строк
GameGLPane::GameGLPane(gameInterface *canvas, int* args) :
wxGLCanvas(canvas, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, wxT("GLCanvas"), args){
dColumns = 1.0f / cColumns;
dRows = 1.0f / cRows;
//SetCurrent(*canvas);
//glEnable(GL_DEPTH_TEST); // включение теста глубины (удаление скрытых поверхностей)
glClearColor(0.0f,0.0f,0.0f,1.0f); // установка цвета и значения альфа, исп при очистке буф. цвета
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL); // установка режима растеризации
glEnable(GL_TEXTURE_2D);//*/
glTexEnvf(GL_TEXTURE_ENV, // определяемая текстурная среда
GL_TEXTURE_ENV_MODE, // определяемое имя параметра
GL_REPLACE); // знач-е пар-ра: значения текселей замещают коды геометрических фрагментов
// Установка параметров текстуры
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); // GL_LINEAR
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // GL_LINEAR
// Задаём способ обработки координат s текстуры не попадающей в диапазон от 0 до 1
//glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
};
void GameGLPane::Render(wxPaintEvent& evt){
wxGLCanvas::SetCurrent();
wxPaintDC(this);
//glViewport(0,0,400,400); // устанавливаем поле просотра с размерами окна
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0,1.0,0.0,1.0);
glMatrixMode(GL_MODELVIEW);
// загрузка единичной матрицы
glLoadIdentity();
// очистка буферов
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glColor3f(1.0f,1.0f,0.0f);
if(PAR::TexImage==NULL) goto toEnd;
// Рисуем
glBindTexture(GL_TEXTURE_2D, PAR::TexImage[0]); // выбираем текстуру
glBegin(GL_QUADS);
glTexCoord2f(1.0f, 0.0f); glVertex2f(0.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex2f(0.0f, 1.0f);
glTexCoord2f(0.0f, 1.0f); glVertex2f(1.0f, 1.0f);
glTexCoord2f(0.0f, 0.0f); glVertex2f(1.0f, 0.0f);
glEnd();
/*float dR1 = 0.0f;
float dR2;
float dC1 = 0.0f;
float dC2;
glBegin(GL_QUADS);
for (int j =1;j<=cRows;j++){
dR2 = j*dRows;
for(int i = 1;i<=cColumns;i++){
dC2 = i*dColumns;
glTexCoord2f(dR1, dC1); glVertex2f(dR1, dC1);
glTexCoord2f(dR1, dC2); glVertex2f(dR1, dC2);
glTexCoord2f(dR2, dC2); glVertex2f(dR2, dC2);
glTexCoord2f(dR2, dC1); glVertex2f(dR2, dC1);
dC1 = dC2;
}
dR1 = dR2;
dC1 = 0.0f;
}
glEnd();//*/
toEnd:
glFlush(); //опорожнить все очереди команд и буферы OpenGL
SwapBuffers();
}
void GameGLPane::mouseDown(wxMouseEvent& event){
int x =10;
};
void GameGLPane::Resized(wxSizeEvent& evt)
{
wxGLCanvas::OnSize(evt);
Refresh();
}
n just a square with no texture is displayed and all: (((
Interesting thread who would understand what was happening, because I thought dried up, threw the Muse!
P.S. Sorry for the English Google translation ))
files Project (MVS 10)
http://files.mail.ru/H1YKGE