opengl 如何用lwjgl绘制半透明/透明纹理?

eiee3dmh  于 2022-11-23  发布在  其他
关注(0)|答案(1)|浏览(208)

我花了很多时间试图找出如何在屏幕上绘制透明纹理,但我的代码似乎不起作用。到目前为止,只有完全不透明的纹理才能正常绘制(如下图的背景)。正如你在下图中看到的,透明部分被红色填充,而不是透明的。(我使用paint.net来绘制透明度,对吗?)
编辑(也使用新代码):现在透明的部分已经消失了,但是有一个红色的小轮廓,就像下面的图像,那里有半透明的像素。我如何使它也呈现为透明的?而且,我不明白为什么设置 glClearColor 的alpha不会改变任何东西。

我将 glClearColor 设置为红色,但Alpha为0。

GL11.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);

下面是我绘制纹理的代码(使用 slick-util):

PNGDecoder decoder = null;
        try {
            decoder = new PNGDecoder(new FileInputStream(Main.projectPath + path));
        } catch (FileNotFoundException e1) {
            e1.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        ByteBuffer buffer = ByteBuffer.allocateDirect(4 * decoder.getWidth() * decoder.getHeight());

        try {
            decoder.decode(buffer, decoder.getWidth() * 4, PNGDecoder.RGBA);
        } catch (IOException e) {
            e.printStackTrace();
        }

        buffer.flip();

        int id = GL13.glGenTextures();

        GL13.glBindTexture(GL13.GL_TEXTURE_2D, id);

        GL13.glPixelStorei(GL13.GL_UNPACK_ALIGNMENT, 1);

        GL13.glTexParameterf(GL13.GL_TEXTURE_2D, GL13.GL_TEXTURE_MIN_FILTER, GL13.GL_NEAREST);
        GL13.glTexParameterf(GL13.GL_TEXTURE_2D, GL13.GL_TEXTURE_MAG_FILTER, GL13.GL_NEAREST);
        
        width = decoder.getWidth();
        height = decoder.getHeight();
        GL13.glTexImage2D(GL13.GL_TEXTURE_2D, 0, GL13.GL_RGBA, decoder.getWidth(), decoder.getHeight(), 0, GL13.GL_RGBA, GL13.GL_UNSIGNED_BYTE, buffer);

        GL30.glGenerateMipmap(GL13.GL_TEXTURE_2D);
        
        GL13.glTexParameteri(GL13.GL_TEXTURE_2D, GL13.GL_TEXTURE_WRAP_S, GL13.GL_RGBA);
        GL13.glTexParameteri(GL13.GL_TEXTURE_2D, GL13.GL_TEXTURE_WRAP_T, GL13.GL_RGBA);
        GL13.glTexParameteri(GL13.GL_TEXTURE_2D, GL13.GL_TEXTURE_MIN_FILTER, GL13.GL_NEAREST_MIPMAP_NEAREST);
        GL13.glTexParameteri(GL13.GL_TEXTURE_2D, GL13.GL_TEXTURE_MAG_FILTER,GL13. GL_NEAREST);

        this.texture = new Texture(id);
        this.textureID =  id;

下面是我在屏幕上渲染纹理的代码:

public void renderMesh(Mesh mesh) {
    GL30.glBindVertexArray(mesh.getVAO());
    GL30.glEnableVertexAttribArray(0);
    GL30.glEnableVertexAttribArray(1);
    GL30.glEnableVertexAttribArray(2);
    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, mesh.getIBO());
    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL13.glBindTexture(GL11.GL_TEXTURE_2D, mesh.getMaterial().getTextureID());
    shader.bind();
    GL11.glDrawElements(GL11.GL_TRIANGLES, mesh.getIndices().length, GL11.GL_UNSIGNED_INT, 0);
    shader.unbind();
    GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
    GL30.glDisableVertexAttribArray(0);
    GL30.glDisableVertexAttribArray(1);
    GL30.glDisableVertexAttribArray(2);
    GL30.glBindVertexArray(0);
}

我想知道这个代码的错误是什么。
编辑:下面是我的init和着色器代码:初始化代码:

window = GLFW.glfwCreateWindow(width, height, title, isFullscreen ? GLFW.glfwGetPrimaryMonitor() : 0, 0);
    
    if (window == 0) {
        System.err.println("ERROR: Window wasn't created");
        return;
    }
    
    GLFWVidMode videoMode = GLFW.glfwGetVideoMode(GLFW.glfwGetPrimaryMonitor());
    windowPosX[0] = (videoMode.width() - width) / 2;
    windowPosY[0] = (videoMode.height() - height) / 2;
    GLFW.glfwSetWindowPos(window, windowPosX[0], windowPosY[0]);
    GLFW.glfwMakeContextCurrent(window);
    GL.createCapabilities();
    GL11.glEnable(GL11.GL_DEPTH_TEST);
    GL11.glMatrixMode(GL11.GL_TEXTURE);
    GL11.glEnable(GL11.GL_TEXTURE_2D);
    GL11.glEnable(GL11.GL_BLEND);
    GL11.glEnable(GL11.GL_ALPHA_TEST);
    GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
    GL11.glPushMatrix();   
    
    
    createCallbacks();
    
    GLFW.glfwShowWindow(window);
    
    GLFW.glfwSwapInterval(1);

顶点着色器:

#version 460 core

in vec3 position;
in vec4 color;
in vec2 textureCoord;

out vec4 passColor;
out vec2 passTextureCoord;

void main() {
    gl_Position = vec4(position, 1.0);
    passColor = color;
    passTextureCoord = textureCoord;
}

片段着色器:

#version 330 core
out vec4 FragColor;

in vec2 passTextureCoord;

uniform sampler2D texture1;

void main()
{             
    vec4 texColor = texture(texture1, passTextureCoord);
    if(texColor.a < 0.1)
        discard;
    FragColor = texColor;
}
6rvt4ljy

6rvt4ljy1#

为了解决红色轮廓的问题,我认为您需要将丢弃像素的阈值设置得更高一些。
我的怀疑是绘图程序没有绘制完全透明的像素。例如,如果一个像素的alpha值为0.2,它不会被丢弃,尽管它有点透明。然后渲染器试图将它与背景混合,因为它不在顺序中。
像素可能是红色的,因为您将背景颜色设置为红色:

GL11.glClearColor(1.0f, 0.0f, 0.0f, 0.0f);

因此,解决此问题的方法是将对象从后往前排序,或者将片段着色器中的丢弃阈值提高到0.9。

相关问题