Rendering Overwriting Transparency When Rendering to Texture When Using Transparency - java

When rendering to a texture (secondary framebuffer) in OpenGL, anything transparent overwrites the transparency of what is below, rather than adding transparency as transparency should. This means if I render a transparent object on top of an existing opaque object, the result is a texture that is transparent, even though it should be opaque.
In this picture, the space is rendered as a background normally, the framebuffer is then changed and opaque blue is then rendered, then, the green/red are rendered. The texture that the framebuffer was rendering to is used to render onto the original framebuffer(the window), and the result is as seen.
Some code:
Framebuffer/Texture Creation:
int texture = glGenTextures();
framebufferID = glGenFramebuffers();
glBindFramebuffer(GL_FRAMEBUFFER,framebufferID);
glBindTexture(GL_TEXTURE_2D, texture);
int width,height;
width = (int)(getMaster().getWindow().getWidth()*(xscale/(16f*getMaster().getGuiCamera().getWidth()))*1.2f);
height = (int)(getMaster().getWindow().getHeight()*(yscale/9f)*1.15f);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture,0);
int depth = glGenTextures();
glBindTexture(GL_TEXTURE_2D, depth);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depth, 0);
this.texture = new Texture(texture,width,height,true);
glDrawBuffer(GL_FRONT_AND_BACK);
The depth buffer here was something I tried to get it to work, but it had no effect on the output texture though.
Render Code:
getMaster().returnToViewportAfterFunction(new Vector2i(texture.getWidth(),texture.getHeight()),
() -> getMaster().returnToFramebufferAfterFunction(framebufferID, () -> {
shapeShader.bind();
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
model.bind();
shapeShader.setUniform("color", 0f, 0f, 1f, 1f); //Blue
shapeShader.setUniform("projection", this.camera.getProjectionForGuiWindow(vec2zero, xscale, yscale));
glDrawElements(GL_TRIANGLES, model.getVerticeCount(), GL_UNSIGNED_INT, 0);
shapeShader.setUniform("color", 0f, 1f, 0f, 0.5f); //Green
shapeShader.setUniform("projection", this.camera.getProjectionForGuiWindow(vec2zero, xscale/2f, yscale/2f));
glDrawElements(GL_TRIANGLES, model.getVerticeCount(), GL_UNSIGNED_INT, 0);
shapeShader.setUniform("color", 1f, 0f, 0f, .2f); //Red
shapeShader.setUniform("projection", this.camera.getProjectionForGuiWindow(vec2zero, xscale/4f, yscale/2f));
glDrawElements(GL_TRIANGLES, model.getVerticeCount(), GL_UNSIGNED_INT, 0);
glDisable(GL_BLEND);
model.unbind();
})
);
//Renders the texture we just made
shader.bind();
model.bind();
textureCoords.bind(texture);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
shader.setUniform("color", 1f, 1f, 1f, 1f);
shader.setUniform("projection", camera.getProjectionForGuiWindow(getPosition(), xscale, yscale));
glDrawElements(GL_TRIANGLES, model.getVerticeCount(), GL_UNSIGNED_INT, 0);
glDisable(GL_BLEND);
model.unbind();
Rendering over opaque objects in framebuffer 0 with a transparent object does not cause the resulting pixels to be transparent, else they would appear as a blend of the glClearColor and the opaque object, so why does this happen in the framebuffer in which I am using to render to a texture? Shouldn't it be consistent? I feel that maybe I'm missing some attachment to my framebuffer but I can't be sure what. I saw a solution that said to use glColorMask(true,true,true,false), the last false meaning no alpha writes, which appears at first glance to work, but why should I disable transparency when transparency is what I'm going for? It also appears to cause many issues if left on. Can anyone lend some insight? Thanks in advance!
EDIT: the glColorMask was not the solution, after further analysis.

You have to use a separable blending function which treats RGB and Alpha values separately: glBlendFuncSeparate. For the RGB values you keep using GL_SRC_ALPHA, GL_SRC_ONE_MINUS_ALPHA. For the Alpha values use something like GL_ONE, GL_ONE so that things simply add up.
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);

For anyone wondering, best solution to my issue was to use glBlendFuncSeparate(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA,GL_ONE_MINUS_DST_ALPHA,GL_ONE) instead of glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

Related

OpenGL GlOrtho no primitives appearing

I am drawing on a texture and then rendering this texture to the screen using GL_QUADS. There is no problem drawing the texture on screen, but while drawing to the texture the only operation that has any effect is glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - this sets the whole texture to the colour I want. It is however impossible to draw any primitives.
The following code should absolutely cover the whole texture with black, right?
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, texRenderer.framebufferID); // switch to the texture framebuffer
glClearColor(1.0f,0.5f,0.0f,1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDisable(GL_DEPTH_TEST);
glDisable(GL_SCISSOR_TEST);
glDisable(GL_CULL_FACE);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, texRenderer.pixelsWidth, 0, texRenderer.pixelsHeight, 1, -1);
// switch to modelview matrix before rendering objects
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glColor4f(0,0,0,1);
glBegin(GL_QUADS);
glVertex2f(-100, -100);
glVertex2f(-100, 100);
glVertex2f(100, 100);
glVertex2f(100, -100);
glEnd();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
//RenderScene(sim, stateMachine, viewSettings, commandMgr, font, texRenderer.pixelsWidth, texRenderer.pixelsHeight, isMainView, drawText);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); // switch back to normal framebuffer
Instead it is orange.
pixelsWidth and pixelsHeight are both equal to 64. I've made sure the viewport is set up correctly. Also glGetError() returns 0.
What have I missed?
Took me 6 hours but the problem is solved. I was wrong. The viewport was not properly set. Before rendering to a texture, be sure to add the following line:
glViewport(0, 0, textureWidth, textureHeight);
And also unbind any currently bound textures using
glBindTexture(GL_TEXTURE_2D, 0);

LWJGL draw rect over texture

I use the following to draw the texture quads
tex.bind();
glTranslatef(x, y, 0);
glBegin(GL_QUADS);
glTexCoord2f(0, 0);
glVertex2f(0, 0);
glTexCoord2f(1, 0);
glVertex2f(width, 0);
glTexCoord2f(1, 1);
glVertex2f(width, height);
glTexCoord2f(0, 1);
glVertex2f(0, height);
glEnd();
glLoadIdentity();
with these configurations:
try {
Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
Display.create();
} catch (LWJGLException e) {
e.printStackTrace();
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, WIDTH, HEIGHT, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
GL11.glEnable(GL11.GL_TEXTURE_2D);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
GL11.glDisable(GL11.GL_DEPTH_TEST);
GL11.glDisable(GL11.GL_LIGHTING);
GL11.glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
GL11.glClearDepth(1);
however now i want to add a menu to the game by drawing a rect over the screen but when i do so, everything turns red (if i set red as color)
case MENU:
GL11.glColor3f(1.0f, 0.0f, 0.0f);
glRectf(50, 50, 50, 50);
Two things:
Whenever you draw using color instead of textures, make sure to disable GL_TEXTURE_2D by calling glDisable(GL_TEXTURE_2D); before the rendering call (in your case before case MENU:). But don't forget to enable it again as soon as you're finished and ready to draw the texture once again (in your case, call glEnable(GL_TEXTURE_2D); after glRectf()). This might not be the reason for the problem that you're experiencing, but it will become a problem later.
The reason as to why everything turns red, is because whenever you render a texture, the currently bound color affects what color components are rendered from the texture. Every pixel in the texture that you're drawing is composed of 3 or 4 values. Red, Green, Blue and possibly an Alpha channel. Since you bind the color to red, and you do not change it before you draw the texture, OpenGL only draws the red component of each pixel within your texture. Thus, the Red component will be ranging from 0-1 in your texture, and the Green and Blue values will be staying at a constant 0.
To fix this, simply call glColor3f(1, 1, 1); After rendering the red rectangle. This will set the rendering color back to white (default) and therefore OpenGL will successfully draw all 3 color components of your texture pixels.
I hope that I've been clear and that this helps.
Good luck! :)
//SK

My Engine flickers when I try to render 2D and 3D

I am working with LWJGL to make a game. It's very basic. Before even implementing any sort of gpu rendering, or fancy model loaders, I wanted to make sure I could at least render 2D and 3D at the same time; My game has a gui while you walk around. Or at least, it is supposed to. Here is my initialization code; The flickering does not happen when I only render 3D.
public void clearGL() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
glLoadIdentity();
}
public void init3D() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective((float) 68, Engine.size[0] / Engine.size[1], 0.3f, 1000);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
}
public void render3D(Camera c) {
init3D();
clearGL();
//Do translations here
glTranslatef(0f, -5f, 0f);
glColor3f(0, 1, 0);
glBegin(GL_QUADS);
glVertex3f(-50f, 0f, -50f);
glColor3f(0, 0, 1);
glVertex3f(50f, 0f, -50f);
glColor3f(1, 0, 0);
glVertex3f(50f, 0f, 50f);
glColor3f(0, 1, 1);
glVertex3f(-50f, 0f, 50f);
glEnd();
}
public void init2D() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, Engine.size[0], 0, Engine.size[1], -1, 1);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_TEXTURE_2D);
glLoadIdentity();
}
public void render2D() {
init2D();
glBegin(GL_QUADS);
glVertex2f(0f, 50f);
glVertex2f(50f, 50f);
glVertex2f(50f, 0f);
glVertex2f(0f, 0f);
glPopMatrix();
}
I can tell its rendering at all because I am drawing a quad to represent the floor in JBullet. For some reason it is above the cameras head, but when I translate the camera up towards it it get's further away, which is why I translated the Camera to -5. That's another problem, for another day.
You should really consider disabling the depth test when you "switch" from 3D to 2D if you are going to draw at Z=0 (middle of your depth range). Half of the visible space in your 3D scene will potentially obstruct your 2D drawing if you do not do this. Alternatively, you could replace your glVertex2f (...) calls with glVertex3f (x,y, -1.0) to bring everything in 2D to the very front of the depth range.
But the really weird thing about all of this is the end of your render2D (...) function: You never call glEnd (...) and you pop a matrix that you appear never to have pushed. That is two sources of mismatched weirdness, either one of them could be causing your problem.

Drawing textured quads OpenGL not working

I am trying to render a group of textured quads.
I can get colored quads to render, but not textured ones (screen comes up empty.)
I am using LWJGL and PNGDecoder.
Code for initializing my OGL:
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, 800, 0, 600, 1, -1);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glEnable(GL11.GL_TEXTURE_2D);
Code for decoding my image:
ByteBuffer buffer = null;
InputStream in = ClassLoader.getSystemResourceAsStream(filename);
try {
buffer = decodeStreamToBuffer(in);
} finally {
in.close();
}
return buffer;
My decodeStreamToBuffer(InputStream in):
PNGDecoder decoder;
ByteBuffer buf = null;
try {
decoder = new PNGDecoder(in);
buf = ByteBuffer.allocateDirect(4*decoder.getWidth()*decoder.getHeight());
decoder.decode(buf, decoder.getWidth()*4, Format.RGBA);
buf.flip();
} catch (Exception e) {
e.printStackTrace();
}
return buf;
My rendering code:
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glColor3f(0.5f, 0.5f, 1.0f); //Still there to test color quads.
// draw quad
GL11.glPushMatrix();
GL11.glTranslatef(screencenter.getX(), screencenter.getY(), 0);
GL11.glScalef(1f, 0.5f, 1f);
GL11.glRotatef(camRotation, 0f, 0f, 1f);
GL11.glTranslatef(-screencenter.getX(), -screencenter.getY(), 0);
GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
GL11.glBegin(GL11.GL_TEXTURE_2D);
GL11.glTexCoord2f(0.0f, 0.0f);
GL11.glVertex2f(0, 0);
GL11.glTexCoord2f(1.0f, 0.0f);
GL11.glVertex2f(32, 0);
GL11.glTexCoord2f(1.0f, 1.0f);
GL11.glVertex2f(32, 32);
GL11.glTexCoord2f(0.0f, 1.0f);
GL11.glVertex2f(0, 32);
GL11.glEnd();
GL11.glPopMatrix();
When I leave the texture binding out and change the GL_TEXTURE_2D to GL_MODELVIEW it all works... but with color instead of a texture. Am I making a noob mistake here?
This is wrong GL11.glBegin(GL11.GL_TEXTURE_2D);
The glBegin method an primitive mode GLenum.
Thereby you either use:
GL_POINTS
GL_LINES
GL_LINE_STRIP
GL_LINE_LOOP
GL_TRIANGLES
GL_TRIANGLE_STRIP
GL_TRIANGLE_FAN
GL_QUADS
GL_QUAD_STRIP
GL_POLYGON
The mode you use specify what you are rendering. In your case you would code GL_QUADS So to fix your code you need to replace GL11.glBegin(GL11.GL_TEXTURE_2D); with GL11.glBegin(GL11.GL_QUADS);.
Extra
Also take in mind that the glVertex, glNormal, glTexCoord, etc. Methods are deprecated and should not be used. You are suppose to use VBOs and Shaders. Though if you are learning OpenGL then keep using the deprecated methods since they are good and easy to use when learning!

OpenGL: 2D Overlay is white over of 3D Scene

I'm trying to make a copy of MineCraft in Java using OpenGL (LWJGL). The problem I'm facing is that everything of my 2D overlay (aiming cross in the middle, menus, etc...) are all white. The 3D part of the game works great: every cube has a texture on each side.
But when I try to draw the overlay, as I said, every texture is white, but I can see the shape of it (because it has transparent areas). I'll add a picture of it.
(This is supposed to be the inventory)
As you can see, the overlay is completely white. And it should look like this:
I'm already searching the web for hours. Can't seem to find a solution.
This drives my crazy... I already searched for instructions of how to create a 2D overlay on a 3D scene, but they don't help either. So I though, I'll give StackOverflow a try.
Hopefully someone can help me?
Thanks for reading my question and for the (hopefully coming) answers!
Martijn
Here is the code:
Initialising OpenGL
public void initOpenGL() throws IOException
{
// init OpenGL
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, 800, 600, 0, 1, 300);
glMatrixMode(GL_MODELVIEW);
float color = 0.9f;
glClearColor(color, color, color, color);
glEnable(GL_TEXTURE_2D);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glShadeModel(GL_FLAT);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glEnable(GL_LINE_SMOOTH);
glEnable(GL_CULL_FACE);
glEnable(GL_FOG);
glFog(GL_FOG_COLOR, MineCraft.wrapDirect(color, color, color, 1.0f));
glFogi(GL_FOG_MODE, GL_LINEAR);
glFogf(GL_FOG_START, _configuration.getViewingDistance() * 0.8f);
glFogf(GL_FOG_END, _configuration.getViewingDistance());
glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, NVFogDistance.GL_EYE_RADIAL_NV);
glHint(GL_FOG_HINT, GL_NICEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
Configuring the matrixes for drawing the overlay (Out of inspiration, I literally copied all the OpenGL calls for this method from BlockMania (another open-source MineCraft copy), which works great)
public void renderOverlay()
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
GLU.gluOrtho2D(0, conf.getWidth(), conf.getHeight(), 0);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_COLOR_MATERIAL);
glPushMatrix();
glLoadIdentity();
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/** RENDER **/
if (_activatedInventory != null)
{
_activatedInventory.renderInventory();
}
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
glEnable(GL_CULL_FACE);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
Drawing the texture itself:
public void renderInventory()
{
Configuration conf = Game.getInstance().getConfiguration();
glTranslatef(conf.getWidth() / 2.0f, conf.getHeight() / 2.0f, 0.0f);
glEnable(GL_TEXTURE_2D);
Texture tex = TextureStorage.getTexture("gui.inventory");
tex.bind(); // newdawn.slick (same library for my whole program, so this works)
float hw = 170; // half width
float hh = 163; // half height
Vector2f _texPosUpLeft = new Vector2f(3, 0);
Vector2f _texPosDownRight = new Vector2f(_texPosUpLeft.x + hw, _texPosUpLeft.y + hh);
_texPosUpLeft.x /= tex.getTextureWidth();
_texPosUpLeft.y /= tex.getTextureHeight();
_texPosDownRight.x /= tex.getTextureWidth();
_texPosDownRight.y /= tex.getTextureHeight();
glColor3f(1, 1, 1); // Changes this doesn't make any effect
glBegin(GL_QUADS);
glTexCoord2f(_texPosUpLeft.x, _texPosUpLeft.y);
glVertex2f(-hw, -hh);
glTexCoord2f(_texPosDownRight.x, _texPosUpLeft.y);
glVertex2f(hw, -hh);
glTexCoord2f(_texPosDownRight.x, _texPosDownRight.y);
glVertex2f(hw, hh);
glTexCoord2f(_texPosUpLeft.x, _texPosDownRight.y);
glVertex2f(-hw, hh);
glEnd();
}
(The texture pack I'm using is CUBISM1.00)
I found it!!
It was the fog. For one or another reason it looks like it thinks the overlay is out of sight and gives it the color of the fog. So, disabling the fog before rendering the overlay solved it.
glDisable(GL_FOG);
/* Render overlay here */
glEnable(GL_FOG);
If there are still people who read this, is this caused by matrix abuse or is this behaviour normal?

Categories