Depth, depth cache, depth test and save as image in OpenGL

Source: Internet
Author: User

1. Depth

The so-called depth is the distance of the pixel z coordinate from the camera in the OpenGL coordinate system. The camera may be placed anywhere in the coordinate system, so it is not easy to say that the greater the z value or the smaller the closer the camera is.

2. Depth buffer

The deep buffer principle is to associate the depth value (or distance) of a distance observation plane (near clipping surface) with each pixel in the window.
First, use Glclear (gl_depth_buffer_bit) to set the depth value of all pixels to the maximum value (typically a far clipping surface).
Then, draw all the objects in any order in the scene. The graphical calculations performed by the hardware or software convert each painted surface into a collection of pixels on the window, regardless of whether it is obscured by other objects.
Second, OpenGL calculates the distance between these surfaces and the observation plane. If the depth buffer is enabled, OpenGL compares its depth value to the depth value already stored in the pixel before each pixel is drawn. The new pixel depth value < The original pixel depth value, the new pixel value replaces the original, whereas the new pixel value is obscured and his color value and depth are discarded.

In order to start the depth buffer, you must first start it, i.e. glenable (gl_depth_test). Each time you draw a scene, you need to clear the depth buffer, glclear (gl_depth_buffer_bit), and then draw the objects in the scene in any order.

Math Basics:

The depth in the camera space to be rendered is often defined as the z-value between the close near to distant far, and the z-coordinate is the same as the x and Y coordinates. After transformation, clipping, and perspective division, the range of Z is -1.0~1.0. The Depthrange map specifies the transformation of the z-coordinate, similar to the viewport transformation used to map X and Y to the window coordinates, after the perspective transformation, to get the new Z ' value:

This is the value of the camera space, which is sometimes expressed as W or W '.

The result z ' is a value after normalization between 1 and 1, where the close near plane is located at-1, and the distant far plane is at 1. The corresponding point outside this range is outside the view body and does not need to be rendered.

In order to achieve depth buffering, the value of Z ' is interpolated between the current polygon vertices in the entire screen space, usually these intermediate values are saved in the depth buffer in the fixed-point format. The closer the close to the near plane, the more dense z ' values are, and the farther away the Z ' value becomes. The closer the camera is, the higher the accuracy. The nearer plane is closer to the camera, the lower the accuracy of the long distance position. Near plane distance camera too close is a common factor that produces human error in long distance objects.

3. In-depth testing

The depth test in OpenGL is to use the deep buffer algorithm to eliminate the non-meeting in the scene. By default, the depth value in the depth cache ranges from 0.0 to 1.0, and this range value can be passed through the function:
Gldepthrange (nearnormdepth, farnormaldepth);
The range of depth values is changed from nearnormdepth to Farnormaldepth. Here nearnormdepth and farnormaldepth can take any value from 0.0 to 1.0, even for nearnormdepth > farnormaldepth. In this way, the Gldepthrange function allows for deep testing in any area of the perspective projection finite observation space.
Another very useful function is:
Glcleardepth (maxDepth);
The parameter maxdepth can be any value in the range of 0.0 to 1.0. Glcleardepth initializes the depth cache with MaxDepth, and by default, the depth cache is initialized with 1.0. Because the polygons that are larger than the depth cache initial values are not drawn in the depth test, the glcleardepth function can be used to speed up the deep test processing. It is important to note that after you specify the initialization value for the depth cache, you should call:
Glclear (Gl_depth_buffer_bit); Completes the initialization of the deep cache.
In the depth test, the default is to compare the Z-value of the new pixel that needs to be drawn to the z-value of the corresponding position in the depth buffer, and if it is smaller than the value in the depth cache, update the color value of the corresponding pixel in the frame cache with the color value of the new pixel. This comparison test can be done by using a function:
Gldepthfunc (func);
Be modified. The value of the parameter Func can be gl_never (no processing), gl_always (processing All), gl_less (less than), gl_lequal (less than equals), gl_equal (equals), gl_gequal (greater than or equal), Gl_ GREATER (greater than) or gl_notequal (not equal to), where the default value is gl_less. These tests can reduce the computation of deep cache processing in a variety of applications.

There is a very useful function in OpenGL: Glreadpixels (), which can read the values of various buffers (depth, color, etc). You need to use this function to save OpenGL's drawing scene as a picture.

For a simple example, see the C program below. Press the "C" key on the keyboard to store the read image buffer data as tmpcolor.txt. #include "windows.h" #include <GL/glut.h> #include <gl/glaux. H> #include <iostream> using namespace std;   // typedef glbyte* BYTEPT;   int winwidth = n; int winheight = n; int arrlen = winwidth * winheight * 3; glbyte* Colorarr = new glbyte[Arrlen];   void Savecolordata (bytept& _pt, string& _str) { file* pFile = NULL; pFile = fopen (_str.c_str (), "wt"); if (!pfile) {fprintf (stderr, "error \ n"); exit ( -1);}   for (int i=0; I<winwidth * winheight * 3; i + +) { if (colorarr[i] = =-1) {colorarr[i] = 255;} }   for (int i=0; I<winwidth * winheight * 3; i + +) { fprintf (PFile, "%d\n", Colorarr[i]); } fclose (pFile); printf ("Color data saved! \ n "); }   void init () { Glclearcolor (0.5, 0.5, 0.5, 0.0); Glshademodel (gl_smooth); }   void Display () { glclear (gl_color_buffer_bit);   Glmatrixmode (gl_modelview); glloadidentity (); Glulookat (0.0, 0.0, 100.0, 0.0 , 0.0, 0.0, 0.0, 1.0, 0.0);   Glmatrixmode (gl_projection); glloadidentity (); gluperspective (45.0, 1.0, 0.1, 500.0); Glmatrixmode (gl_modelview);   glcolor3f (1.0, 0.0, 0.0); Glbegin (gl_triangles); glvertex3f (0.0, 25.0, 0.0); glvertex3f ( -25.0, -25.0, 0.0); glvertex3f (25.0, -25.0, 0.0); glend ();   Glflush (); }   void keyboard (unsigned char key, int x, int y) { Glint Viewport[4] = {0}; switch (key) { Case ' C ': Case ' C ': Glgetintegerv (Gl_viewport, VIEWPORT); Glreadpixels (viewport[0], viewport[1], viewport[2], viewport[3], Gl_rgb, Gl_unsigned_byte, Colorarr); printf ("Color data read!\n"); Savecolordata (Colorarr, (String) "Tmpcolor.txt"); Default: Break ; } }   int main (int argc, char** argv) { Glutinit (&ARGC, argv); Glutinitdisplaymode (Glut_single | GLUT_RGB); Glutinitwindowposition (a); Glutinitwindowsize (+--); Glutcreatewindow (argv[0]); init (); Glutdisplayfunc (display); Glutkeyboardfunc (keyboard); Glutmainloop ();   Delete [] Colorarr;   return 0; }  Tmpcolor.txt the color of each pixel in the order of R, G, B into a vector, i.e. (r,g,b,r,g,b,... )。 Also, the origin of coordinates in the reading buffer is the coordinate origin of the window coordinate system (the lower left corner of the picture), so the original picture can be adjusted in MATLAB: function Test a = Load (' tmpcolor.txt ');   pos = Find (A = =-1); A (POS) = 255;   r = A (1:3:end); g = A (2:3:end); B = A (3:3:end); img = zeros (400,400,3); img (:,:, 1) = reshape (r,[400,400]); img (:,:, 2) = reshape (g,[400,400]); img (:,:, 3) = reshape (b,[400,400]); img = uint8 (img);      tmpr = zeros (400,400); TMPR = IMG (:,:, 1); tmpg = zeros (400,400); Tmpg = IMG (:,:, 2); TMPB = zeros (400,400); TMPB = IMG (:,:, 3);      For i=1:1:400 img (i,:,1) = TMPR (:, 400-i+1); img (i,:,2) = Tmpg (:, 400-i+1); img (i,:,3) = TMPB (:, 400-i+1); End      Figure ; imshow (IMG); End      Of course, after reading the data, you can easily store the image using tools such as OPENCV. A corresponding OPENCV code is: void Savecolordata2img (bytept& _pt, string& _str) { cv::mat img; vector<cv::mat> Imgplanes; img.create (Winheight, Winwidth, cv_8uc3); cv::split (IMG, imgplanes);   for (int i = 0; i < winheight; i + +) { uchar* plane0ptr = imgplanes[0].ptr<uchar> (i); uchar* plane1ptr = imgplanes[1].ptr<uchar> (i); uchar* plane2ptr = imgplanes[2].ptr<uchar> (i); For (int j = 0; J < Winwidth; J + +) { int k = 3 * (i * winwidth + j); Plane2ptr[j] = _pt[k]; Plane1ptr[j] = _pt[k+1]; Plane0ptr[j] = _pt[k+2]; } } cv::merge (Imgplanes, IMG); cv::flip (IMG, IMG, 0);//!!! Cv::imwrite (_STR.C_STR (), IMG);   printf ("OpenCV Save OpenGL IMG done! \ n "); }      It is important to note that if you want to dump OpenGL scenes integrated in MFC into pictures, because the pixel format in MFC only supports RGBA and color indexing, you need to use Gl_rgba as a parameter in Glreadpixels. The corresponding write a C + + class, for reference: class Glgrabber { Public : Glgrabber (); ~glgrabber ();   void Glgrab (); void Savecolordata2img (string& _str); Private: glbyte* Colorarr; Glint viewport[4]; int winwidth; int winheight; };   // Glgrabber::glgrabber () { Colorarr = NULL; }   // Glgrabber::~glgrabber () { if (colorarr!=null) {delete [] colorarr; colorarr = NULL;} }   // void Glgrabber::glgrab () { Glgetintegerv (Gl_viewport, VIEWPORT); if (Colorarr! = null) {delete [] colorarr; colorarr = null;} winwidth = viewport[2]; winheight = viewport[3];   Colorarr = new glbyte[winwidth * winheight * 4];//MFC's pixel format only supports RGBA   Glreadpixels (viewport[0], viewport[1], viewport[2], viewport[3], Gl_rgba, Gl_unsigned_byte, COLORARR);//RGBA   printf ("x:%d, y:%d, window width:%d, window height:%d \ n", Viewport[0], viewport[1], viewport[2], viewport[3]); printf ("Color data read! \ n "); }   // void Glgrabber::savecolordata2img (string& _str) { cv::mat img; vector<cv::mat> Imgplanes; img.create (Winheight, Winwidth, cv_8uc3); cv::split (IMG, imgplanes);   for (int i = 0; i < winheight; i + +) { uchar* plane0ptr = imgplanes[0].ptr<uchar> (i); uchar* plane1ptr = imgplanes[1].ptr<uchar> (i); uchar* plane2ptr = imgplanes[2].ptr<uchar> (i); For (int j = 0; J < Winwidth; J + +) { int k = 4 * (i * winwidth + j);//RGBA Plane2ptr[j] = colorarr[k]; Plane1ptr[j] = colorarr[k+1]; Plane0ptr[j] = colorarr[k+2]; } }   cv::merge (Imgplanes, IMG); cv::flip (IMG, IMG, 0);//!!! Cv::namedwindow ("Openglgrab"); cv::imshow ("Openglgrab", IMG); Cv::waitkey ();   //cv::imwrite (_STR.C_STR (), IMG);   printf ("OpenCV Save OpenGL IMG done! \ n "); }

Depth, depth cache, depth test and save as image in OpenGL

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.