User avatar
PeterO
Posts: 5436
Joined: Sun Jul 22, 2012 4:14 pm

Anyone used GL_NV_read_depth extension ?

Wed Jan 08, 2020 10:38 am

If you use google to try and find out how to read the depth (z) buffer in openGLES2/3 you'll find lots of articles that say "You can't do it, it's not supported".

BUT

Looking at the extensions that are supported on the Pi's GLES3 I saw "GL_NV_read_depth"
This took me to https://www.khronos.org/registry/OpenGL ... tencil.txt where it says you CAN read the depth buffer.
So I tried it, and lo and behold you can read the depth buffer with glReadPixels. Luckily my Intel desktop machine supports the same extension.

Has anyone else used this extension ?

My "test jig" shows that calling "glReadPixels(x,y,1,1,GL_DEPTH_COMPONENT,GL_UNSIGNED_SHORT,&depth);" is returning something to do with the depth but I'm not sure how exactly to interpret the returned value. The background returns -1 and I'm getting values between -3000 and -4000 for rendered objects in my scene.

Does anyone know how to convert the values into "world z" coordinates ?

PeterO


PS: It's possible that I've got the type/size of the returned values wrong !
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

Daniel Gessel
Posts: 113
Joined: Sun Dec 03, 2017 1:47 am
Location: Boston area, MA, US
Contact: Website Twitter

Re: Anyone used GL_NV_read_depth extension ?

Wed Jan 08, 2020 12:43 pm

It’s been a while, but IIRC:

Divide unsigned shorts by 65535.0 to get normalized z values. Subtract viewport x and y from pixel x and y, then divide by viewport width and height, respectively. Everything should be in [0, 1] range.

Multiply x, y, and z by 2 and subtract 1 to get clip coordinates [-1, 1] range.

Multiply by the inverse of the equivalent of the projection matrix in your vertex shader, with 1.0 for input w.

Divide x, y and z through by output w.

The first steps can all be combined with the inverse of the projection matrix so it’s a single homogenous matrix x vector multiply.

User avatar
PeterO
Posts: 5436
Joined: Sun Jul 22, 2012 4:14 pm

Re: Anyone used GL_NV_read_depth extension ?

Wed Jan 08, 2020 1:24 pm

I've adjusted my nearZ and farZ values is the Perspective matrix and now I'm getting a much larger range in the raw depth values so I can better see what is going on.

I will now try the calculation you suggest, but I've just had some "deja-vu" that I might have done this all before some years ago when I was playing with desktop openGL 2.1.

I'll let you know how I get on.

Thanks.

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

User avatar
PeterO
Posts: 5436
Joined: Sun Jul 22, 2012 4:14 pm

Re: Anyone used GL_NV_read_depth extension ?

Wed Jan 08, 2020 3:22 pm

This may take a while as I've discovered cglm https://cglm.readthedocs.io/en/latest/
I've decided to strip out my previous matrix/vector/maths code that was based on the examples in the openGL ES 3.0 Programming Guide.
cglm looks to be much better (e.g. it has documentation) and is maintained.

So far I've only replaced a couple of matrix multiplications, a translation and a rotation, but it is looking straightforward

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

User avatar
PeterO
Posts: 5436
Joined: Sun Jul 22, 2012 4:14 pm

Re: Anyone used GL_NV_read_depth extension ?

Thu Jan 09, 2020 9:27 am

Hmmmmm..... :roll:

Not getting the right results , so building a simple test rig with just a single rendered triangle to try and work out where the maths is going wrong.

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

Daniel Gessel
Posts: 113
Joined: Sun Dec 03, 2017 1:47 am
Location: Boston area, MA, US
Contact: Website Twitter

Re: Anyone used GL_NV_read_depth extension ?

Thu Jan 09, 2020 12:10 pm

Sounds like a good plan. Try with a simple vertex shader (no transform) in case I got the first steps wrong. Inverting whatever process the vertex shader goes through to map from world to clip is definitely part of the formula. The other steps I suggested may have a sign error or other basic misstep.

I was looking for open source gluUnProject but couldn’t find it. Found this instead: https://dondi.lmu.build/share/cg/unproj ... lained.pdf

I haven’t looked at it carefully but thought it might prove to be a helpful walkthrough.

User avatar
PeterO
Posts: 5436
Joined: Sun Jul 22, 2012 4:14 pm

Re: Anyone used GL_NV_read_depth extension ?

Thu Jan 09, 2020 12:19 pm

Finally got this working using glm_unproject.

The trick is that this requires a z value in the range 0..1 (not -1..+1 as I was giving it !).

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

User avatar
PeterO
Posts: 5436
Joined: Sun Jul 22, 2012 4:14 pm

Re: Anyone used GL_NV_read_depth extension ?

Thu Jan 09, 2020 12:35 pm

Daniel Gessel wrote:
Thu Jan 09, 2020 12:10 pm
Sounds like a good plan. Try with a simple vertex shader (no transform) in case I got the first steps wrong. Inverting whatever process the vertex shader goes through to map from world to clip is definitely part of the formula. The other steps I suggested may have a sign error or other basic misstep.

I was looking for open source gluUnProject but couldn’t find it. Found this instead: https://dondi.lmu.build/share/cg/unproj ... lained.pdf

I haven’t looked at it carefully but thought it might prove to be a helpful walkthrough.
That's exactly what I did, started off with just a "Hello Triangle" program with no mvpMatrix, then added an identity mvpMatrix and got that working.

allocation is the GtkAllocation for the window.
*em is the GdkEventButton for the current mouse position (this code is in a "motion_notify_event" handler as I want to get a 3D object to track the mouse over a surface);
depth is a GLuint

Code: Select all

	    glReadPixels((GLint)em->x,(GLint)(allocation.height-em->y),1,1,GL_DEPTH_COMPONENT,GL_UNSIGNED_INT,&depth);
	    e = glGetError();
	    if(e != 0)
	    {
		printf("glReadPixels Error  %x\n",e);
		//return;
	    }

	    z = (GLfloat) (depth / 4294967296.0);
	    x = (GLfloat) em->x;
	    y = (GLfloat) (allocation.height - em->y);
    
	    printf("%u (%f,%f,%f) ",depth,(double)x,(double)y,(double)z);

	    glm_unproject((vec3){x,y,z},mvpMatrix,(vec4){0.0,0.0,(GLfloat)allocation.width,
						(GLfloat) allocation.height},xyz);

	    printf("[%f,%f,%f]\n",(double)xyz[0],(double)xyz[1],(double)xyz[2]);
I now need to add code to use glm_mat4_inv to only calculate the mvpMatrix inverse when the camera moves.

PeterO
Discoverer of the PI2 XENON DEATH FLASH!
Interests: C,Python,PIC,Electronics,Ham Radio (G0DZB),1960s British Computers.
"The primary requirement (as we've always seen in your examples) is that the code is readable. " Dougie Lawson

Return to “OpenGLES”