glBlendFunc : transparency conflict using .png Sprites and glCreateShader lights

Started by thw, November 26, 2014, 08:36:16

Previous topic - Next topic

thw

Hello,

To resume my problem :
I'm using basic Sprite-sheets with alpha transparency. I also wish to use light/color effects with shaders. My problem is with (or seems to be with) glBlendFunc :
In the main gl setup, glBlendFunc(GL_ONE, GL_ONE) works fine for lights with glCreateShader(GL_FRAGMENT_SHADER) but all Sprites have transparency when overlapping. With glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA), Sprites are fine but "shader lights" don't display correctly.

I'm trying to find the correct way to setup gl for both these aspects. I've tried many different params in glBlendFunc without success. My code examples bellow :

My main gl setup with call to shader lights setup at end :
            Display.create();
            
            // enable textures since : used sprites.
            glEnable(GL_TEXTURE_2D);

            // disable the OpenGL depth test : rendering 2D graphics
            glDisable(GL_DEPTH_TEST);

            glMatrixMode(GL_PROJECTION);
            glEnable(GL_BLEND); 
            
            // this call to Blend makes lights work:
            glBlendFunc(GL_ONE, GL_ONE);
            // this call to blend is good for sprites but not for lights:
            //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
            
            glLoadIdentity();

            glOrtho(0, FrameConst.FRM_WIDTH_800, FrameConst.FRM_HEIGHT_600, 0, -1, 1);
            glMatrixMode(GL_MODELVIEW);
            glLoadIdentity();
            glViewport(0, 0, FrameConst.FRM_WIDTH_800, FrameConst.FRM_HEIGHT_600);
            
            glLightHelper.initGLLightRendering(GLLightHelper.SHADER1);
            //------- TEST : --------------//
            glLightHelper.lightEntities.put("test",
                new GLLight(new Vector2f(300.0f, 300.0f), 1.0f, 5.0f, 10.0f));
            // END TEST


Init for light rendenring with shader :
public void initGLLightRendering(final String shaderPath) throws GLLightHelperException {

        shaderProgram = glCreateProgram();
        fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
        final StringBuilder fragmentShaderSource = new StringBuilder();
        try {
            String line;
            BufferedReader reader = new BufferedReader(new FileReader(shaderPath));
            while ((line = reader.readLine()) != null) {
                fragmentShaderSource.append(line).append("\n");
            }
        } catch (final FileNotFoundException fnfe) {
            Logger.getLogger(GLLightHelper.class.getName()).log(Level.SEVERE, null, fnfe);
        } catch (final IOException ioe) {
            Logger.getLogger(GLLightHelper.class.getName()).log(Level.SEVERE, null, ioe);
        }
        glShaderSource(fragmentShader, fragmentShaderSource);
        glCompileShader(fragmentShader);
        if (glGetShaderi(fragmentShader, GL_COMPILE_STATUS) == GL_FALSE) {
            throw new GLLightHelperException("Fragment shader compilation failed.");
        }
        glAttachShader(shaderProgram, fragmentShader);
        glLinkProgram(shaderProgram);
        glValidateProgram(shaderProgram);
        glEnable(GL_STENCIL_TEST);
        glClearColor(0, 0, 0, 0);
    }


Light rendering method :
public void renderLights() {

        for (GLLight light : this.lightEntities.values()) {
            
            glColorMask(false, false, false, false);
            glStencilFunc(GL_ALWAYS, 1, 1);
            glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
            glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
            glStencilFunc(GL_EQUAL, 0, 1);
            glColorMask(true, true, true, true);
            glUseProgram(shaderProgram);
            glUniform2f(glGetUniformLocation(shaderProgram, "lightLocation"),
                light.location.getX(), FRAME_HEIGHT - light.location.getY());
            glUniform3f(glGetUniformLocation(shaderProgram, "lightColor"),
                light.red, light.green, light.blue);
            //glEnable(GL_BLEND); // Already activated (see Game.init()).
            //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // OK for textures but no lights.
            //glBlendFunc(GL_ONE, GL_ONE); // OK for lights but to much alpha on textures.
            glBegin(GL_QUADS);
            {
                glVertex2f(0, 0);
                glVertex2f(0, FRAME_HEIGHT);
                glVertex2f(FRAME_WIDTH, FRAME_HEIGHT);
                glVertex2f(FRAME_WIDTH, 0);
            }
            glEnd();
            glUseProgram(0);
            glClear(GL_STENCIL_BUFFER_BIT);
        }
        glColor3f(0, 0, 0);
    }


POJO class for lights :
public class GLLight {

    public Vector2f location;
    public float red;
    public float green;
    public float blue;

    public GLLight(Vector2f location, float red, float green, float blue) {
        this.location = location;
        this.red = red;
        this.green = green;
        this.blue = blue;
    }

}


Finaly, shader fragment :
uniform vec2 lightLocation;
uniform vec3 lightColor;
uniform float screenHeight;
void main() {
float distance = length(lightLocation - gl_FragCoord.xy);
float attenuation = 1.0 / (distance * 2); // Also try 1.0 / distance;
vec4 color = vec4(attenuation, attenuation, attenuation, pow(attenuation, 3)) * vec4(lightColor, 1);
gl_FragColor = color;
}


I am obviously new to OPENGL and LWJGL. I'm very gratefull for any help/advice or links to documentation of any kind on the subject.


spasi

The first thing I recommended to anyone having trouble with blending is to read this Premultiplied alpha.

thw

Thanks!,

Highly interesting article. Need to read the article again + read Porter & Duff's "composing digital images" 1984 paper to digest it : S

I have more (off topic) questions :

  • Is this OpenGL 4.5 man/doc relevant when using lwjgl 2.9.1 with java ? : https://www.opengl.org/sdk/docs/man/
  • I still don't understand why using shaders and glBlendFunc(GL_ONE, GL_ONE) has impact on textures/sprite-sheets transparency ? Obvioulsy, as said on the left side, i'm a open gl newbie : D That's fine with me, but where is the starting point for leaning OPEN GL from scratch (Java, C++ what ever...) ? Basicly i'm using 'stuff' I don't understand, what's the best doc/book/anything to understand what's happening behind all the glThisThat() static calls ?

I'm keen to learn, just a bit lost and don't want to wast time reading the wrong stuff.
All the best, tom.

spasi

Quote from: thw on November 26, 2014, 17:42:52Is this OpenGL 4.5 man/doc relevant when using lwjgl 2.9.1 with java ? : https://www.opengl.org/sdk/docs/man/

Yes.

Quote from: thw on November 26, 2014, 17:42:52I still don't understand why using shaders and glBlendFunc(GL_ONE, GL_ONE) has impact on textures/sprite-sheets transparency ? Obvioulsy, as said on the left side, i'm a open gl newbie : D That's fine with me, but where is the starting point for leaning OPEN GL from scratch (Java, C++ what ever...) ? Basicly i'm using 'stuff' I don't understand, what's the best doc/book/anything to understand what's happening behind all the glThisThat() static calls ?

Blending is global OpenGL state, which means it affects anything you render. In order to understand the impact, you need to figure out where blending fits in the rendering pipeline and how BlendFunc can be used to configure it.

Some resources for learning:

- The official OpenGL reference.
- docs.gl, unofficial OpenGL reference with more information (e.g. example code).
- glisdeprecated.com, quickly find if something has been deprecated.
- The Learning Modern 3D Graphics Programming ebook. <<< This is probably the best place to start
- The OpenGL Samples Pack by G-Truc.
- A extensive list of blogs related to real-time rendering.