2012-05-15 2 views
2

Я пытаюсь написать пользовательский интерфейс в OpenGL и столкнулся с проблемой при изменении размера элемента управления.Буферы повреждены?

Texture errors

Как я сжать панель, текст текстуры, кажется, уменьшить или испорчена и в конечном итоге кнопки сделать то же самое. Кнопки не привязаны к размеру окна, поэтому проблема заключается не в вычислении размеров. Я напечатал размер текстуры текста и размеры кнопок, и они остались неизменными во время теста.

Таким образом, каждый раз, когда я изменить размер окна, вот что происходит:

onResize 
    Delete TexturedRectangle object 
     | Delete 9 sprites (including vertex data) used for the TexturedRectangle 
     | Delete the RenderTexture 
    New TexturedRectangle Object 
     | Create 9 sprites (new vertex data) for the textured rectangle 
     | Render the rectangle using the 9 sprites to a new RenderTexture the size of the window 

Я прошел через код и убедился, что я удалить старые данные с графическим процессором, прежде чем создавать новые буферы. Являются ли мои буферы повреждены или я неверно отношусь к RenderTextures? Я проверил glGetError() и не получил ошибок во время выполнения. Может ли проблема быть в стеке OpenGL? Я не могу сказать, где проблема, потому что кнопки не меняются вообще при изменении размера окна.

Sprite::Sprite() 
    : ISprite(), mVbo(0) { 
    mDiffuse = ResourceCache::getSingleton().getTexture("Texture_NOTFOUND"); 
    createVbo(); 
} 

Sprite::Sprite(ITexture *diffuse, FloatRect textureBounds) 
    : ISprite(), mVbo(0) { 
    mDiffuse = diffuse; 

    if(textureBounds.x == 0 && textureBounds.y == 0) { 
     mTextureBounds = diffuse->getBounds(); 
    } else { 
     mTextureBounds = textureBounds; 
    } 

    createVbo(); 
} 

Sprite::~Sprite() { 
    glDeleteBuffers(1, &mVbo); 
} 

void Sprite::draw(IRenderTarget *target, RenderState *state) const { 
    glEnableClientState(GL_VERTEX_ARRAY); 
    glEnableClientState(GL_TEXTURE_COORD_ARRAY); 

    glBindBuffer(GL_ARRAY_BUFFER, mVbo); 

    switch(state->getRenderMode()) { 
    default: 
    case RenderState::DIFFUSE: 
     mDiffuse->bindTexture(); 
     break; 
    case RenderState::NORMAL_MAP: 
     mNormalMap->bindTexture(); 
     break; 
    case RenderState::HEIGHT_MAP: 
     mHeightMap->bindTexture(); 
     break; 
    }; 

    glPushMatrix(); 
    glTranslatef(mPosition.x, mPosition.y, mPosition.z); 
    glColor4f(mColor.r, mColor.g, mColor.b, mColor.a); 

    glVertexPointer(3, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, x)); 
    glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, tx)); 

    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); 

    glPopMatrix(); 

    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
    glDisableClientState(GL_VERTEX_ARRAY); 
} 

void Sprite::createVbo() { 
    if(mVbo != 0) { 
     glDeleteBuffers(1, &mVbo); 
    } 

    // Generate the VBO 
    glGenBuffers(1, &mVbo); 
    Vector2f size = getSize(); 

    float texW = mDiffuse->getWidth(); 
    float texH = mDiffuse->getHeight(); 
    float srcW = size.x/texW; 
    float srcH = size.y/texH; 


    // Calculate the vertices 
    Vertex verts[] = {{0.f, 0.f, 0.f, mTextureBounds.x/texW, mTextureBounds.y/texH}, 
         {size.x, 0.f, 0.f, (mTextureBounds.x/texW) + srcW, mTextureBounds.y/texH}, 
         {0.f, size.y, 0.f, mTextureBounds.x/texW, (mTextureBounds.y/texH) + srcH}, 
         {size.x, size.y, 0.f, (mTextureBounds.x/texW) + srcW, (mTextureBounds.y/texH) + srcH}}; 

    int vertSize = sizeof(verts); 

    // Bind the VBO 
    glBindBuffer(GL_ARRAY_BUFFER, mVbo); 

    // Submit the vertex data to the GPU 
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * 4, &verts[0].x, GL_STATIC_DRAW_ARB); 

    // Unbind the VBO 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
} 

Повторяя Sprite

RepeatingSprite::RepeatingSprite(Texture *diffuseTexture, FloatRect spriteBounds, int xRepeat, int yRepeat) 
    : ISprite(), mXRepeat(xRepeat), mYRepeat(yRepeat) { 
    mVbo = 0; 
    mDiffuse = diffuseTexture; 
    mTextureBounds = spriteBounds; 
    createVbo(); 
} 

RepeatingSprite::~RepeatingSprite() { 
    glDeleteBuffers(1, &mVbo); 
} 



void RepeatingSprite::draw(IRenderTarget *target, RenderState *state) const { 
    glEnableClientState(GL_VERTEX_ARRAY); 
    glEnableClientState(GL_TEXTURE_COORD_ARRAY); 

    glBindBuffer(GL_ARRAY_BUFFER, mVbo); 

    switch(state->getRenderMode()) { 
    default: 
    case RenderState::DIFFUSE: 
     mDiffuse->bindTexture(); 
     break; 
    case RenderState::NORMAL_MAP: 
     mNormalMap->bindTexture(); 
     break; 
    case RenderState::HEIGHT_MAP: 
     mHeightMap->bindTexture(); 
     break; 
    }; 

    glPushMatrix(); 
    glTranslatef(mPosition.x, mPosition.y, mPosition.z); 
    glColor4f(mColor.r, mColor.g, mColor.b, mColor.a); 

    glVertexPointer(3, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, x)); 
    glTexCoordPointer(2, GL_FLOAT, sizeof(Vertex), (void*)offsetof(Vertex, tx)); 

    glDrawArrays(GL_QUADS, 0, (mXRepeat * mYRepeat) * 4); 

    glPopMatrix(); 

    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glDisableClientState(GL_TEXTURE_COORD_ARRAY); 
    glDisableClientState(GL_VERTEX_ARRAY); 
} 

void RepeatingSprite::createVbo() { 
    int totalRepeats = mXRepeat * mYRepeat; 
    float textureWidth = mDiffuse->getWidth(); 
    float textureHeight = mDiffuse->getHeight(); 
    Vertex *vertices = new Vertex[totalRepeats*4]; 

    int counter = 0; 
    // For each sprite count, create a quad 
    for(float y = 0; y < mYRepeat; y++) { 
     for(float x = 0; x < mXRepeat; x++) { 

      Vertex v1 = {x * mTextureBounds.w, 
         y * mTextureBounds.h, 0.f, 
         mTextureBounds.x/textureWidth, 
         mTextureBounds.y/textureHeight}; 

      Vertex v2 = {x * mTextureBounds.w + mTextureBounds.w, 
         y * mTextureBounds.h, 0.f, 
         (mTextureBounds.x/textureWidth) + (mTextureBounds.w/textureWidth), 
         mTextureBounds.y/textureHeight}; 

      Vertex v3 = {x * mTextureBounds.w, 
         y * mTextureBounds.h + mTextureBounds.h, 0.f, 
         mTextureBounds.x/textureWidth, 
         (mTextureBounds.y/textureHeight) + (mTextureBounds.h/textureHeight)}; 

      Vertex v4 = {x * mTextureBounds.w + mTextureBounds.w, 
         y * mTextureBounds.h + mTextureBounds.h, 0.f, 
         (mTextureBounds.x/textureWidth) + (mTextureBounds.w/textureWidth), 
         (mTextureBounds.y/textureHeight) + (mTextureBounds.h/textureHeight)}; 


      vertices[counter] = v1; 
      counter++; 
      vertices[counter] = v2; 
      counter++; 
      vertices[counter] = v4; 
      counter++; 
      vertices[counter] = v3; 
      counter++; 
     } 
    } 

    glGenBuffers(1, &mVbo); 

    glBindBuffer(GL_ARRAY_BUFFER, mVbo); 

    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertex) * (totalRepeats*4), &vertices[0].x, GL_STATIC_DRAW_ARB); 

    glBindBuffer(GL_ARRAY_BUFFER, 0); 

    delete[] vertices; 
} 

Рендер текстура

RenderTexture::RenderTexture(float width, float height) { 
    mWidth = width; 
    mHeight = height; 

    // Create the color buffer 
    glGenTextures(1, &mId); 
    glBindTexture(GL_TEXTURE_2D, mId); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (int)mWidth, (int)mHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); 
    glBindTexture(GL_TEXTURE_2D, 0); 

    // Create the framebuffer 
    glGenFramebuffers(1, &mFbo); 
    glBindFramebuffer(GL_FRAMEBUFFER, mFbo); 

    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mId, 0); 

    GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER); 
    assert(err == GL_FRAMEBUFFER_COMPLETE); // Make sure texture is valid 

    glBindFramebuffer(GL_FRAMEBUFFER, 0); 
} 

RenderTexture::~RenderTexture() { 
    glDeleteBuffers(1, &mFbo); 
    glDeleteTextures(1, &mId); 
    mFbo = 0; 
} 


void RenderTexture::preDraw() { 
    // store the glViewport and glEnable states 
    glPushAttrib(GL_VIEWPORT_BIT); 

    // Bind the frame buffer 
    //glBindTexture(GL_TEXTURE_2D, 0); 
    glBindFramebuffer(GL_FRAMEBUFFER, mFbo); 

    // Save the current matrix 
    glPushMatrix(); 
    glLoadIdentity(); 

    // Setup the projection matrix for the render target 
    glMatrixMode(GL_PROJECTION); 
    glPushMatrix(); 
    glLoadIdentity(); 
    glViewport(0, 0, (int)mWidth, (int)mHeight); 
    glOrtho(0, mWidth, 0.f, mHeight, 0.f, 100.f); 

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); 
    glDrawBuffer(GL_COLOR_ATTACHMENT0); 
} 

void RenderTexture::postDraw() { 
    // Pop the render target's projection matrix off the stack 
    glPopMatrix(); 
    // Restore previouse projection matrix 
    glPopMatrix(); 
    glBindFramebuffer(GL_FRAMEBUFFER, 0); 
    // Restore the previous viewport settings 
    glPopAttrib(); 
} 
+0

С о д е е я р с т. – vines

ответ

2

В OpenGL, когда вы применяете преобразование некоторого вида на объект и увидеть другие объекты, которые пострадали, хорошее место начать искать - ваша логика преобразования и стека.

Так RenderTexture::preDraw() у вас есть:

glPushMatrix(); 
// ... 
glMatrixMode(GL_PROJECTION); 
glPushMatrix(); 

и RenderTexture::postDraw():

glPopMatrix(); 
// Restore previouse projection matrix 
glPopMatrix(); 

без вызова glMatrixMode() между ними.

Это не сработает должным образом. Каждый матричный режим имеет свой собственный стек, так что второй glPopMatrix() выталкивает неправильный стек.

Вам нужно будет идти что-то вроде:

glPopMatrix(); 
glMatrixMode(GL_MODELVIEW); 
glPopMatrix(); 
Смежные вопросы