2013-07-18 2 views
1

У меня есть класс под названием Texture. Этот класс отвечает за управление текстурой. При запуске программ контекст OpenGL инициализируется должным образом (что и делает этот вопрос отличным от большинства случаев, связанных с неожиданным поведением glGenTextures). Texture получает имя текстуры от glGenTextures(), а затем загружает и связывает данные изображения в память для этого имени текстуры в функции texGLInit(). Это работает, и текстура отображается точно так, как ожидалось.glGenTextures работает, но возвращает одно и то же имя текстуры каждый раз

Однако, я также хочу, чтобы моя текстура могла изменять текстуру, отображаемую при нажатии пользователем кнопки, и выбирает ее с жесткого диска в OpenFileDiaglog. Функция для этого называется reloadTexture(). Эта функция пытается удалить старые данные изображения/пикселя из памяти и заменить их новыми данными из файла, выбранного пользователем. Однако, когда это происходит, оно удаляет имя текстуры с помощью glDeleteTextures, а затем назначает новое имя текстуры и загружает новые пиксельные данные в память с помощью функции texGLInit(). Но имя текстуры точно такое же, как раньше (обычно «1») в 100% случаев.

Изображение, отображаемое после этого, является нечетным. Он имеет новые размеры изображений, но все еще старые пиксели изображений. Проще говоря, он искажает старое изображение до размера новых изображений. Он по-прежнему выполняется с использованием предположительно удаленных данных пикселя. Что должно произойти, так это то, что на экране теперь отображается новый файл изображения на экране. Я считаю, что это связано с тем, что имя текстуры не уникально.

код приведен ниже:

Texture::Texture(string filename)//---Constructor loads in the initial image. Works fine! 
{ 
    textureID[0]=0; 

    const char* fnPtr = filename.c_str(); //our image loader accepts a ptr to a char, not a string 
    //printf(fnPtr); 

    lodepng::load_file(buffer, fnPtr);//load the file into a buffer 

    unsigned error = lodepng::decode(image,w,h,buffer);//lodepng's decode function will load the pixel data into image vector from the buffer 
    //display any errors with the texture 
    if(error) 
    { 
     cout << "\ndecoder error " << error << ": " << lodepng_error_text(error) <<endl; 
    } 
    //execute the code that'll throw exceptions to do with the images size 
    checkPOT(w); 
    checkPOT(h); 


    //image now contains our pixeldata. All ready for OpenGL to do its thing 

    //let's get this texture up in the video memory 
    texGLInit(); 

    Draw_From_Corner = CENTER; 
} 

void Texture::reloadTexture(string filename)//Reload texture replaces the texture name and image/pixel data bound to this texture 
{ 
    //first and foremost clear the image and buffer vectors back down to nothing so we can start afresh 
    buffer.clear(); 
    image.clear(); 
    w = 0; 
    h = 0; 
    //also delete the texture name we were using before 
    glDeleteTextures(1, &textureID[0]); 




    const char* fnPtr = filename.c_str(); //our image loader accepts a ptr to a char, not a string 
    //printf(fnPtr); 

    lodepng::load_file(buffer, fnPtr);//load the file into a buffer 

    unsigned error = lodepng::decode(image,w,h,buffer);//lodepng's decode function will load the pixel data into image vector from the buffer 
    //display any errors with the texture 
    if(error) 
    { 
     cout << "\ndecoder error " << error << ": " << lodepng_error_text(error) <<endl; 
    } 
    //execute the code that'll throw exceptions to do with the images size 
    checkPOT(w); 
    checkPOT(h); 

    //image now contains our pixeldata. All ready for to do its thing 

    //let's get this texture up in the video memoryOpenGL 
    texGLInit(); 

    Draw_From_Corner = CENTER; 
} 

void Texture::texGLInit()//Actually gets the new texture name loads the pixeldata into openGL 
{ 
    glGenTextures(1, &textureID[0]); 
    ////printf("\ntextureID = %u", textureID[0]); 
    glBindTexture(GL_TEXTURE_2D, textureID[0]);//evrything we're about to do is about this texture 
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1); 
    glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 
    //glDisable(GL_COLOR_MATERIAL); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,w,h,0, GL_RGBA, GL_UNSIGNED_BYTE, &image[0]); 
    //we COULD free the image vectors memory right about now. But we'll do it when there's a need to. At the beginning of the reloadtexture func, makes sure it happens when we need it to. 



} 

Для чего это стоит здесь функция втягивания класса Texture.

void Texture::draw(point* origin, ANCHOR drawFrom) 
{ 
    //let us set the DFC enum here. 
    Draw_From_Corner = drawFrom; 

    glEnable(GL_TEXTURE_2D); 
    //printf("\nDrawing texture at (%f, %f)",centerPoint.x, centerPoint.y); 
    glBindTexture(GL_TEXTURE_2D, textureID[0]);//bind the texture 
    //create a quick vertex array for the primitive we're going to bind the texture to 
    ////printf("TexID = %u",textureID[0]); 
    GLfloat vArray[8]; 

#pragma region anchor switch 
    switch (Draw_From_Corner) 
    { 
    case CENTER: 

     vArray[0] = origin->x-(w/2); vArray[1] = origin->y-(h/2);//bottom left i0 
     vArray[2] = origin->x-(w/2); vArray[3] = origin->y+(h/2);//top left i1 
     vArray[4] = origin->x+(w/2); vArray[5] = origin->y+(h/2);//top right i2 
     vArray[6] = origin->x+(w/2); vArray[7] = origin->y-(h/2);//bottom right i3 
     break; 

    case BOTTOMLEFT: 

     vArray[0] = origin->x; vArray[1] = origin->y;//bottom left i0 
     vArray[2] = origin->x; vArray[3] = origin->y+h;//top left i1 
     vArray[4] = origin->x+w; vArray[5] = origin->y+h;//top right i2 
     vArray[6] = origin->x+w; vArray[7] = origin->y;//bottom right i3 

     break; 

    case TOPLEFT: 

     vArray[0] = origin->x; vArray[1] = origin->y-h;//bottom left i0 
     vArray[2] = origin->x; vArray[3] = origin->y;//top left i1 
     vArray[4] = origin->x+w; vArray[5] = origin->y;//top right i2 
     vArray[6] = origin->x+w; vArray[7] = origin->y-h;//bottom right i3 

     break; 

    case TOPRIGHT: 

     vArray[0] = origin->x-w; vArray[1] = origin->y-h;//bottom left i0 
     vArray[2] = origin->x-w; vArray[3] = origin->y;//top left i1 
     vArray[4] = origin->x; vArray[5] = origin->y;//top right i2 
     vArray[6] = origin->x; vArray[7] = origin->y-h;//bottom right i3 

     break; 

    case BOTTOMRIGHT: 

     vArray[0] = origin->x-w; vArray[1] = origin->y;//bottom left i0 
     vArray[2] = origin->x-w; vArray[3] = origin->y+h;//top left i1 
     vArray[4] = origin->x-h; vArray[5] = origin->y;//top right i2 
     vArray[6] = origin->x; vArray[7] = origin->y;//bottom right i3 

     break; 

    default: //same as center 

     vArray[0] = origin->x-(w/2); vArray[1] = origin->y-(h/2);//bottom left i0 
     vArray[2] = origin->x-(w/2); vArray[3] = origin->y+(h/2);//top left i1 
     vArray[4] = origin->x+(w/2); vArray[5] = origin->y+(h/2);//top right i2 
     vArray[6] = origin->x+(w/2); vArray[7] = origin->y-(h/2);//bottom right i3 

     break; 


    } 
#pragma endregion   

    //create a quick texture array (we COULD create this on the heap rather than creating/destoying every cycle) 
    GLfloat tArray[8] = 
    { 
     //this has been tinkered with from my normal order. I think LodePNG is bringing the PD upside down. SO A QUICK FIX HERE WAS NECESSARY. 
     0.0f,1.0f,//0 
     0.0f,0.0f,//1 
     1.0f,0.0f,//2 
     1.0f,1.0f//3 
    }; 

    //and finally.. the index array...remember, we draw in triangles....(and we'll go CW) 
    GLubyte iArray[6] = 
    { 
     0,1,2, 
     0,2,3 
    }; 

    //Activate arrays 
    glEnableClientState(GL_VERTEX_ARRAY); 
    glEnableClientState(GL_TEXTURE_COORD_ARRAY); 

    //Give openGL a pointer to our vArray and tArray 
    glVertexPointer(2, GL_FLOAT, 0, &vArray[0]); 
    glTexCoordPointer(2, GL_FLOAT, 0, &tArray[0]); 

    //Draw it all 
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, &iArray[0]); 

    //glDrawArrays(GL_TRIANGLES,0,6); 

    //Disable the vertex arrays 
    glDisableClientState(GL_VERTEX_ARRAY); 
    glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
    glDisable(GL_TEXTURE_2D); 
} 

Может кто-нибудь сказать мне, почему OpenGL не нагружать и опираясь на новые данные пикселей, которые я загруженным в него? Как я уже сказал, я подозреваю, что это связано с тем, что glGenTextures не дает мне нового имени текстуры.

+2

Я не вижу ничего плохого в glGenTextures, дающем вам старое название текстуры. В [документации для glDeleteTextures] (http://www.opengl.org/sdk/docs/man/xhtml/glDeleteTextures.xml) явно говорится: «После того, как текстура удалена, она не имеет содержимого или размерности, а ее имя является бесплатным для повторного использования (например, glGenTextures) ". – dfan

+0

Я не понимаю, почему textureID является массивом. Ну, да, это работает ... но ... почему? Что случилось с простой переменной? – datenwolf

+0

@ datenwolf Я использовал простой GLUint, я экспериментировал с использованием массива вместо этого, когда увидел, что все остальные используют их в примерах. В конце концов, в документации говорится, что 2-й аргумент указывает массив. Я просто не вернулся еще:] –

ответ

2

Вы звоните glTexImage2D и передаете указатель на клиентскую память. Осторожно, документация говорит:

Если ненулевой поименованный объект буфера связан с GL_PIXEL_UNPACK_BUFFER цели (см glBindBuffer) в то время как изображение текстуры указано, data трактуются как байте в хранилище данных объекта буфера ,

Возможно, вы захотите позвонить glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0), чтобы отпереть любой объект буфера только для того, чтобы быть в безопасности.

+0

Вы бы рекомендовали сделать это перед любым попыткой повторного связывания? –

+0

@Guy: Нет, я бы использовал этот вызов прямо перед 'glTexImage2D (..., & image [0]);', чтобы убедиться, что OpenGL не будет выглядеть в каком-то связанном буфере для пиксельных данных вместо чтения из массив 'image'. –

+0

Наконец-то я получил работу glew. Однако glBindBuffer, как и выше, вызывает сбой. 'Необработанное исключение типа« System.AccessViolationException »произошло в Spritey.exe Дополнительная информация: Попытка чтения или записи защищенной памяти. Это часто указывает на то, что другая память повреждена. «Я почти уверен, что не выделяю ни одно из моих объектов, использующих память в это время. –

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