Search code examples
javaopenglglslshaderlwjgl

Transparency issues with LWJGL "discard", everything is invisible?


When I attempt to implement transparency for my textures in LWJGL 3, the models seem to render with full transparency, and thus are not visible at all. When I remove the check, it works fine. Any clue's as to why?

Here is the shader code where the alpha component is checked:

#version 430

in vec2 pass_textureCoords;
in vec3 surfaceNormal;
in vec3 toLightVector[5];
in vec3 toCameraVector;
in float visibility;

out vec4 out_Color;

uniform sampler2D textureSampler;
uniform vec3 lightColour[5];
uniform vec3 attenuation[5];
uniform float shineDamper;
uniform float reflectivity;
uniform vec3 skyColour;

void main(void) {

    vec3 unitNormal = normalize(surfaceNormal);
    vec3 unitVectorToCamera = normalize(toCameraVector);

    vec3 totalDiffuse = vec3(0.0);
    vec3 totalSpecular = vec3(0.0);

    for (int i = 0; i < 5; i++) {
        float distance = length(toLightVector[i]);
        float attFactor = attenuation[i].x + (attenuation[i].y * distance) + (attenuation[i].z * distance * distance);
        vec3 unitLightVector = normalize(toLightVector[i]);
        float nDot1 = dot(unitNormal, unitLightVector);
        float brightness = max(nDot1, 0.0);
        vec3 lightDirection = -unitLightVector;
        vec3 reflectedLightDirection = reflect(lightDirection, unitNormal);
        float specularFactor = dot(reflectedLightDirection, unitVectorToCamera);
        specularFactor = max(specularFactor, 0.0);
        float dampedFactor = pow(specularFactor, shineDamper);
        totalDiffuse = totalDiffuse + (brightness * lightColour[i])/attFactor;
        totalSpecular = totalSpecular + (dampedFactor * reflectivity * lightColour[i])/attFactor;
    }
    totalDiffuse = max(totalDiffuse, 0.2);


////////////////////////////////////////////////////////////////////////////
    vec4 textureColour = texture(textureSampler, pass_textureCoords);
    if (textureColour.a < 0.5) {
        discard;
    }
////////////////////////////////////////////////////////////////////////////

    out_Color = vec4(totalDiffuse, 1.0) * textureColour + vec4(totalSpecular, 1.0);
    out_Color = mix(vec4(skyColour,1.0),out_Color, visibility);

}

I've triple checked everything is loaded up to the shader in the correct order ect. but the only way to make the textures appear is to remove this check.

Anything else of use, please ask. Thanks!

EDIT 1:

Loading the texture from an image:

protected Texture loadTexture(BufferedImage image, String info) {
    Texture texture;

    int width = image.getWidth();
    int height = image.getHeight();
    int[] pixels = image.getRGB(0, 0, width, height, null, 0, width);

    ByteBuffer buffer = BufferUtils.createByteBuffer((width * height) * 4);
    int id = glGenTextures();

    for (int i = 0; i < pixels.length; i++) {
        byte r = (byte)((pixels[i] >> 16) & 0xFF);
        byte g = (byte)((pixels[i] >> 8) & 0xFF);
        byte b = (byte)(pixels[i] & 0xFF);
        byte a = (byte)((pixels[i] >> 24) * 0xFF);
        buffer.put(r);
        buffer.put(g);
        buffer.put(b);
        buffer.put(a);
    }
    buffer.flip();
    glBindTexture(GL_TEXTURE_2D, id);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    glBindTexture(GL_TEXTURE_2D, 0);

    texture = new Texture(id, buffer, width, height);
    if (info != "") processData(info, texture);
    return texture;
}

EDIT 2:

After trying Out_Color = vec4(textureColour.aaa, 1.0);

enter image description here


Solution

  • It was a simple fix as suggested by Rabbid76 that the alpha channel was getting lost when reading the image to a pixels array. Instead, i now use:

        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                int pixel = image.getRGB(x, y);
                byte alpha = (byte)((pixel >> 24) & 0xff);
                byte red = (byte)((pixel >> 16) & 0xff);
                byte green = (byte)((pixel >> 8) & 0xff);
                byte blue = (byte)((pixel >> 0) & 0xff);
                buffer.put(red);
                buffer.put(green);
                buffer.put(blue);
                buffer.put(alpha);
            }
        }
    

    which works perfectly!