i'd like to make this :
draw object 1 (because I should use glDrawElement or glDrawArray, depth test should be used)
draw object 2
blend 1 and 2 (obj 1 + transparent obj2)
Explaining by simple pseudo code,
glEnable(GL_BNELD);
/// draw obj1 ///
glEnable(GL_DEPTH_TEST);
glUniform4f(color1,1.0f);
glDrawElements(...) // draw obj1
glDisable(GL_DEPTH_TEST);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
/// draw obj2 ///
glEnable(GL_DEPTH_TEST);
glUniform4f(color2,0.5f);
glDrawElements(...) // draw obj2
glDisable(GL_DEPTH_TEST);
glDisable(GL_BLEND);
I heard that those blending and depth test are not used simultaneously, then is there any alternative? (actually the result of above code looks like strange)
Yes, blending and depth testing can be used at the same time. And you'll need it if you want to draw something translucent that's partially occluded by something opaque in the foreground.
What's not possible with the current state of the art of simple depth buffered rendering, is order independent transparency, i.e. blending objects in arbitrary order with the outcome being equivalent to drawing them far to near.
Related
Edit: Rendering the skybox before all other objects in the scene fixed this problem.
I've seen the question here but adding
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
doesn't appear to help.
I'm trying to render a spherical Skybox for my scene and for some reason when I Disable depth testing before doing so, the Skybox is the only thing rendered.
[Render other objects..]
// Disable depth test & mask, faceculling
glDisable(GL_DEPTH_TEST); // Adding this makes everything else invisible
glDepthMask(GL_FALSE);
glCullFace(GL_FRONT);
[Render texture onto inside of sphere..]
// Re-enable faceculling, & depth
glDepthMask(GL_TRUE);
glEnable(GL_DEPTH_TEST);
glCullFace(GL_BACK);
Any idea why this might be happening?
I wasn't sure of what code to include to keep this clear, so don't hesitate to ask for more.
Just to let you know, this:
glDisable(GL_DEPTH_TEST);
Disables both depth test and writing, so you don't need both that and set the depth mask to GL_FALSE.
When you clear the depth buffer each frame by default it should clear it the maximum value, probably 1.0. By default the depth function is GL_LESS meaning any depth value coming out of the fragment shader less than the one in the depth buffer passes and is written to the framebuffer.
It seems to me that what you're doing is clearing the depth buffer to 1.0, disabling depth testing and writing, drawing your objects, then enabling depth testing and writing and drawing your skybox. The problem with this is that the drawing of your objects doesn't write anything to the depth buffer, and so when it comes time to draw your skybox (with depth testing enabled) all the pixel depth values in the buffer are 1.0 (because you never wrote anything to it), and because the depth function is GL_LESS every pixel you draw of your skybox passes the depth test and is written to the framebuffer.
If there is a special need to have your objects always drawn in front of the skybox, for example the skybox follows the camera position around, then:
1) Disable the depth writing.
2) Draw the skybox.
3) Enable the depth writing.
4) Draw your objects.
Well, yes. That's what the depth test is for. Without it, there's nothing to indicate to OpenGL that the skybox shouldn't be rendered on top of everything else.
If you don't want this to happen, don't disable the depth test… or draw the skybox before everything else, instead of afterwards.
I am using gluCylinder() to create a cylinder in openGL and then plotting points inside the cylinder with Depth Test On .
When i see the front view of the cylinder, the points inside the cylinder are obstructed by front face.
To make front face of the cylinder translucent i am using Blending.
I am using below functions.
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
But whatever coloring or alpha value i assign to the cylinder the front face is not looking transparent due to its back face.
Tell whether it is possible to do with blending only or else i need to introduce lighting for both the faces of Cylinder.Here it clearly visible the change in the color of front face and back face of cylinder. And the points inside the cylinder are not visible due to being obstructed by front face of cylinder.
You should be able to accomplish this by drawing the cylinder twice, while culling the front faces the first time, and culling the back faces the second time. This way, you can draw the front and back parts differently, e.g. by making the front part transparent.
The code sequence could look like this:
// Draw back part of cylinder, opaque.
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
gluCylinder(...);
// Draw points.
// Draw front part of cylinder, transparent.
glCullFace(GL_BACK);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
gluCylinder(...);
glDisable(GL_BLEND);
If I understand you right then no, you can't do it with blending alone.
If the cylinder's normals all point outward then you also won't be able to see the cylinder's internal parts no matter what you do.
I do something similar to show characters behind walls and it goes like this - render your scene normally and save it all to a framebuffer. Then render what you want shown behind with the buffer contents on top, using a custom shader to make a bubble of transparency around the thing you want shown behind.
Not sure if I am explaining it well or not but it unfortunately requires multiple steps to get the results you want.
Your problem is still a bit unclear to me despite the image but I will attempt to answer based on my perception of your issue.
You are drawing a cylinder and have geometry (lines or other models) inside the cylinder. You want the cylinder to look translucent so the inner objects are visible. Here is one way to do it. Assuming your render functions are drawCylinder() and drawPoints().
init()
{
...
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
...
}
drawScene()
{
glDepthMask(GL_FALSE);
glEnable(GL_BLEND);
drawCylinder();
glDisable(GL_BLEND);
glDepthMask(GL_TRUE);
drawPoints();
}
doing so will make sure that the points are drawn regardless of the cylinder. Try using lower values of alpha for your cylinder color.
Please note this is one way to do it. I suggest using shaders to have more control over blending as well as exploring fragment/pixel discard options.
In libGdx, i'm trying to create a shaped texture: Take a fully-visible rectangle texture and mask it to obtain a shaped textured, as shown here:
Here I test it on rectangle, but i will want to use it on any shape. I have looked into this tutorial and came with an idea to first draw the texture, and then the mask with blanding function:
batch.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_ALPHA);
GL20.GL_ZERO - because i really don't want to paint any pixels from the mask
GL20.GL_SRC_ALPHA - from original texture i want to paint only those pixels, where mask was visible (= white).
Crucial part of the test code:
batch0.enableBlending();
batch0.begin();
batch0.draw(original, 0, 0); //to see the original
batch0.draw(mask, width1, 0); //and the mask
batch0.draw(original, 0, height1); //base for the result
batch0.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_ALPHA);
batch0.draw(mask, 0, height1); //draw mask on result
batch0.setBlendFunction(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
batch0.end();
The center ot the texture get's selected well, but instead of transparent color around, i see black:
Why is the result blank and not transparent?
(Full code - Warning: very messy)
What you're trying to do looks like a pretty clever use of blending. But I believe the exact way you apply it is "broken by design". Let's walk through the steps:
You render your background with red and green squares.
You render an opaque texture on top of you background.
You erase parts of the texture you rendered in step 2 by applying a mask.
The problem is that for the parts you erase in step 3, the previous background is not coming back. It really can't, because you wiped it out in step 2. The background of the whole texture area was replaced in step 2, and once it's gone there's no way to bring it back.
Now the question is of course how you can fix this. There are two conventional approaches I can think of:
You can combine the texture and mask by rendering them into an off-sreen framebuffer object (FBO). You perform steps 1 and 2 as you do now, but render into an FBO with a texture attachment. The texture you rendered into is then a texture with alpha values that reflect your mask, and you can use this texture to render into your default framebuffer with standard blending.
You can use a stencil buffer. Masking out parts of rendering is a primary application of stencil buffers, and using stencil would definitely be a very good solution for your use case. I won't elaborate on the details of how exactly to apply stencil buffers to your case in this answer. You should be able to find plenty of examples both online and in books, including in other answers on this site, if you search for "OpenGL stencil". For example this recent question deals with doing something similar using a stencil buffer: OpenGL stencil (Clip Entity).
So those would be the standard solutions. But inspired by the idea in your attempt, I think it's actually possible to get this to work with just blending. The approach that I came up with uses a slightly different sequence and different blend functions. I haven't tried this out, but I think it should work:
You render the background as before.
Render the mask. To prevent it from wiping out the background, disable writing to the color components of the framebuffer, and only write to the alpha component. This leaves the mask in the alpha component of the framebuffer.
Render the texture, using the alpha component from the framebuffer (DST_ALPHA) for blending.
You will need a framebuffer with an alpha component for this to work. Make sure that you request alpha bits for your framebuffer when setting up your context/surface.
The code sequence would look like this:
// Draw background.
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
glDisable(GL_BLEND);
// Draw mask.
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
glEnable(GL_BLEND);
glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
// Draw texture.
A very late answer, but with the current version this is very easy. You simply draw the mask, set the blending mode to use the source color to the destination and draw the original. You'll only see the original image where the mask is.
//create batch with blending
SpriteBatch maskBatch = new SpriteBatch();
maskBatch.enableBlending();
maskBatch.begin();
//draw the mask
maskBatch.draw(mask);
//store original blending and set correct blending
int src = maskBatch.getBlendSrcFunc();
int dst = maskBatch.getBlendDstFunc();
maskBatch.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_COLOR);
//draw original
maskBatch.draw(original);
//reset blending
maskBatch.setBlendFunction(src, dst);
//end batch
maskBatch.end();
If you want more info on the blending options, check How to do blending in LibGDX
I am trying to check transparency and how it works.
I have created a solidsphere and a solidcube in it.
I have enabled
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
The transparency works as expected using color4f.
The problem is that when I am setting the transparency of the sphere to 1.0, the cube still appears.
I am also using these:
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glClearDepth(1);
glPolygonMode(GL_FRONT_AND_BACK,GL_FILL);
glEnable(GL_CULL_FACE);
glFrontFace(GL_CW);
How can I make the cube visible only when the transparency of the sphere is != 1.0 ?
Is there a reason you've set glFrontFace(GL_CW); ? The default is GL_CCW, so you'll be culling front faces, and rendering back faces. With the front of the sphere missing, you'll see inside it.
To elaborate:
When rendering translucent objects using a normal (src_alpha , 1-src_alpha) blend, the translucent surfaces need to be rendered in depth order, back to front.
If you render only the back-surfaces of an object, it may (if it's more or less symmetrical) appear normal, but it is in fact inside-out, and thus cannot occlude objects correctly which are actually inside it.
So for this to work, it is important both that the front-surfaces are not culled, and that the opaque or more distant objects are rendered first.
If you want both front and back of the sphere to render translucently, and correctly, you would need to render the back before the front. This could be done with polygon sorting, but for a convex object it would suffice to render it twice, with the backface culling inverted - so render back faces first, and then the front faces, in two seperate passes.
My cube isn't rendering as expected when I use GL_BLEND.
glEnable(GL_CULL_FACE);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
I'm also having a similar problem with drawing some semi-opaque vertices in front, which could well be related.
Related: Why do my semi-opaque vertices make background objects brighter in OpenGL?
Here's what it's supposed to look like:
Normal cube http://img408.imageshack.us/img408/2853/normalcube.png
And here's what it actually looks like:
Dark cube http://img7.imageshack.us/img7/7133/darkcube.png
Please see the code used to create the colored cube, and the code used to actually draw the cube.
The cube is being drawn like so:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
glLoadIdentity();
// ... do some translation, rotation, etc ...
drawCube();
glPopMatrix();
// ... swap the buffers ...
You could try disabling all lighting before drawing the cube:
glDisable(GL_LIGHTING);
It looks like you have lighting enabled on the second one,
try with a glShadeModel( GL_FLAT ) before drawing,
This has me stomped. What it looks like is that some vertices have some alpha values that are non-opaque. However the code you posted has all 1. for alpha. So... in order to debug more, did you try to change your clear color to something non-black ? Say green ?
From the code, I doubt lighting is turned on, since no normals were specified.
Last comment, offtopic... You should really not use glBegin/glEnd (2 function calls per vertex + 2 per primitive is really not a good usage of the recent developments in OpenGL). Try glDrawElements with QUAD_LIST, or even better, TRIANGLE_LIST. You already have the data nicely laid out for that.