我正在寻找使用 OpenGL 将 4 个图像混合到屏幕上。第一个图像包含背景,其他 3 个图像包含一些具有透明度的卡通。我的目标是一次渲染这 4 张图像。在每次渲染调用时,我都会用新图像更新前 3 个图像以组成新帧。
我是 OpenGL 的新手,到目前为止,我能够实现这些图像的混合,但是我在渲染时注意到了一些可怕的问题。我看到前 3 张图片中的一些有时会丢失,或者有些被渲染,但看起来它们是被隐形人裁剪的......
每条线代表一个不同的图像。
图片裁剪问题:
图像被裁剪并且缺少一张图像:
它应该是什么样子:
任何解决问题的帮助我将不胜感激!在我正在使用的代码下方。
这是我用来渲染图像的代码。
void MoviePreview::prepareTexture (GLuint texture, GLint format, int w, int h)
{
// Bind to generated texture
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glShadeModel(GL_FLAT);
//glShadeModel(GL_SMOOTH);
glTexImage2D(GL_TEXTURE_2D, 0, format, w, h, 0, format, GL_UNSIGNED_BYTE, 0);
if (GL_RGBA == format)
{
//glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
}
// Crop the texture rectangle
GLint rect[] = {0, h, w, -h};
glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_CROP_RECT_OES, rect);
glDrawTexiOES(0, 0, 0, w, h);
}
void MoviePreview::resize (int w, int h)
{
LOGI("native_gl_resize %d %d", w, h);
// init open gl
//glClearColor(1.0, 1.0, 1.0, 1.0);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
glDisable(GL_DITHER);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glDisable(GL_COLOR_MATERIAL);
glDisable(GL_FOG);
glDisable(GL_CULL_FACE);
glDisable(GL_STENCIL_TEST);
glDisable(GL_COLOR_LOGIC_OP);
glDisable(GL_ALPHA_TEST);
//glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);//NEW
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);//NEW
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_DST_ALPHA);
// Generate one texture object
glGenTextures(MAX_TEXTURES, mTexture);
check_gl_error("glGenTextures");
int frameHeight = h;//image.rows;
int frameWidth = w;//image.cols;
// first texture is our background texture
prepareTexture(mTexture[0], GL_RGBA, mBg.cols, mBg.rows);
prepareTexture(mTexture[1], GL_RGBA, frameWidth, frameHeight);
prepareTexture(mTexture[2], GL_RGBA, frameWidth, frameHeight);
prepareTexture(mTexture[3], GL_RGBA, frameWidth, frameHeight);
mSurfaceWidth = w;
mSurfaceHeight = h;
}
void MoviePreview::render (int64_t* imageIds, const int images)
{
int i = 0;
double sleepDuration = 0;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// TODO try to see if we can just get away from always loading the bg
// since it doesn't change often might be worth loading it once and that
// is it...
//glBindTexture(GL_TEXTURE_2D, mTexture[0]);
//glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, mBg.cols, mBg.rows, GL_RGBA, GL_UNSIGNED_BYTE, mBg.ptr());
//glDrawTexiOES(0, 0, 0, mSurfaceWidth, mSurfaceHeight);
// TODO pass the image batch loader
// load images
for (i=0; i<images; i++)
{
if (0 < imageIds[i])
{
sprintf(mTempPath, "%s/f1_%lld.png",mProjectPath.c_str(), imageIds[i]);
mImageLoader[i].loadImage(mTempPath);
}
}
if (0 < mFrameDuration)
{
// here we try to control the suggested frame rate
// set. We calculate since the last show image time
// if we should sleep or not...
if (0 < mLastDrawTimestamp) {
sleepDuration = mFrameDuration - (now_ms() - mLastDrawTimestamp);
}
if (0 < sleepDuration) {
usleep((long)sleepDuration*NANO_IN_MS);
}
}
// draw images
i = 0;
for (i=0; i<images; i++)
{
if (0 < imageIds[i])
{
cv::Mat img = mImageLoader[i].getImage();
if (!img.empty())
{
glBindTexture(GL_TEXTURE_2D, mTexture[i+1]);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, img.cols, img.rows, GL_RGBA, GL_UNSIGNED_BYTE, img.ptr());
glDrawTexiOES(0, 0, 0, img.cols, img.rows);
}
}
}
mLastDrawTimestamp = now_ms();
}