PDA

View Full Version : 3D Objects behind an 2D Image with alpha 0.5 not drawn



Archon
05-18-2007, 10:03 AM
At first, my english is not very good, so please don't wonder if I use false grammar.

I have the following problem:
I want to draw an 2D Image with alpha 0.5 over some 3D objects so that they can be seen a bit. I've tried this with the following code (JOGL) but it just don't draw the 3D objects (except if the image is not drawn, then the objects are drawn)


gl.glDisable( GL.GL_DEPTH_TEST );
gl.glWindowPos2i(0,engine.getHeight()/2);
gl.glDrawPixels(image.getWidth() ,image.getHeight() ,gl.GL_RGBA ,gl.GL_UNSIGNED_BYTE, image.getRGBABuf());//image.getRGBABuf() returns the pixel values (R G B A=0.5);
gl.glEnable(gl.GL_DEPTH_TEST);This code is executed after the other objects are drawn
It is drawn with the following viewing volume:

private double [] position = { 0.0, 0.0, 5.0 };
private double [] lookAt = { 0.0, 0.0, 0.0 };
private double [] up = { 0.0, 1.0, 0.0 };
private double fovy = 45.0;
private double aspect = 1/4;
private double nearClip = 0.01;
private double farClip = 20;
...
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(fovy, aspect, nearClip, farClip);
gl.glMatrixMode(GL.GL_MODELVIEW);
...
glu.gluLookAt(position[0],position[1],position[2],lookAt[0],lookAt[1],lookAt[2],up[0],up[1],up[2]);And Blending is also enabled:

gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(gl.GL_BLEND);Do anybody know whats wrong with this code (or can definitly say the OpenGL code is ok, but maybe there's an problem with image itself)?

k_szczech
05-18-2007, 01:05 PM
glDrawPixels will replace contents of framebuffer.

If you want to overlay a 2D image with blending then put it into texture and draw a fullscreen quad with that texture.

Bob
05-18-2007, 04:10 PM
Originally posted by k_szczech:
glDrawPixels will replace contents of framebuffer.
Not correct. glDrawPixels will generate fragments that are passed through the fragment operations just like any other rasterized primitive. Blending which OP talks about, for example, is pefectly possible with glDrawPixels.

Anyway, the code and description as posted does look correct. The problem is likely somewhere else.

k_szczech
05-18-2007, 06:03 PM
You're right Bob.
This is from specs:

The glDrawPixels function reads pixel data from memory and writes it into the framebufferThat's why I thought it replaces data in the framebuffer. I haven't been using glDrawPixels with alpha channel.

Anyway thanks for this important correction.

The problem is likely to be related to depth testing. Try using glDrawPixels on only half of the screen and make sure your geometry is really drawn.
Perhaps you clear depth buffer in wrong place?

Archon
05-19-2007, 02:48 AM
The rendering of one frame loks like this(Blending is enabled in the init):

gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glEnableClientState(gl.GL_VERTEX_ARRAY);
gl.glVertexPointer(3, gl.GL_DOUBLE, 0, vertsBuf);
gl.glColor3f(1.0f,1.0f,1.0f);
gl.glTranslatef(-1.0,1.0,-5.0);
gl.glDrawElements(gl.GL_QUADS,24,gl.GL_UNSIGNED_IN T,indsBuf);
gl.glDisableClientState(GL.GL_VERTEX_ARRAY);

gl.glDisable( GL.GL_DEPTH_TEST );
gl.glWindowPos2i(0,engine.getHeight()/2);
gl.glDrawPixels(800 ,300 ,gl.GL_RGBA ,gl.GL_UNSIGNED_BYTE, image.getRGBABuf());
gl.glEnable(gl.GL_DEPTH_TEST);And the image is created here(the most is copied from http://today.java.net/pub/a/today/2003/09/11/jogl2d.html -Drawing Images):

int width = engine.getWidth(), height = engine.getHeight();
ByteBuffer buf;
Z3DImage image = new Z3DImage();
WritableRaster raster =
Raster.createInterleavedRaster(DataBuffer.TYPE_BYT E,
width,
height/2,
4,
null);
ComponentColorModel colorModel=
new ComponentColorModel(ColorSpace.getInstance(ColorSp ace.CS_sRGB),
new int[] {8,8,8,8},
true,
false,
ComponentColorModel.TRANSLUCENT,
DataBuffer.TYPE_BYTE);
BufferedImage bufImg =
new BufferedImage(colorModel,
raster,
false,
null);
Graphics2D g = bufImg.createGraphics();
bufImg.getAlphaRaster().setPixels(1,1,50,50,alpha) ;
AffineTransform gt = new AffineTransform();
gt.translate(0,height/2);
gt.scale(1, -1d);
g.transform(gt);
g.setColor(new Color(1.0f,1.0f,1.0f,0.5f));
g.setComposite(AlphaComposite.Src);
g.fillRect(0,0,width,height/2);
g.drawRect(1,1,width-3,20);
g.drawRect(0,height/2-20,width-1,20);
g.dispose();
...
DataBufferByte imageBuf = (DataBufferByte)image.getRaster().getDataBuffer();
byte[] RGBA = imageBuf.getData();
this.setRGBA(RGBA);
if(this.imageBuf == null){
this.imageBuf = BufferUtil.newByteBuffer( RGBA.length*2);
}else{
this.imageBuf.clear();
}
this.imageBuf.put(RGBA);
this.imageBuf.rewind();I've searched for the mistake but i couldn't find it.

and with the Quad is another problem. I tried it with the follwoing coordinates: P(0.0, 0.0, 4.0) (Camera settings are in my first post) but it wasn't shown - until i used P(0.0, 0.0, -1.0)- but is that right? - the near clippling Pane is just 0.01 units away from the camera so P(0.0, 0.0, 4.0) should also be drawn, or did I misunderstood this?

double [] coords = {0.0,0.0,-1.0};
gl.glLoadIdentity();
gl.glColor3f(1.0f,1.0f,1.0f);
gl.glTranslated(coords[0],coords[1],coords[2]);
gl.glBegin(gl.GL_QUADS);
gl.glVertex3f(1.0f,1.0f,0.0f);
gl.glVertex3f(1.0f,0.0f,0.0f);
gl.glVertex3f(-1.0f,0.0f,0.0f);
gl.glVertex3f(-1.0f,1.0f,0.0f);
gl.glEnd();

Overmind
05-19-2007, 02:40 PM
(Camera settings are in my first post)No they are not :p . You have a glLoadIdentity before your quad drawing code. This resets the camera to the origin, looking in the negative z direction, so 4.0 is behind the camera, -1.0 is in front of the camera.

As for the original problem, does it work with a textured quad?

EDIT: Yeah... 1024 posts ;)

Archon
05-20-2007, 06:04 AM
I didn't know that glLoadIdentity resets also the camera.
I tried it with a textured Quad but it doesn't work, and had a very slow performance(I have to redraw the Texture because the user should be able to draw text in there).
After switching back to glDrawPixel it suddenly worked - but only if I use the following (strange) lines of code in the init:

gl.glEnable(GL.GL_TEXTURE_2D);
tex=TextureIO.newTexture(image.getImage(),false);//getImage() returns the BufferedImage wich is drawn.It seems that the TextureIO.newTexture() use Code to either manipulate the BufferImage or use an OpenGL function that i've forgotten to use. Does anybody know wich function(s) could that be? Because it seems silly to me, to create an texture only for the function calls.

Archon
06-02-2007, 01:37 AM
I've fixed it.
The Problem was, that I didn't set the background(Clear)-Color for the BufferedImage. So the clearing Color had an alpha value of 1.0.
This code fixed it:

Graphics2D g = (Graphics2D)img.getGraphics();
g.setColor(new Color(255,255,255,128));
g.setBackground(new Color(0,0,0,0));