OpenGL淡出问题



我就是这么做的:

  • 渲染第一张图片,使用颜色: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)。

最新更新