Java-Gaming.org Java4K winners: [ by our judges | by the community ]         
Featured games (67)
games approved by the League of Dukes
Games in Showcase (∞)
games submitted by our members



News: Read the Java Gaming Resources, or peek at the official Java tutorials
 
    Home     Help   Search   Login   Register   
Pages: [1]
  Print  
  Write names to additional buffer similar to z-buffer  (Read 2189 times)
0 Members and 2 Guests are viewing this topic.
Offline Saxer

Full Member
**

Posts: 115



« on: 2007-03-30 14:26:04 »

Hi there,

is it possible to write the names used on the namestack to a buffer object.

Let the z-Buffer be something like

0 0 0 0
1 0 1 1
1 1 1 1

and I used to "named" polygons for this rendering (names: 1 and 2).
I'd like the new buffer to be:

1 1 1 1
2 1 2 2
2 2 2 2

so I could easily say which is shown at pixel x,y. My aim is to avoid the picking-routine. I'll apply this technique only with very static scenes.

Thanks for any answer
Klemens
Online Riven
« League of Dukes »

JGO Kernel
*****

Posts: 5872
Medals: 255


Hand over your head.


« Reply #1 on: 2007-03-30 15:10:44 »

Yup, but instead of 'names', use color-coding as a first rendering-pass:
- disable all textures/lighting/shaders that change the fragment-colors
- give every group-of-polys a unique color (glColor3ub)
- grab the pixel-color at X,Y and multiply the R,G,B back to your 'name'
you can fake a name-stack with a max depth of 3, by limiting yourself to 256 items at each level

Now clear the scene, render it with textures, lighting and whatnot, like you'd normally do.

If you want to use it in a 'buffer object', you might want to render-to-texture, and fetch the values using a fancy shader.

Hi, appreciate more people! Σ ♥ = ¾

Learn how to award medals... and work your way up the social rankings
Offline Saxer

Full Member
**

Posts: 115



« Reply #2 on: 2007-03-30 15:40:00 »

Thanks for your reply. That's what I wantet.

I think I will render into a pBuffer. The color-coding without shading and light was my idea too. Can I get the pixel-values of the pBuffer via pBuffer.getGL().glReadPixels(...)?

I'm using GLJPanel without an animator, so I'm not always aware of sporadic repaint => display-calls. So I don't want to use mutexes which would block my on screen rendering.

Thanks so far.
Just little steps are missing
Games published by our own members! Go get 'em!
Online Riven
« League of Dukes »

JGO Kernel
*****

Posts: 5872
Medals: 255


Hand over your head.


« Reply #3 on: 2007-03-30 17:02:01 »

I have no experience with PBuffers unfortunately. I guess you can call glReadPixels() on them. If you'd go for RTT, you can read your pixels from the texture like any texture-pixel-download.

Hi, appreciate more people! Σ ♥ = ¾

Learn how to award medals... and work your way up the social rankings
Offline Ken Russell

JGO Kernel
*****

Posts: 3446
Medals: 3


Java games rock!


« Reply #4 on: 2007-03-30 22:21:48 »

Just to confirm, yes, you can call glReadPixels() against a pbuffer. A GLAutoDrawable attached to a GLPbuffer behaves the same as when it's attached to, for example, an on-screen GLCanvas.
Offline Saxer

Full Member
**

Posts: 115



« Reply #5 on: 2007-03-31 07:29:36 »

Thanks for your answers...

I tried to setup my pBuffer (the canCreatePBuffer method returns true on my intel-855GM).

Unfortunately I can't find the "another pbuffer thread", which is quoted often within other threads.

But I get the following error:
pbuffer creation error: Couldn't find a suitable pixel format

The code I am using:

GLCapabilities caps = new GLCapabilities();
//      caps.setDoubleBuffered(true);
//      caps.setHardwareAccelerated(true);
//      caps.setRedBits(Cool;
//      caps.setGreenBits(Cool;
//      caps.setBlueBits(Cool;
//      caps.setAlphaBits(Cool;
//      caps.setSampleBuffers(true);
//      caps.setNumSamples(3);
      
      mouseBuffer = GLDrawableFactory.getFactory().createGLPbuffer(
            caps, new DefaultGLCapabilitiesChooser(), renderPanel.getWidth(),
            renderPanel.getHeight(), null);

How can I work around this problem?

Greets
Klemens
Offline Saxer

Full Member
**

Posts: 115



« Reply #6 on: 2007-03-31 08:52:31 »

In case, of an jogl/intel issue, I tried to render and read back the pixeldata..

//... rendering code with "false colors"

intBuffer = BufferUtil.newIntBuffer(renderPanel.getWidth() * renderPanel.getHeight() * 4);
gl.glReadPixels(0, 0, renderPanel.getWidth(), renderPanel.getHeight(), GL.GL_BGRA, GL.GL_UNSIGNED_BYTE, intBuffer);
for (int i = 0; i < renderPanel.getWidth() * renderPanel.getHeight() * 4; i ++) {
 if (intBuffer.get(i) != 0) {
System.out.print(intBuffer.get(i) + " an " + i);
}
}

//... normal rendering code

unfortunately the intBuffer ist empty... just 0's
Offline Saxer

Full Member
**

Posts: 115



« Reply #7 on: 2007-03-31 09:03:22 »

I have no experience with PBuffers unfortunately. I guess you can call glReadPixels() on them. If you'd go for RTT, you can read your pixels from the texture like any texture-pixel-download.

I'm also new with the RTT thing... could you point me to the basic steps of this method?
Offline Saxer

Full Member
**

Posts: 115



« Reply #8 on: 2007-03-31 18:57:31 »

I found this thread(http://www.java-gaming.org/forums/index.php?topic=13473.15), but I still keep getting 0's as colors.

My colors are set via - for example: glColor3ub((byte) 255, (byte) 0,(byte) 0)

1  
2  
3  
4  
5  
6  
7  
8  
IntBuffer buf = BufferUtil.newIntBuffer(3);

gl.glReadPixels(renderPanel.getWidth() / 2, renderPanel.getHeight() / 2 - 30, 1, 1, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, buf);
buf.rewind();

int r = buf.get() & 0xFF;
int g = buf.get() & 0xFF;
int b = buf.get() & 0xFF;


The pixel at this position is definitively != 0...

I hope the problem is just a very silly mistake on my side

And sorry for my flooding...
Offline Ken Russell

JGO Kernel
*****

Posts: 3446
Medals: 3


Java games rock!


« Reply #9 on: 2007-03-31 19:26:58 »

Try doing a simple test where you use glClear() and glClearColor() to get the entire background color set up. Also double-check to make sure the read buffer is set up correctly, although the default should be correct for the GLPbuffer. Also, triple-check to make sure you are calling this while an OpenGL context is current; you can do this by installing a DebugGL in your GLEventListener.init() method.
Games published by our own members! Go get 'em!
Offline Saxer

Full Member
**

Posts: 115



« Reply #10 on: 2007-04-01 05:46:01 »

Oh I'm so sorry... it didn't have the context current (just wondering why I didn't get any exception)... within the renderloop I'm able to get my pixel-data. I now try to use the panel.getcontext().makeCurrent() just fearing some synchronization problems.

I tried to set up the GLPbuffer within the renderloop (with all the default values) but it kept failing with the above mentioned exception. I really think it's because of my intel graphcis board!?

Thanks so far
Klemens
Online Riven
« League of Dukes »

JGO Kernel
*****

Posts: 5872
Medals: 255


Hand over your head.


« Reply #11 on: 2007-04-01 05:57:39 »

You're interested in *bytes* (GL_UNSIGNED_BYTE) and you read 3 *ints* (meaning the last 2 ints are definitly 0)

So pass a ByteBuffer as argument, or read back only 1 int from the IntBuffer and fetch the bytes with some bit-shifting.

Hi, appreciate more people! Σ ♥ = ¾

Learn how to award medals... and work your way up the social rankings
Offline Saxer

Full Member
**

Posts: 115



« Reply #12 on: 2007-04-01 09:16:44 »

Hehe yes... it was the first quick hack...

In "production" use I'd changed this. For now I was quite happy with a result != 0  Grin
Offline Saxer

Full Member
**

Posts: 115



« Reply #13 on: 2007-04-09 11:34:05 »

Just one problem is left...

In my application I do the false-color-rendering on demand after doing certain geometry-transforms. I didn't want to do this in the display-cycle. So I wrote this code to ensure the context I'm using is "current".

   renderPanel.getContext().setSynchronized(true);
   renderPanel.getContext().makeCurrent();
   render(renderPanel.getGL(), true);
   renderPanel.getContext().release();
   renderPanel.getContext().setSynchronized(false);

For me it's no problem to "wait" in the makeCurrent-method. But unfortunately if I run this code with the opengl-pipeline enabled my glReadPixels() results in 0's just like before. Am I doing something wrong here?

My first workaround is something like this:

if (!Java2D.isOGLPipelineActive()) {
renderPanel.getContext().setSynchronized(true);
renderPanel.getContext().makeCurrent();
render(renderPanel.getGL(), true);
renderPanel.getContext().release();
renderPanel.getContext().setSynchronized(false);
} else {
needsFalseColoring = true;
}

where needsFalseColoring is a flag which is handled in the display-cycle. But as I said I'd like to bypass the display-cycle.

Thanks for any help (it's no really bad problem, but I'd like to solve it)
Klemens
Offline Ken Russell

JGO Kernel
*****

Posts: 3446
Medals: 3


Java games rock!


« Reply #14 on: 2007-04-09 13:13:48 »

Sorry, but unless you rewrite the GLJPanel you're not going to have access to the drawables and contexts you need in order to manually make the OpenGL context current. In fact, it isn't possible to make it current on the current thread -- you would currently have to run a Runnable on another thread. The best and most portable solution is to do all of your work in your display() callback.
Offline Saxer

Full Member
**

Posts: 115



« Reply #15 on: 2007-04-09 14:06:26 »

Ok, so I will do it as my last code-block described.
Offline Saxer

Full Member
**

Posts: 115



« Reply #16 on: 2007-04-20 06:19:59 »

I just found out, that the glReadPixel-method causes a crash when multiple reshape calls occur in short time-distances.

I have the glReadPixels in my render-method. If I (just for testing) change the size of the GLJpanel frequently via a frame-resize the programm (and sometimes the system) crashes.

Any suggestions on this?
Offline Ken Russell

JGO Kernel
*****

Posts: 3446
Medals: 3


Java games rock!


« Reply #17 on: 2007-04-20 22:54:56 »

Do you have a test case for this?

The system shouldn't crash under any circumstances -- this sounds like a driver bug. Perhaps the buffer you're passing in to glReadPixels isn't large enough? Note that the pbuffer which backs the GLJPanel is larger than the GLJPanel's size, so if you aren't careful you may be reading back too much data.
Offline Saxer

Full Member
**

Posts: 115



« Reply #18 on: 2007-04-21 06:07:59 »

I'll provide a test-case next week. Or maybe later today.

I always rebuild the buffer with gljpanel.getWidth() * gljpanel.getHeight() * 3 and I'm reading unsigned bytes. So that should be okay. The problem I see is about hectic resizes. Where the GLJPanel (as a simple jcomponent) is resized (so the getWidth and getHeight calls result the new width) but the viewport and the unerlying gl-stuff etc. is still of a different size cause of the reshape call come's a bit later.

Currently I'm setting a flag like "rebuildTheBuffer" within the reshape method. Anfortunaltey there come a lot reshape calls after each other so just when this flag is used to rebuild the buffer other reshape calls (and other resizings of course) let it crash. I tried to synchronize between the reshape method and my glReadBuffer-call, but the problem lies deeper within the gljpanel (or the driver) so my reshape-callback comes too late to react in a fitting manner.
Offline Saxer

Full Member
**

Posts: 115



« Reply #19 on: 2007-04-21 12:07:21 »

So here's my testcase. Just try to resizes the frame some times without releasing the mouse.

Edit: I changed the mousebuffer to have a 1024*1024*3 size as you said ((width+1)*(height+1)*3 works as well). And no exceptions occur... so why is there a problem by using real sizes? So take this testcase just as an implementation question  Grin

It crashes on nvidia and intel with following error:

#
# An unexpected error has been detected by Java Runtime Environment:
#
#  EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x77f437fe, pid=3972, tid=4060
#
# Java VM: Java HotSpot(TM) Client VM (1.6.0-b105 mixed mode)
# Problematic frame:
# C  [ntdll.dll+0x37fe]
#
# An error report file with more information is saved as hs_err_pid3972.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
#

Sometimes I get an error like: Windows detected a problem with javaw.exe....

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  
import java.nio.ByteBuffer;

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

import com.sun.opengl.util.BufferUtil;


public class ReshapeReadPixelTest {

   public static boolean read = true;
   /**
    * @param args
    */

   public static void main(String[] args) {

      final GLJPanel panel = new GLJPanel();
      panel.setOpaque(false);
      panel.addGLEventListener(new GLEventListener() {

         private ByteBuffer mouseBuffer;
         private int width;
         private int height;

         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.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();
           
            if (read) {
               read = false;
               mouseBuffer = BufferUtil.newByteBuffer(width * height * 3);
               gl.glReadPixels(0, 0, width, height, GL.GL_RGB, GL.GL_UNSIGNED_BYTE, mouseBuffer);
            }
         }

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

         public void init(GLAutoDrawable arg0) {
         }

         public void reshape(GLAutoDrawable arg0, int x, int y, int width, int height) {
            this.width = width;
            this.height = height;
            read = true;
            GL gl = arg0.getGL();
            GLU glu = new GLU();
            gl.glViewport(x, y, width, height);
            gl.glMatrixMode(GL.GL_PROJECTION);
            gl.glLoadIdentity();
   
            glu.gluPerspective(45.0, (float) width / height, 1.0, 400.0);
            gl.glMatrixMode(GL.GL_MODELVIEW);
            gl.glLoadIdentity();
   
            glu.gluLookAt(0, 0, 5, 0, 0, 0, 0, 1, 0);
           
//            panel.repaint();
        }
         
      });
     
      JFrame f = new JFrame();
      f.setSize(300,300);
      f.add(panel);
     
      f.setVisible(true);
   }

}
Offline Ken Russell

JGO Kernel
*****

Posts: 3446
Medals: 3


Java games rock!


« Reply #20 on: 2007-04-21 15:03:48 »

The issue is that the GL_PACK_ALIGNMENT defaults to 4 and you're allocating 3 bytes per pixel so you're overrunning the pixel read buffer. If you insert a call to gl.glPixelStorei(GL.GL_PACK_ALIGNMENT, 1); before your call to glReadPixels() that solves the problem.
Offline Saxer

Full Member
**

Posts: 115



« Reply #21 on: 2007-04-21 19:02:46 »

Well I'll check this out. The funny thing is, that it's wokring perfectly without any hectic resizing. Could you point me a bit closer to the problem. I'd like to understand it.
Offline Ken Russell

JGO Kernel
*****

Posts: 3446
Medals: 3


Java games rock!


« Reply #22 on: 2007-04-22 01:33:03 »

The issue is that for each pixel read back into your buffer, OpenGL is writing 3 bytes and then aligning the destination address to a 4-byte aligned value. Since your buffer is only big enough to hold three bytes per pixel, you're overrunning the end of your readback buffer and corrupting the C heap. This is causing crashes later when free() is called by the code inside the JDK which deallocates the backing store for your direct buffer.
Pages: [1]
  Print  
 
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.16 | SMF © 2011, Simple Machines Valid XHTML 1.0! Valid CSS!
Page created in 0.142 seconds with 20 queries.