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
|
|
|
|
|
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
|
|
|
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!
|
|
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
|
|
|
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.
|
|
|
|
|
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(  ; // caps.setGreenBits(  ; // caps.setBlueBits(  ; // caps.setAlphaBits(  ; // 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
|
|
|
|
|
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
|
|
|
|
|
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?
|
|
|
|
|
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...
|
|
|
|
|
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!
|
|
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
|
|
|
|
|
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
|
|
|
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 
|
|
|
|
|
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
|
|
|
|
|
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.
|
|
|
|
|
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.
|
|
|
|
|
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?
|
|
|
|
|
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.
|
|
|
|
|
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.
|
|
|
|
|
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  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; 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); } }); JFrame f = new JFrame(); f.setSize(300,300); f.add(panel); f.setVisible(true); }
} |
|
|
|
|
|
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.
|
|
|
|
|
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.
|
|
|
|
|
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.
|
|
|
|
|
|