Java-Gaming.org Hi !
Featured games (90)
games approved by the League of Dukes
Games in Showcase (741)
Games in Android Showcase (225)
games submitted by our members
Games in WIP (823)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  java2d-pipeline / glReadPixels / alpha-component  (Read 5064 times)
0 Members and 1 Guest are viewing this topic.
Offline Saxer

Junior Devvie





« Posted 2007-06-17 15:56:37 »

Hello,

As mentioned in several posts before I'm experimenting with the jogl-java2d-pipeline.

Right now I have again a problem with the glReadPixel-Method. I want to determine which pixels are transparent. So I just look at the 4th pixel-component to see if it's != 0. With an enabled pipeline every pixel has an alpha-value of 255. What I know from the technical stuff behind the pipeline is, that opengl renders directly into the swingbuffer. Am I right with the suggestion, that I'm reading the content of the - lets say - jframe and not just my gljpanel?

My solution works great without the pipeline enabled.

The code around the readpixels:
1  
2  
3  
4  
mouseBuffer = BufferUtil.newByteBuffer((renderPanel.getWidth())
               * (renderPanel.getHeight()) * 4);
gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1);
gl.glReadPixels(0, 0, renderPanel.getWidth(), renderPanel   .getHeight(), GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, mouseBuffer);


The code which determins the alpha-value:
1  
2  
int index = (mouseBuffer.get(pos + 3) & 0xFF);
return index != 0;


The calculation of pos is ok because it works for other purposes.

The buffer contains more than I would expect. Is there a way to simple extract the real 3d-rendered-content? I could draw the scene into a bufferedimage and check the pixels, but I don't think it would help the performance  of my app Tongue

Thanks for any comments / help
Greets Klemens
Offline broumbroum

Junior Devvie





« Reply #1 - Posted 2007-06-17 19:50:16 »

I don't know about 2d pipeline in jogl. But I know that it can be enabled for Java2d app like this way: (-J)-Dsun.java2d.opengl=True as a command line arg to java.
Why do you pay time to Java2D when your goal is 3D scening? That'd be the question.

::::... :..... :::::: ;;;:::™ b23:production 2006 GNU/GPL @ http://b23prodtm.webhop.info
on sf.net: /projects/sf3jswing
Java (1.6u10 plz) Web Start pool
dev' VODcast[/ur
Offline Saxer

Junior Devvie





« Reply #2 - Posted 2007-06-17 21:01:47 »

Well, I'm building swing-components with 3D features. Therefore I need this. I know how to enable the pipeline... the described problem only exists with enabled pipeline.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Ken Russell

JGO Coder




Java games rock!


« Reply #3 - Posted 2007-06-18 03:01:53 »

Yes, you should be able to see the entire Swing back buffer and not just your GLJPanel's contents if you're careful. Note that the OpenGL viewport and scissor region are set up to surround just the GLJPanel's region before your GLEventListener is called, so you'll need to change them if you want to read back more than just your GLJPanel.

Aside from that I don't know why you're seeing alpha=255 pixels everywhere. If you could please provide a small and clear test case showing the problem we can look into it.

You may also find it useful to look at the source code of the XTrans demo in the jogl-demos workspace, which does some 3D effects with Swing components using the Java 2D/JOGL bridge.
Offline Saxer

Junior Devvie





« Reply #4 - Posted 2007-06-18 07:33:25 »

Yes I'll provide one test-case later this afternoon. The reason of the 255's seems to be, that I read the final composed pixels of the buffer which are fully opaque.
Offline Saxer

Junior Devvie





« Reply #5 - Posted 2007-06-19 19:12:24 »

Here's my testcase I hope it shows the problem. I cant test it with the pipeline at this maschine. Just click on the quad in the middle and watch at the console.

1  
2  
3  
4  
5  
6  
7  
8  
9  
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  
21  
22  
23  
24  
25  
26  
27  
28  
29  
30  
31  
32  
33  
34  
35  
36  
37  
38  
39  
40  
41  
42  
43  
44  
45  
46  
47  
48  
49  
50  
51  
52  
53  
54  
55  
56  
57  
58  
59  
60  
61  
62  
63  
64  
65  
66  
67  
68  
69  
70  
71  
72  
73  
74  
75  
76  
77  
78  
79  
80  
81  
82  
83  
84  
85  
86  
87  
88  
89  
90  
91  
92  
93  
94  
95  
96  
97  
98  
99  
100  
101  
102  
103  
104  
105  
106  
107  
108  
109  
110  
111  
112  
113  
114  
115  
116  
117  
118  
119  
120  
121  
import java.awt.BorderLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.nio.ByteBuffer;

import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLJPanel;
import javax.media.opengl.glu.GLU;
import javax.swing.JButton;
import javax.swing.JFrame;

import com.sun.opengl.util.BufferUtil;

public class PipelineError {

   private static ByteBuffer mouseBuffer;
   /**
    * @param args
    */

   public static void main(String[] args) {
     
      GLCapabilities caps = new GLCapabilities();
      caps.setAlphaBits(8);
     
      final GLJPanel panel = new GLJPanel(caps);
      panel.setOpaque(false);
      panel.addGLEventListener(new GLEventListener() {

         public void display(GLAutoDrawable arg0) {
            GL gl = arg0.getGL();
            if (panel.shouldPreserveColorBufferIfTranslucent()) {
                  gl.glClear(GL.GL_DEPTH_BUFFER_BIT);
              } else {
                  gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
              }

            gl.glEnable(GL.GL_DEPTH_TEST);
            gl.glColor3f(0.6f, 0.6f,0.6f);
           
            gl.glColor3f(1f, 0f, 1f);
            gl.glBegin(GL.GL_QUADS);
            gl.glVertex3f(-1, 1, 0);
            gl.glVertex3f(-1, -1, 0);
            gl.glVertex3f(1, -1, 0);
            gl.glVertex3f(1, 1, 0);
            gl.glEnd();
           
            mouseBuffer = BufferUtil.newByteBuffer((panel.getWidth())
                  * (panel.getHeight()) * 4);
            gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1);
            gl.glReadPixels(0, 0, panel.getWidth(), panel.getHeight(), GL.GL_RGBA, GL.GL_UNSIGNED_BYTE, mouseBuffer);
         }

         public void displayChanged(GLAutoDrawable arg0, boolean arg1, boolean arg2) {
           
         }

         public void init(GLAutoDrawable arg0) {
            arg0.getGL().glClearColor(1,0,1,0);
               int clearBits = GL.GL_DEPTH_BUFFER_BIT;
               clearBits |= GL.GL_COLOR_BUFFER_BIT;
               
               arg0.getGL().glClear(clearBits);
         }

         public void reshape(GLAutoDrawable arg0, int x, int y, int width, int height) {
            GL gl = arg0.getGL();
            gl.glViewport(x, y, width, height);
              gl.glMatrixMode(GL.GL_PROJECTION);
              gl.glLoadIdentity();
              new GLU().gluPerspective(45.0, (float) width / height, 1.0, 400.0);
             
              gl.glMatrixMode(GL.GL_MODELVIEW);
              gl.glLoadIdentity();
             
              new GLU().gluLookAt(
                      0,0,5, 0,0,0,
                      0, 1, 0);

         }
         
      });
     
      panel.addMouseListener(new MouseAdapter() {
         @Override
         public void mousePressed(MouseEvent e) {
           
            int x = e.getX();
            int y = e.getY();
           
            if (mouseBuffer == null || x < 0 || y < 0) {
               return;
            }

            int bufX = x;
            int bufY = panel.getHeight() - y;

            int pos = (bufY * panel.getWidth() + bufX) * 4;

            if (pos >= 0 && pos < mouseBuffer.capacity()) {
               int index = (mouseBuffer.get(pos + 3) & 0xFF);
               System.out.println(index);
            }
         }
      });
     
     
      JFrame frame = new JFrame();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setSize(400, 400);
      frame.setGlassPane(panel);
      panel.setVisible(true);
      frame.add(new JButton("test-Button"), BorderLayout.CENTER);
     
      frame.setVisible(true);
   }

}
Offline campbell

Junior Devvie




Java games rock!


« Reply #6 - Posted 2007-06-19 21:09:37 »

Here's the deal.  Swing's backbuffer is always opaque.  There is currently no way to specify that you'd like Swing to allocate an alpha channel with its backbuffer.  When you have the OpenGL-based Java 2D pipeline enabled, and you're using GLJPanel, Swing's backbuffer is allocated as a pbuffer or FBO without an alpha channel.  It is therefore expected that you will see all opaque alpha values if you read back directly from the Swing backbuffer using glReadPixels().

When the OpenGL-based Java 2D pipeline is not enabled, and you're using GLJPanel, JOGL will allocate a pbuffer that does contain an alpha channel, which is necessary for properly compositing the contents of that offscreen pbuffer onto the actual Swing backbuffer.  So in that case, you're using glReadPixels() to read back from that alpha channel enabled pbuffer, and therefore some of the pixels may appear to be transparent.

Chris
Offline Saxer

Junior Devvie





« Reply #7 - Posted 2007-06-20 06:29:28 »

I expected something like that.

How could I archieve the functionality which is described in the demo? Rendering into an additional pbuffer? Or rendering into an BufferedImage (not sure if this would work). The mentioned functionality is completely essential for my projekt :-(. I don't need it in every frame just in few - lets call them - key-frames.

It would be enough to simply know if pixel x,y belongs to the gljpanel or not. (I use this technique to modify the contains(x,y) method in order to hide the gljpanel from mouseevents)
Maybe an bad idea:
readPixels => Buffer1
doRendering
readPixels => Buffer2

if (Buffer1(x,y) != Buffer2(x,y)) {
    somsething happend in the rendering => rendered-alpha != 255
}

That wouldn't cover a rendered blue pixel ontop of a blue pixel which is already there. Should the backbuffer be lets say completely black / white in all the regions which are not affected by the rendering?

I hope you've got an positive answer  Undecided

Offline Saxer

Junior Devvie





« Reply #8 - Posted 2007-06-23 15:25:37 »

No suggestions? I'm quite stuck with this.

I tried to set the clearColor to opaque-black and take black as the decision color instead of the alpha value. That results in black rectangles (the gljpanel) even if I clear the scene after the glReadPixels call with a translucent color.

I don't need the readpixels for presentation - just for background-functionality. Therefore it could be useful to render into the mousebuffer directly (and with an alpha component). Unfortunately I don't know how to do this exactly. To render within a different context (pbuffer or something) seems to be possible but very difficult, cause I would have to setup all of the transforms and textures for that context.

thanks in advance
Klemens
Offline Ken Russell

JGO Coder




Java games rock!


« Reply #9 - Posted 2007-06-23 18:47:37 »

Look at the source for the XTrans demo in the jogl-demos workspace. If you are able to manually trigger a repaint in order to create your readback ("mouse") buffer, then you can cause Swing to render itself into a BufferedImage (create a BufferedImage of the appropriate size, call getGraphics() on it, and pass that into the paint(Graphics) method of your top-level component). You could potentially then use that BufferedImage for your queries while still doing your on-screen rendering another way. The XTrans demo does something vaguely similar to this except it takes advantage of the Java 2D / JOGL bridge to interact with VolatileImages and it doesn't do any readback of this sort except for rendering.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Saxer

Junior Devvie





« Reply #10 - Posted 2007-06-30 09:16:55 »

I checked the XTrans-Demo. It seems, you don't use a GLJPanel within this demo. I manage the rendering stuff of the nested components as you do (or even quite similar).

The only hint I could eventuelly use is this isOptimizedDrawingEnabled()  method. But I don't know if this would help (Thinking about doing setting it to false when I screenshot the GLJPanel (see below).

The problem shows up, when I paint the GLJPanel into a dedicated Graphics-object (the one I got from the BufferdImage).

With disabled pipeline everything works as it should (BufferedImage setup in pain-method an super.paint(image.getGraphics)). I get translucent pixels with correct alpha-values to work with. Wit enabed pipeline I get an fully opaque image. I tried every possible glClear-Setting (color-bit only, color + depth, depth only, nothing at all). Only with no glClear-call I get transparent pixels (unfortunately the content is totally disorderd with some bad artefacts - as you might now).

I know it is against the intention of the pipeline, but is there a way to workaround the "render to the swingbuffer"-thing in certain situations. I don't know how you do it exactly, but is it possible to determine if the passed graphics-object comes from an image? And for that case disable the backbuffer-thing.

Maybe an public BufferedImage getContentAsImage() method would be the nicest feature Grin

I'm not sure if the Screenshot-class which shippes with jogl would solve the problem. I'll give it a try soon.

I forgot: I didn't try it with latest jogl - lastest jdk 6 update. I 'll do it this afternoon.
Offline Ken Russell

JGO Coder




Java games rock!


« Reply #11 - Posted 2007-07-03 20:16:40 »

If the GLJPanel isn't working for you due to the Java 2D / JOGL bridge then you can build your own. You can use either a GLPbuffer or, better, a Frame Buffer Object to render your 3D scene and then use the JOGL-internal Java2D class in similar fashion to how the GLJPanel does in order to render that FBO as a texture to the Java 2D / Swing back buffer.
Offline Saxer

Junior Devvie





« Reply #12 - Posted 2007-07-04 09:31:47 »

Hmmm... I'll have a look into the GLJPanel implementation to see if I can insert my identifikation-stuff somewhere within it's rendering cycle. Otherwise I'll have to do one additional rendering-loop with some kind of color-masking (every geometry would be paintet in black) to determine which pixels are "inside" and which are "outside".
Offline Saxer

Junior Devvie





« Reply #13 - Posted 2007-07-21 13:12:48 »

Well as always I run from one sloved problem into the next. Right now I use the depthbuffer to determine which pixels have been drawn and which not.

I'm not quite sure which dimension my readback buffer should have cause of the viewport-thing of the java2d-pipeline:

Should I do this?
1  
2  
3  
4  
5  
int width = renderPanel.getWidth() + viewPort.x;
int height = renderPanel.getHeight() + viewPort.y;
containsBufferFloat = BufferUtil.newFloatBuffer(width * height);
gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1);
gl.glReadPixels(0, 0, width, height, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT, containsBufferFloat);


or that?
1  
2  
3  
4  
5  
int width = renderPanel.getWidth();
int height = renderPanel.getHeight();
containsBufferFloat = BufferUtil.newFloatBuffer(width * height);
gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1);
gl.glReadPixels(0, 0, width, height, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT, containsBufferFloat);


Of course I have to deal with the "translation" when I convert the mouse-position to find the right position... I tried the first-variant cause I felt, that just reading "renderpanel.getWidth"-pixels in a row would give me not all the pixels of the rendering (because the viewport begins not in 0,0)

Well nevertheless it's no big problem and could be solved by simply checking out what information is returned.

Unfortunately the depth-buffer seems to be filled wrong (I don't know if this i a graphics-vendor bug). I have pictures wihtin I tried to visualise the contents of the buffer (1.0 means blue - 0.0 means black) . In my case I use 2 GLJPanels within a LayeredPane - otherwise (with only one panel) the content of the buffer seems to be ok. These pictures visualise the depthbuffers of the two panels (nothing was rendered so they should be completely black).




(note that the pixels in the top-left-corner seem to be identical)

I completely don't understand this behaviour :-(
Offline lhkbob

JGO Knight


Medals: 32



« Reply #14 - Posted 2007-07-21 15:40:38 »

Make sure you clear the depth buffer bit, too, just like you would for clearing the color bit, but pass in GL.GL_DEPTH_BUFFER_BIT.  Also, for better performance, you can "or" all of the bits together in glClear() cal.

Offline Ken Russell

JGO Coder




Java games rock!


« Reply #15 - Posted 2007-07-21 15:44:37 »

What are you really trying to read back? The GLJPanel's contents or the entire Swing back buffer?

You should be calling approximately

1  
2  
3  
4  
5  
int width = renderPanel.getWidth();
int height = renderPanel.getHeight();
containsBufferFloat = BufferUtil.newFloatBuffer(width * height);
gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1);
gl.glReadPixels(viewPort.x, viewPort.y, width, height, GL.GL_DEPTH_COMPONENT, GL.GL_FLOAT, containsBufferFloat);

Offline Saxer

Junior Devvie





« Reply #16 - Posted 2007-07-21 16:13:06 »

you're right with your code. The first part of my post was more like a philosophical question.

The problem starts with the actual depth-values. It seems, that those values are not cleared correctly. In my "vision" glClear should "reset" all of the values to 1.0 (or whatever one has configured). Without enabled pipeline my result are as expected (totally black "images").
Offline Ken Russell

JGO Coder




Java games rock!


« Reply #17 - Posted 2007-07-22 05:18:00 »

Yes, it should. In this area, the main difference between having the Java 2D / OpenGL pipeline enabled and disabled is that when it's disabled, the (x, y) offset to your component is always (0, 0), and when it's enabled, the (x, y) offset to your component is its (x, y) offset on the actual back buffer. You may need to use some of the internal methods on the Java2D class to compute the region on the Swing back buffer in OpenGL coordinates of your panel. I would also suggest you try reading back the color buffer first instead of the depth buffer so it's easier for you to calibrate your code and figure out what's going on. At that point you can switch over to reading the depth buffer, which should then work 100%.
Offline Saxer

Junior Devvie





« Reply #18 - Posted 2007-07-22 11:43:55 »

Well... the viewport-thing was exactly the reason of all the trouble. Although I can't figure out, why it was working "partially" before. (The "blue" artifacts appeared just in particular positions.)

Thanks for your help. Now the performance on "slow" systems (with pipeline-support) could be increased conspicuously .
Offline Ken Russell

JGO Coder




Java games rock!


« Reply #19 - Posted 2007-07-23 02:33:26 »

Glad things are working.
Pages: [1]
  ignore  |  Print  
 
 

 
xxMrPHDxx (18 views)
2017-11-21 16:21:00

xxMrPHDxx (11 views)
2017-11-21 16:14:31

xxMrPHDxx (14 views)
2017-11-21 16:10:57

Ecumene (114 views)
2017-09-30 02:57:34

theagentd (148 views)
2017-09-26 18:23:31

cybrmynd (248 views)
2017-08-02 12:28:51

cybrmynd (248 views)
2017-08-02 12:19:43

cybrmynd (244 views)
2017-08-02 12:18:09

Sralse (258 views)
2017-07-25 17:13:48

Archive (878 views)
2017-04-27 17:45:51
List of Learning Resources
by elect
2017-03-13 14:05:44

List of Learning Resources
by elect
2017-03-13 14:04:45

SF/X Libraries
by philfrei
2017-03-02 08:45:19

SF/X Libraries
by philfrei
2017-03-02 08:44:05

SF/X Libraries
by SkyAphid
2017-03-02 06:38:56

SF/X Libraries
by SkyAphid
2017-03-02 06:38:32

SF/X Libraries
by SkyAphid
2017-03-02 06:38:05

SF/X Libraries
by SkyAphid
2017-03-02 06:37:51
java-gaming.org is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑gaming.org
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!