Opengl 透明部分被渲染为黑色

Posted

技术标签:

【中文标题】Opengl 透明部分被渲染为黑色【英文标题】:Opengl transparent parts get rendered black 【发布时间】:2019-10-15 14:41:54 【问题描述】:

我也想使用 OpenGL 在我的屏幕上渲染具有透明部分的纹理,但由于某种原因透明部分显示为黑色。

质地:

截图:

代码是:

#define STB_IMAGE_IMPLEMENTATION
#include <stdio.h>
#include "stdlib.h"
#include "GLFW/glfw3.h"
#include "GL/gl.h"
#include "stb_image.h"

int windowheight;
int windowwidth;

void camera();
void program();

void rendertex(int x, int y, int w, int h)

    glColor4d(255,255,255,255);
    glDisable(GL_COLOR_MATERIAL);
    glEnable(GL_TEXTURE_2D);
    glShadeModel(GL_SMOOTH);
    int width,height,channel;
    auto *data = stbi_load("../textures/isaac.png",&width,&height,&channel,0);
    GLuint texture;
    glGenTextures(1,&texture);
    glBindTexture(GL_TEXTURE_2D,texture);;
    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA, width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,data);

    stbi_image_free(data);

    printf("%d\n",width);
    printf("%d\n",height);
    printf("%d\n",channel);

    glBegin(GL_QUADS);
    glTexCoord2d(0,0);
    glVertex2d(x,y);
    glTexCoord2d(0,1);
    glVertex2d(x,y + h);
    glTexCoord2d(1,1);
    glVertex2d(x + w, y + h);
    glTexCoord2d(1,0);
    glVertex2d(x + w, y);
    glEnd();

    glDisable(GL_TEXTURE_2D);

static void key(GLFWwindow* window, int key, int scancode, int action, int mods)

    switch (key)
    
        case GLFW_KEY_ESCAPE:
            exit(0);
        case GLFW_KEY_UP:
            break;
    


int main()

    glfwInit();
    GLFWwindow* window = glfwCreateWindow(800,800,"t", nullptr, nullptr);
    glfwMakeContextCurrent(window);
    glfwSetKeyCallback(window,key);
    glfwSwapInterval(1);
    glfwGetFramebufferSize(window,&windowwidth,&windowheight);
    glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);

    while (!glfwWindowShouldClose(window))
    
        glfwSwapBuffers(window);
        glfwGetFramebufferSize(window,&windowwidth,&windowheight);
        program();
        camera();
        glfwPollEvents();
    


void program()

    glClearColor(255,255,255,255);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glBegin(GL_LINES);
    glColor4d(255,0,0,0);
    glVertex2d(0,0);
    glVertex2d(windowwidth,windowheight);
    glEnd();
    glFlush();


    rendertex(20,20,400,500);


void camera()

    glViewport(0,0,windowwidth,windowheight);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(0,windowwidth,windowheight,0,0,1);
    glMatrixMode(GL_MODELVIEW);

我已经尝试将一些行注释掉,但没有运气。我正在使用 linux,如果这很重要

编辑:cmakelist.txt

cmake_minimum_required(VERSION 3.15)
project(t)

set(CMAKE_CXX_STANDARD 17)

add_executable(t main.cpp)

target_link_libraries(t GL glfw)

【问题讨论】:

与问题无关,但您可能不需要使用双重版本的调用(例如,将 glVertex2d 替换为 glVertex2f)。 @Killoso32 问题解决了吗?答案可以接受吗? (答案左侧的复选标记) 【参考方案1】:

您必须启用Blending。在混合时,片段的颜色会与帧缓冲区的当前颜色混合,然后再写入帧缓冲区。 颜色的混合方式取决于可以配置的公式。

启用混合并指定根据片段颜色的颜色通道混合颜色:

glEnable(GL_BLEND); 
glBlendEquation(GL_FUNC_ADD); // this is default
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  

注意上面的代码种了以下混合函数(D 表示帧缓冲区颜色,C 片段颜色):

D_rgba = C_rgba * C_alpha - D_rgba * (1 - C_alpha)

另见LearnOpenGL - Blending。


在纹理渲染之前启用混合并在之后禁用它:

void rendertex(int x, int y, int w, int h)

    // [...]


    glEnable(GL_BLEND); 
    glBlendEquation(GL_FUNC_ADD); // this is default
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_TEXTURE_2D);

    glBegin(GL_QUADS);
    glTexCoord2d(0,0);
    glVertex2d(x,y);
    glTexCoord2d(0,1);
    glVertex2d(x,y + h);
    glTexCoord2d(1,1);
    glVertex2d(x + w, y + h);
    glTexCoord2d(1,0);
    glVertex2d(x + w, y);
    glEnd();

    glDisable(GL_TEXTURE_2D);

【讨论】:

@Killoso32 问题解决了吗?答案可以接受吗? (答案左侧的复选标记)

以上是关于Opengl 透明部分被渲染为黑色的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 多重渲染目标 - 黑色输出

Android opengl 画文字,怎么把文字后面的黑色背景去掉

使用 OpenGL 渲染位数组

OpenGL中的完全透明圆环

如何用OpenGL ES 2.0渲染一个透明surface

渲染具有透明度的纹理时 OpenGL 不需要的像素