我就是这么做的:
- 渲染第一张图片,使用颜色:
glColor4f(1.0, 1.0, 1.0, 1.0);
- 渲染第二张图片,使用颜色:
glColor4f(1.0, 1.0, 1.0, calc);
。calc
是一个在一秒内从0.0到1.0的数字,我可以验证它确实这样做了。
我期望它做的是从一个图像到另一个图像褪色,它做到了这一点,但中途,它进入某种灰色阴影(黑色是背景色,顺便说一句)。您可以在这里看到问题:http://www.youtube.com/watch?v=8dZXiYIM43s&feature=youtu.be .
我只是想要基本的褪色,没有的灰色调,当在褪色的中间(这是最强的在0.5不透明度)。我试过用GIMP这样做,底层是不透明的,顶层是可变的不透明度,它工作得很好,它确实正是我想要它做的,我只是不知道为什么我的代码(或OpenGL)不会做同样的事情。一个演示我意思的视频:http://www.youtube.com/watch?v=Ym-VPu9hhjQ&feature=youtu.be
EDIT:经过一些实验(将背景颜色更改为红色),在0.5时,它变成半透明的,这通常是想要的效果,除了两个纹理都是半透明的(不仅仅是顶部的)。为什么会这样?
代码如下:
void Sprite::render_single(Image* image, Pos2D pos, Angle angle) {
int cx = image->width / 2;
int cy = image->height / 2;
glPushMatrix();
glTranslatef(pos.x + cx, pos.y + cy, 0);
glRotatef(angle.to_degrees(), 0.0, 0.0, 1.0);
glTranslatef(-cx, -cy, 0);
image->bind();
glBegin(GL_QUADS);
glTexCoord2f(0.0, 0.0);
glVertex2f(0.0, 0.0);
glTexCoord2f(1.0, 0.0);
glVertex2f(image->width, 0.0);
glTexCoord2f(1.0, 1.0);
glVertex2f(image->width, image->height);
glTexCoord2f(0.0, 1.0);
glVertex2f(0.0, image->height);
glEnd();
image->unbind();
glPopMatrix();
}
void Sprite::render(Pos2D pos, Angle angle) {
Image* img = this->get_current_frame();
if (this->images.size() == 1) {
this->render_single(img, pos, angle);
return;
}
double calc = (((double)this->current_frame_overflow) / this->frame_length);
std::cout << calc << std::endl;
glPushMatrix();
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
this->render_single(img, pos, angle);
img = this->get_next_frame();
glColor4f(1.0f, 1.0f, 1.0f, calc);
this->render_single(img, pos, angle);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glPopMatrix();
}
使用的混合函数:glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
OpenGL初始化函数
/**
* @brief Initializes OpenGL
*/
void Game::init_gl() {
float width = this->display->w;
float height = this->display->h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, width, height, 0.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
另外,这里是主循环的整个源代码(其中包含大多数OpenGL的东西):https://github.com/MiJyn/dbab/blob/master/src/game.cpp。精灵:https://github.com/MiJyn/dbab/blob/master/src/sprite.cpp .
当您使用glBlendFunc
函数(启用混合)时,使用相同的因素来计算目标片段的alpha值。
只有当你渲染到一个有alpha通道的纹理,然后在启用混合的情况下使用该纹理时,这才重要。在这种情况下,渲染纹理的alpha通道以0到1之间的值结束。当纹理被绘制到后面的缓冲区时,这会导致一些背景溢出。
解决方案就是在绘制全屏四边形时禁用混合。此外,如果你不使用它,你也可以从纹理中删除通道(使用GL_RGB
而不是GL_RGBA
作为内部纹理格式)。
灰色边缘是不使用预乘法alpha的副作用。
尝试使用glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
来启用预乘法alpha。查找预乘法获取更多信息,但基本上所有的纹理和颜色都需要预乘法。简而言之,你遍遍每个像素和颜色,并将r, g和b乘以a。所以你将50%的白色作为(1,1,1,0.5),现在它变成了(0.5,0.5,0.5,0.5)。在这种情况下,你的目标颜色也需要是(calc, calc, calc, calc)。