OpenGLでUIを作成しようとしていますが、コントロールのサイズを変更すると問題が発生します。
パネルを縮小すると、テキストテクスチャが縮小または破損しているように見え、最終的にボタンも同じように動作します。ボタンはウィンドウのサイズに関連付けられていないため、サイズの計算に問題はありません。テキストテクスチャのサイズとボタンのサイズを印刷しましたが、テスト中は一貫性が保たれていました。
したがって、ウィンドウのサイズを変更するたびに、次のようになります。
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
コードを確認し、新しいバッファーを作成する前に、GPUから古いデータを削除していることを確認しました。バッファが破損していますか、それとも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);
}
スプライトの繰り返し
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();
}