Graphics Programming
Cameras: Perspective Projection
Thorsten Thormählen
November 17, 2023
Part 6, Chapter 1
Thorsten Thormählen
November 17, 2023
Part 6, Chapter 1
This is the print version of the slides.
Advance slides with the → key or
by clicking on the right border of the slide
Slides can also be advanced by clicking on the left or right border of the slide.
Type | Font | Examples |
---|---|---|
Variables (scalars) | italics | $a, b, x, y$ |
Functions | upright | $\mathrm{f}, \mathrm{g}(x), \mathrm{max}(x)$ |
Vectors | bold, elements row-wise | $\mathbf{a}, \mathbf{b}= \begin{pmatrix}x\\y\end{pmatrix} = (x, y)^\top,$ $\mathbf{B}=(x, y, z)^\top$ |
Matrices | Typewriter | $\mathtt{A}, \mathtt{B}= \begin{bmatrix}a & b\\c & d\end{bmatrix}$ |
Sets | calligraphic | $\mathcal{A}, B=\{a, b\}, b \in \mathcal{B}$ |
Number systems, Coordinate spaces | double-struck | $\mathbb{N}, \mathbb{Z}, \mathbb{R}^2, \mathbb{R}^3$ |
$\tilde{\mathbf{P}}= \left( f \frac{p_x}{p_z}, f \frac{p_y}{p_z}, f \right)^\top$
$\frac{\tilde{p}_x}{f} = \frac{p_x}{p_z}$ and $\frac{\tilde{p}_y}{f} = \frac{p_y}{p_z}$
$\tilde{\mathbf{P}}= \begin{pmatrix} \tilde{p}_x \\ \tilde{p}_y \\ \tilde{p}_z \end{pmatrix}= \begin{pmatrix} f \frac{p_x}{p_z}\\ f \frac{p_y}{p_z}\\ f \end{pmatrix} \in \mathbb{R}^3 \longmapsto \underline{\tilde{\mathbf{P}}}= \begin{pmatrix}f \, p_x \\f \, p_y \\ f \, p_z\\ p_z\end{pmatrix} \in \mathbb{H}^3$
$\begin{align}\underline{\tilde{\mathbf{P}}} & = \begin{pmatrix}f \, p_x \\f \, p_y \\ f \, p_z\\ p_z\end{pmatrix} = \underbrace{\begin{bmatrix} f & 0 & 0 & 0 \\ 0 & f & 0 & 0 \\ 0 & 0 & f & 0 \\ 0 & 0 & 1 & 0 \end{bmatrix}}_{\mathtt{A}} \begin{pmatrix}p_x \\p_y \\ p_z\\ 1\end{pmatrix}\\ \underline{\tilde{\mathbf{P}}} &=\mathtt{A}\, \underline{\mathbf{P}} \end{align}$
$\begin{align}\underline{\tilde{\mathbf{P}}} & = \begin{pmatrix}f \, p_x \\f \, p_y \\ f \, p_z\\ -p_z\end{pmatrix} = \underbrace{\begin{bmatrix} f & 0 & 0 & 0 \\ 0 & f & 0 & 0 \\ 0 & 0 & f & 0 \\ 0 & 0 & -1 & 0 \end{bmatrix}}_{\mathtt{A}} \begin{pmatrix}p_x \\p_y \\ p_z\\ 1\end{pmatrix}\\ \underline{\tilde{\mathbf{P}}} &=\mathtt{A}\, \underline{\mathbf{P}} \end{align}$
$p_z=-z_n \quad \mapsto \quad \tilde{p}_z=-1$
and for points on the far-plane:
$p_z=-z_f \quad \mapsto \quad \tilde{p}_z=1$
$\underline{\tilde{\mathbf{P}}} = \begin{pmatrix}f \, p_x \\f \, p_y \\ \alpha \, p_z + \beta \\ -p_z\end{pmatrix} = \begin{bmatrix} f & 0 & 0 & 0 \\ 0 & f & 0 & 0 \\ 0 & 0 & \alpha & \beta \\ 0 & 0 & -1 & 0 \end{bmatrix} \begin{pmatrix}p_x \\p_y \\ p_z\\ 1\end{pmatrix} \in \mathbb{H}^3$
$\tilde{\mathbf{P}}=(\tilde{p}_x,\tilde{p}_y,\tilde{p}_z)^\top = \left( f \frac{p_x}{-p_z}, f \frac{p_y}{-p_z}, -\alpha \, + \frac{\beta}{-p_z} \right)^\top \in \mathbb{R}^3$
$\begin{align} \alpha &= \frac{z_f+z_n}{z_n-z_f}\\ \beta & = \frac{2 z_f \, z_n}{z_n-z_f}\end{align}$
$\begin{align} \underline{\tilde{\mathbf{P}}} & = \underbrace{\begin{bmatrix} f & 0 & 0 & 0 \\ 0 & f & 0 & 0 \\ 0 & 0 & \frac{z_f+z_n}{z_n-z_f} & \frac{2 z_f \, z_n}{z_n-z_f} \\ 0 & 0 & -1 & 0 \end{bmatrix}}_{\mathtt{A}} \begin{pmatrix}p_x \\p_y \\ p_z\\ 1\end{pmatrix}\\ \underline{\tilde{\mathbf{P}}} &=\mathtt{A}\, \underline{\mathbf{P}} \end{align}$
$\frac{f}{1} = \frac{\cos( 0.5 \, \Theta)}{\sin( 0.5 \, \Theta)} \Leftrightarrow f = \mathrm{cotan}( 0.5 \, \Theta)$
GL_PROJECTION
matrix is used.glMatrixMode(GL_PROJECTION);
glLoadIdentity, glLoadMatrix, glMultMatrix, glRotate,
glScale, glTranslate, glPushMatrix, glPopMatrix, gluPerspective
are then executed on the GL_PROJECTION
matrix.
GL_PROJECTION
matrix influences the transformation of objects only if they are drawn (OpenGL as a state machine)Creating a perspective projection matrix in OpenGL:
glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(fovy, aspect, near, far);
$ \mathtt{A} = \begin{bmatrix} \frac{f}{\mathrm{aspect}} & 0 & 0 & 0 \\ 0 & f & 0 & 0 \\ 0 & 0 & \frac{\mathrm{far}+\mathrm{near}}{\mathrm{near}-\mathrm{far}} & \frac{2 \ast \mathrm{far} \ast \mathrm{near}}{\mathrm{near}-\mathrm{far}} \\ 0 & 0 & -1 & 0 \end{bmatrix}$
with $f = \mathrm{cotan}( 0.5 \ast \mathrm{fovy})$
and $\mathrm{aspect}= \mathrm{w} / \mathrm{h}$
$\tilde{p}_y = f \frac{p_y}{-p_z}$
class Renderer { public: float t; //time const float d0; // initial distance public: Renderer() : t(1.0), d0(3.0), width(0), height(0) {} public: void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (dollyZoomFovy(), (float)width/(float)height, 0.1, 50.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // translate camera by 3 units glTranslatef(0.0f, 0.0f, -t*d0); // draw a cube in the local coordinate system drawCube(); // draw random lines drawRandomLines(); } void init() { glEnable(GL_DEPTH_TEST); // create random values between -1.0 and 1.0 for(unsigned r=0; r < 1000; r++) { int r = rand(); randVals.push_back(2.0*float(r)/float(RAND_MAX)-1.0f); } } void resize(int w, int h) { // ignore this for now glViewport(0, 0, w, h); width = w; height = h; } float dollyZoomFovy() { float fovyInit = 60.0f; // initial field of view float theta = fovyInit / 180.0f * M_PI; // degree to rad float f = 1.0f / tan(theta/2.0f); float fNew = f * (d0*t-1) / (d0-1); float thetaNew = atan(1.0f / fNew) * 2.0f; float val = 180.0 * thetaNew / M_PI; //rad to degree return val; } private: int width; int height; std::vector<float> randVals; private: void drawCube() { glColor3f(1.0f, 1.0f, 1.0f); glLineWidth(3.0f); glBegin(GL_LINE_LOOP); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f( 1.0f, 1.0f,-1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f( 1.0f, 1.0f,-1.0f); glVertex3f( 1.0f, 1.0f, 1.0f); glVertex3f( 1.0f,-1.0f, 1.0f); glVertex3f( 1.0f,-1.0f,-1.0f); glEnd(); glBegin(GL_LINE_LOOP); glVertex3f(-1.0f, 1.0f,-1.0f); glVertex3f(-1.0f, 1.0f, 1.0f); glVertex3f(-1.0f,-1.0f, 1.0f); glVertex3f(-1.0f,-1.0f,-1.0f); glEnd(); glLineWidth(1.0); } void drawRandomLines() { if(randVals.size() % 5) return; unsigned i = 0; while(i < randVals.size()) { glColor3f(fabs(randVals[i++]), fabs(randVals[i++]), fabs(randVals[i++])); float x = randVals[i++]; float y = randVals[i++]; glBegin(GL_LINES); glVertex3f(x, y, -1.0f); glVertex3f(x, y, 1.0f); glEnd(); } } };
$\underline{\tilde{\mathbf{P}}} = \mathtt{A} \, \mathtt{T}_{\mathrm{\small cam}}^{-1} \, \mathtt{T}_{\mathrm{\small obj}} \, \underline{\mathbf{P}}$
Mapping equation for homogeneous points:
$\underline{\tilde{\mathbf{P}}} = \mathtt{A} \, \mathtt{T}_{\mathrm{\small cam}}^{-1} \, \mathtt{T}_{\mathrm{\small obj}} \, \underline{\mathbf{P}}$
where the $4 \times 4$ matrix
$ \mathtt{T}_{\mathrm{\small obj}} = \begin{bmatrix}\tilde{\mathbf{b}}_x & \tilde{\mathbf{b}}_y & \tilde{\mathbf{b}}_z & \mathbf{C}_b\\0 & 0 & 0 & 1\end{bmatrix}$
$\begin{align} \mathtt{T}_{\mathrm{\small cam}} & = \begin{bmatrix}\tilde{\mathbf{a}}_x & \tilde{\mathbf{a}}_y & \tilde{\mathbf{a}}_z & \mathbf{C}_a\\0 & 0 & 0 & 1\end{bmatrix} \\ & = \begin{bmatrix} \mathtt{R}_a & \mathbf{C}_a\\ \mathbf{0}^\top & 1\end{bmatrix} \end{align}$
$\mathtt{T}_{\mathrm{\small cam}}^{-1} = \begin{bmatrix} \mathtt{R}_a & \mathbf{C}_a\\ \mathbf{0}^\top & 1\end{bmatrix}^{-1} = \begin{bmatrix} \mathtt{R}_a^{\top} & -\mathtt{R}_a^{\top} \mathbf{C}_a\\ \mathbf{0}^\top & 1\end{bmatrix} $
Mapping equation for homogeneous points:
$\underline{\tilde{\mathbf{P}}} = \mathtt{A} \, \underbrace{\mathtt{T}_{\mathrm{\small cam}}^{-1} \, \mathtt{T}_{\mathrm{\small obj}}}_{\mathtt{T}_{\mathrm{\small modelview}}} \, \underline{\mathbf{P}}$
GL_MODELVIEW
matrixGL_MODELVIEW
matrix directly describes the transformation from the respective local coordinate system to the camera coordinate systemGL_PROJECTION
matrix $\mathtt{A}$ describes the mapping from the camera coordinate system into the image planegluLookAt(eyex, eyey, eyez, refx, refy, refz, upx, upy, upz);
$\begin{align} \mathbf{d} & = \mathbf{C}_{\mathrm{\small eye}} - \mathbf{P}_{\mathrm{\small ref}}\\ \tilde{\mathbf{a}}_z &= \frac{\mathbf{d}}{|\mathbf{d}|}, \mathbf{v}' = \frac{\mathbf{v}_{\mathrm{\small up}}}{|\mathbf{v}_{\mathrm{\small up}}|} \\ \tilde{\mathbf{a}}_x &= \mathbf{v}'\times \tilde{\mathbf{a}}_z \\ \tilde{\mathbf{a}}_y &= \tilde{\mathbf{a}}_z \times \tilde{\mathbf{a}}_x\\ \mathtt{R}_{a} & = \begin{bmatrix}\tilde{\mathbf{a}}_x & \tilde{\mathbf{a}}_y & \tilde{\mathbf{a}}_z \end{bmatrix} \\ \end{align}$
class Renderer { ... void resize(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (30.0, (float)w/(float)h, 2.0, 20.0); } void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // camera orbits in the y=10 plane // and looks at origin double rad = M_PI / 180.0f * t; gluLookAt(10.0*cos(rad), 10.0 , 10.0*sin(rad), // eye 0.0, 0.0, 0.0, // look at 0.0, 1.0, 0.0); // up //draw cube at origin drawCube(); glRotatef(45.0f, 0.0f, 0.0f, 1.0f); glTranslatef(2.5f, 0.0f, 0.0f ); glScalef(0.5f, 0.5f, 0.5f); //draw transformed cube drawCube(); } ... }
glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (...); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); gluLookAt(...); glRotatef(...); glTranslatef(...); glScalef(...);
$\mathtt{T}_{\mathrm{\small projection}}= \mathtt{I}$
$\mathtt{T}_{\mathrm{\small projection}}= \mathtt{I} \, \mathtt{A}$
$\mathtt{T}_{\mathrm{\small modelview}}= \mathtt{I}$
$\mathtt{T}_{\mathrm{\small modelview}}= \mathtt{I}\,\mathtt{T}_{\mathrm{\small cam}}^{-1}$
$\mathtt{T}_{\mathrm{\small modelview}}= \mathtt{I}\,\mathtt{T}_{\mathrm{\small cam}}^{-1} \,\mathtt{T}_r$
$\mathtt{T}_{\mathrm{\small modelview}}= \mathtt{I}\,\mathtt{T}_{\mathrm{\small cam}}^{-1} \,\mathtt{T}_r\,\mathtt{T}_t$
$\mathtt{T}_{\mathrm{\small modelview}}= \mathtt{I}\,\mathtt{T}_{\mathrm{\small cam}}^{-1} \,\mathtt{T}_r\,\mathtt{T}_t\,\mathtt{T}_s $
$\begin{align} \underline{\tilde{\mathbf{P}}} &= \mathtt{T}_{\mathrm{\small projection}} \mathtt{T}_{\mathrm{\small modelview}} \, \underline{\mathbf{P}}\\ &= \mathtt{A} \, \mathtt{T}_{\mathrm{\small cam}}^{-1} \,\mathtt{T}_r\,\mathtt{T}_t\,\mathtt{T}_s \,\underline{\mathbf{P}} \end{align}$
class Renderer { public: float t; public: Renderer() : t(0.0) {} public: void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // camera orbits in the y=10 plane // and looks at origin double rad = M_PI / 180.0f * t; gluLookAt(10.0*cos(rad), 10.0 , 10.0*sin(rad), // eye 0.0, 0.0, 0.0, // look at 0.0, 1.0, 0.0); // up //draw model at origin drawCubeHierarchy(0, 4); } void init() { glEnable(GL_DEPTH_TEST); } void resize(int w, int h) { glViewport(0, 0, w, h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (30.0, (float)w/(float)h, 0.1, 50.0); } private: void drawCube() { ... } void drawCubeHierarchy(int depth, int neighbors) { drawCube(); // draw parent depth +=1; if (depth < 6){ for (int n = 0; n < neighbors; n++){ glPushMatrix(); glRotatef(n*90.0f-90.0f, 0.0f, 0.0f, 1.0f); glTranslatef(2.5f, 0.0f, 0.0f ); glScalef(0.5f, 0.5f, 0.5f); drawCubeHierarchy(depth, 3); // draw children glPopMatrix(); } } } };
When using the fixed-function pipeline the following transformations are applied on the vertex data
$\underline{\mathbf{P}} = \begin{pmatrix}p_x\\p_y\\p_z\\p_w\end{pmatrix} \in \mathbb{H}^3 \quad \longmapsto \quad \mathbf{P}= \begin{pmatrix}\frac{p_x}{p_w}\\\frac{p_y}{p_w}\\\frac{p_z}{p_w} \end{pmatrix} \in \mathbb{R}^3 $
$-p_w < p_x < p_w \quad \longmapsto \quad -1 < \frac{p_x}{p_w} < 1$
glViewport(int ix, int iy, int width, int height)
ix
and iy
define the lower-left corner of the viewport and width
and height
the screen size (the unit is pixels)class Renderer { public: float t; public: Renderer() : t(0.0), width(0), height(0) {} public: void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // top right viewport (look from front) glViewport(width/2, height/2, width/2, height/2); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); drawFrame(); // set camera (look from positive x-direction) gluLookAt(10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); // draw scene drawSceneGrid(); drawRotatingPyramid(); // bottom left viewport (look from left) glViewport(0, 0, width/2, height/2); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); drawFrame(); // set camera (look from negative y-direction) gluLookAt(0.0, -10.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); // draw scene drawSceneGrid(); drawRotatingPyramid(); // top left viewport (look from top) glViewport(0, height/2, width/2, height/2); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); drawFrame(); // set camera (look from positive z-direction) gluLookAt(0.0, 0.0, 10.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0); // draw scene drawSceneGrid(); drawRotatingPyramid(); // bottom right viewport (perspective) glViewport(width/2, 0, width/2, height/2); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); drawFrame(); // set camera gluLookAt(8.0, -2.0, 5.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0); // draw scene drawSceneGrid(); drawRotatingPyramid(); } void init() { glEnable(GL_DEPTH_TEST); //glEnable(GL_CULL_FACE); } void resize(int w, int h) { width = w; height = h; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (30.0, (float)width/(float)height, 0.1, 50.0); } private: int width; int height; private: void drawFrame() { glLineWidth(2.0); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glColor3f(1.0f, 1.0f, 1.0f); glBegin(GL_LINE_LOOP); glVertex3f(-1.0f, 1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 0.0f); glVertex3f( 1.0f,-1.0f, 0.0f); glVertex3f(-1.0f,-1.0f, 0.0f); glEnd(); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glLineWidth(1.0); } void drawSceneGrid() { glColor3f(0.3f, 0.3f, 0.3f); glBegin(GL_LINES); for(unsigned i=0; i<=10; i++) { glVertex3f(-5.0f+i, -5.0f, 0.0f); glVertex3f(-5.0f+i, 5.0f, 0.0f); glVertex3f(-5.0f, -5.0f+i, 0.0f); glVertex3f( 5.0f, -5.0f+i, 0.0f); } glEnd(); glColor3f(0.0f, 0.0f, 1.0f); drawCoordinateAxisZ(); glColor3f(0.0f, 1.0f, 0.0f); drawCoordinateAxisY(); glColor3f(1.0f, 0.0f, 0.0f); drawCoordinateAxisX(); } void drawCoordinateAxisZ() { glLineWidth(2.0); glBegin(GL_LINES); glVertex3f(0.0f, 0.0f, 0.0f); // z-axis glVertex3f(0.0f, 0.0f, 2.0f); glEnd(); glLineWidth(1.0); // z-axis tip glBegin(GL_TRIANGLES); glVertex3f( 0.0f, 0.0f, 2.0f); glVertex3f(-0.05f, 0.05f, 1.9f); glVertex3f( 0.05f, 0.05f, 1.9f); glVertex3f( 0.0f, 0.0f, 2.0f); glVertex3f( 0.05f, -0.05f, 1.9f); glVertex3f(-0.05f, -0.05f, 1.9f); glVertex3f( 0.0f, 0.0f, 2.0f); glVertex3f( 0.05f, 0.05f, 1.9f); glVertex3f( 0.05f, -0.05f, 1.9f); glVertex3f( 0.0f, 0.0f, 2.0f); glVertex3f(-0.05f, -0.05f, 1.9f); glVertex3f(-0.05f, 0.05f, 1.9f); glEnd(); glBegin(GL_POLYGON); glVertex3f( 0.05f, -0.05f, 1.9f); glVertex3f( 0.05f, 0.05f, 1.9f); glVertex3f(-0.05f, 0.05f, 1.9f); glVertex3f(-0.05f, -0.05f, 1.9f); glEnd(); } void drawCoordinateAxisX() { glPushMatrix(); glRotatef(90.0f, 0.0f, 1.0f, 0.0f); drawCoordinateAxisZ(); glPopMatrix(); } void drawCoordinateAxisY() { glPushMatrix(); glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); drawCoordinateAxisZ(); glPopMatrix(); } void drawRotatingPyramid() { glRotatef(t, 0.0f, 0.0f, 1.0f); drawPyramid(); } void drawPyramid() { glColor3f(1.0,0.0,0.0); glBegin(GL_TRIANGLES); glVertex3f( 0.0f, 0.0f, 1.5f); glVertex3f(-1.0f, 1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 0.0f); glEnd(); glColor3f(0.0,1.0,0.0); glBegin(GL_TRIANGLES); glVertex3f( 0.0f, 0.0f, 1.5f); glVertex3f( 1.0f, -1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f); glEnd(); glColor3f(0.0,0.0,1.0); glBegin(GL_TRIANGLES); glVertex3f( 0.0f, 0.0f, 1.5f); glVertex3f( 1.0f, 1.0f, 0.0f); glVertex3f( 1.0f, -1.0f, 0.0f); glEnd(); glColor3f(1.0,1.0,0.0); glBegin(GL_TRIANGLES); glVertex3f( 0.0f, 0.0f, 1.5f); glVertex3f(-1.0f, -1.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 0.0f); glEnd(); glColor3f(0.0,1.0,1.0); glBegin(GL_POLYGON); glVertex3f( 1.0f, -1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 0.0f); glVertex3f(-1.0f, -1.0f, 0.0f); glEnd(); } };
glEnable(GL_DEPTH_TEST)
and glClear(GL_DEPTH_BUFFER_BIT)
were used without discussing their functionalityglEnable(GL_DEPTH_TEST)
is used to activated the depth test in OpenGLglClear(GL_DEPTH_BUFFER_BIT)
FOR each primitiv FOR each pixel of primitive at position (x,y) with colour c and depth d IF d < depthbuffer(x,y) framebuffer(x,y) = c depthbuffer(x,y) = d END IF END FOR END FOR
class Renderer { public: float t; int width, height; double nearPlane, farPlane; int depthBits; public: Renderer() : t(0.0), nearPlane(2.0), farPlane(20.0) {} public: void resize(int w, int h) { glViewport(0, 0, w, h); width = w; height = h; } void display() { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective (30.0, (float)width/(float)height, nearPlane, farPlane); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // camera orbits in the y=10 plane // and looks at origin double rad = M_PI / 180.0f * t; gluLookAt(10.0*cos(rad), 10.0 , 10.0*sin(rad), // eye 0.0, 0.0, 0.0, // look at 0.0, 1.0, 0.0); // up //draw cube at origin drawCube(); } void init() { glEnable(GL_DEPTH_TEST); glGetIntegerv (GL_DEPTH_BITS, &depthBits); } private: void drawCube() { ... } };
Please notify me by e-mail if you have questions, suggestions for improvement, or found typos: Contact