在 OpenGL 4.6 中没有适合我的 alpha 混合

Posted

技术标签:

【中文标题】在 OpenGL 4.6 中没有适合我的 alpha 混合【英文标题】:No alpha blending working for me in OpenGL 4.6 【发布时间】:2019-01-12 10:36:37 【问题描述】:

我正在使用 OpenGL 和 460 版着色器开发粒子系统,这些着色器编译为 SPIR-V。

我的粒子基于带有 alpha 的 PNG 纹理,它实际上非常简单,我之前在早期的 OpenGL 版本上做过。

但是,输出窗口中的粒子仍然是一个正方形,边角是黑色的——也就是说,alpha 通道被绘制为黑色。我使用了不同的 PNG 文件,其中一个带有 alpha 上的灰色或黑色上的灰色的粒子。我在片段着色器中将第四个组件设置为 0.0 或 0.5 以查看任何变化,但没有任何变化。我尝试更改 loadTexture 函数中的格式,但还是一样。

我尝试了各种不同的混合模式并改变了线条的顺序。我在 RenderDoc 中注意到目标混合被禁用。但是将 glEnable(GL_BLEND) 更改为另一个位置并没有帮助。

非常感谢您的帮助!

// init stuff
glEnable(GL_POINT_SPRITE);
initbasicShaders(); // vertex, fragment
initTexture();
...

void application::initTexture()

    m_ParticleTex = Texture(); // empty constructor
    m_ParticleTex.loadTexture(TEXTURE_PATH);

    GLint baseImageLoc = glGetUniformLocation(m_RenderProgramHandle, "u_Texture");
    glUseProgram(m_RenderProgramHandle);
    glUniform1i(baseImageLoc, 0); 
    glActiveTexture(GL_TEXTURE0 + 0);
    glBindTexture(GL_TEXTURE_2D, m_ParticleTex.getTextureID());


// using the library stb_image
void Texture::loadTexture(const char* fileName)

    int channels, width, height;
    unsigned char * localBuffer;
    m_FilePath = fileName;

    localBuffer = stbi_load(fileName, &width, &height, &channels, 4);

    glGenTextures(1, &m_TextureID);
    glBindTexture(GL_TEXTURE_2D, m_TextureID);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, localBuffer);
    glBindTexture(GL_TEXTURE_2D, 0);

    if (localBuffer) 
        stbi_image_free(localBuffer);
    


...
...
...
// Now - the render loop:
void application::runOpenGLBuffer()

    Log::logInfoRun(m_Name, "OpenGL buffer");
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
    glEnable(GL_POINT_SMOOTH);
    glDisable(GL_DEPTH_TEST);
    glEnable(GL_ALPHA_TEST);

    glPointSize(PARTICLE_SIZE);
    glHint(GL_POINT_SMOOTH_HINT, GL_NICEST);

        glUseProgram(m_RenderProgramHandle);
    this->updateTextures();
        glDrawArrays(GL_POINTS, 0, NUM_PARTICLES);



...
// and the fragment shader
#version 460
#extension GL_ARB_separate_shader_objects : enable

layout(std430, binding = 3) buffer density_block

    float density[];
;

void main()

// densitColor is just a variable color from density
    vec4 particleColor = vec4(texture(u_Texture, gl_PointCoord) * densityColor);
    color = particleColor;

这里是渲染帧中的输出和来自 RenderDoc 的信息:

【问题讨论】:

【参考方案1】:

glEnable 的参数(如GL_BLENDGL_POINT_SMOOTH)是枚举数常量,而不是位字段的位。 | 运算符不能连接不同的枚举数常量。每个状态都必须单独启用:

glEnable(GL_BLEND | GL_POINT_SMOOTH);glEnable(GL_BLEND);glEnable(GL_POINT_SMOOTH);

注意,按位或运算通过对两个值的每一位执行“或”来计算新值。结果可能对glEnable 没有任何意义。这会导致您的代码中既没有启用GL_BLEND 也没有启用GL_POINT_SMOOTH

【讨论】:

感谢@Rabbid76 的提示,我更改了它。不幸的是,它并没有解决问题。我会在这里编辑它,让其他人不用担心。 我也想知道 glEnable(GL_POINT_SPRITE);如果我不设置它什么都不会显示。但据我所知,这是一个遗留功能。

以上是关于在 OpenGL 4.6 中没有适合我的 alpha 混合的主要内容,如果未能解决你的问题,请参考以下文章

个人作业3——个人总结(Alphe)

Qt 4.6 OpenGL GLSL

使用 SDL2 和 xcode 4.6。我设法创建了一个 OpenGL 3.2 核心上下文。但是不能使用 glsl 1.50

Unity 4.6 - 如何将 GUI 元素缩放到适合每个分辨率的大小

OpenGL 裁剪

关于OpenGL的一个not support 3.3.的问题的记录