CS 354Transformation, Clipping, and CullingMark KilgardUniversity of TexasJanuary 31, 2012
CS 354 2
Today’s material
Homework #2 assigned, due Thursday start of class! Math problems http://www.cs.utexas.edu/~mjk/teaching/cs354_s12/hw2.pdf
In-class quiz Lecture topic: graphics math & transformations
How do vertex positions transformed to NDC space? Generalized clipping and culling
Assignment Reading
Chapter 6, 310-322 Next project (Project #1) to be assigned Thursday, February 2
Building a 3D object model loader Due Thursday, February 16
CS 354 3
Course Information Reminders Piazza
Working well now https://piazza.com/utexas/cs354
Public CS course web site http://www.cs.utexas.edu/~mjk/teaching/cs354_s12/
Lecture slides in PDF form Now has class lecture schedule
Slideshare.net http://www.slideshare.net/Mark_Kilgard
Lecture slides for web browser viewing
CS 354 4
My Office Hours
Tuesday, before class Painter (PAI) 5.35 8:45 a.m. to 9:15
Thursday, after class ACE 6.302 11:00 a.m. to 12:00
CS 354 5
Last time, this time
Last lecture, we discussed Setup for interpolation Basic hidden surface removal via depth
testing Simplistic pixel updates
This lecture Getting coordinates from object space to
NDC space Generalized clipping and culling
CS 354 6
Daily Quiz
1. Scenario: Depth buffering is enabled, the depth buffer is cleared to 1.0, the depth function is “less than”; and color writes are enabled (blending is disabled)…
A stream of shaded fragments are rasterized to the pixel location (24.5, 11.5) in the following order with their depth and color indicated:
1: [ depth = 0.7, red ]2: [ depth = 0.9, green ]3: [ depth = 0.3, pink ]4: [ depth = 0.4, green ]
What is the final depth and color of the pixel at (24.5, 11.5)?
2. Setting up the plane equation for an interpolated attribute for a triangle to rasterize involves which of the following?
A) Solving a system of equations with 3 unknownsB) Watertight perimeter computationC) Evaluating the quadratic equationD) Inverting a 5x5 matrix
3. For barycentric triangle interpolation, the three barycentric weights for each vertex sum to what value?
On a sheet of paper• Write your EID, name, and date• Write #1, #2, #3, followed by its answer
CS 354 7
Programmer’s View:OpenGL API Example
Let’s draw a triangleglShadeModel(GL_SMOOTH); // smooth color interpolationglEnable(GL_DEPTH_TEST); // enable hidden surface removal
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glBegin(GL_TRIANGLES); { // every 3 vertexes makes a triangle glColor4ub(255, 0, 0, 255); // RGBA=(1,0,0,100%) glVertex3f(-0.8, 0.8, 0.3); // XYZ=(-8/10,8/10,3/10)
glColor4ub(0, 255, 0, 255); // RGBA=(0,1,0,100%) glVertex3f( 0.8, 0.8, -0.2); // XYZ=(8/10,8/10,-2/10)
glColor4ub(0, 0, 255, 255); // RGBA=(0,0,1,100%) glVertex3f( 0.0, -0.8, -0.2); // XYZ=(0,-8/10,-2/10)} glEnd();
Pro Tip: use curly braces to “bracket” nested OpenGLusage; no semantic meaning, just highlights grouping
CS 354 8
Programmer’s View:GLUT API Example
Windowing code#include <GL/glut.h> // includes necessary OpenGL headers
void display() { // << insert code on prior slide here >> glutSwapBuffers();}
void main(int argc, char **argv) { // request double-buffered color window with depth buffer glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH); glutInit(&argc, argv); glutCreateWindow(“simple triangle”); glutDisplayFunc(display); // function to render window glutMainLoop();}
FYI: GLUT = OpenGL Utility Toolkit
CS 354 9
A Simplified Graphics PipelineApplication
Vertex batching & assembly
Triangle assembly
Triangle clipping
Triangle rasterization
Fragment shading
Depth testing
Color update
Application-
OpenGL API boundary
Framebuffer
NDC to window space
Depth buffer
severaloperations
left outfor simplicityin explaining
the simple_triangleexample
CS 354 10
A few more steps expandedApplication
Vertex batching & assembly
Lighting
View frustum clipping
Triangle rasterization
Fragment shading
Depth testing
Color update
Application-
OpenGL API boundary
Framebuffer
NDC to window space
Depth buffer
Vertex transformation
User defined clipping
Back face culling
Perspective divide
Triangle assemblyTexture coordinate generation
was just “triangle clipping” before
CS 354 11
Conceptual Vertex Transformation
glVertex*API
commands
Modelviewmatrix
User-definedclip planes
View-frustumclip planes
to primitiverasterization
object-space coordinates
(xo,yo,zo,wo) eye-space coordinates
(xe,ye,ze,we)
clipped eye-space coordinates
clipped clip-space coordinates Perspective
divisionProjection
matrix
Viewport + Depth Rangetransformation
(xc,yc,zc,wc)
window-spacecoordinates
(xw,yw,zw,1/wc)
normalized device coordinates (NDC)
(xn,yn,zn,1/wc)
clip-spacecoordinates
(xc,yc,zc,wc)
(xe,ye,ze,we)
(xe,ye,ze,we)
CS 354 12
User Clip Planes in Practice
[ParaView]
[IVoR]
Primarily used scientific visualizationand Computer Aided Design (CAD) applications
CS 354 13
Remember Back toclipspace Example
Six user-defined clip planes enabled toclip teapot to left scene’s clip space view
Without user clip planes
CS 354 14
Four-component positions!
Conventional geometry represents 3D points at (x,y,z) positions Affine 3D positions, Cartesian coordinates
Projective position concept Use fourth coordinate: W
So (x,y,z,w) (x/w, y/w, z/w) is the corresponding affine 3D position Known as “homogeneous coordinates”
Advantages Represents perspective cleanly Allows rasterization of external triangles Puts off (expensive) division
CS 354 15
Example, All Identical Positions Affine 3D
(x,y,z)
Projective 3D (x,y,z,w) → (x/w,y/w,z/w)
(2,-5,10) (2,-5,10,1)
(4,-10,20,2)
(1,-2.5,5,0.5)
(-2,5,-10,-1)
CS 354 16
Affine View FrustumClip Equations
The idea of a [-1,+1]3 view frustum cube Regions outside this cube get clipped Regions inside the cube get rasterized
Equations -1 ≤ xc ≤ +1
-1 ≤ yc ≤ +1
-1 ≤ zc ≤ +1
CS 354 17
Projective View FrustumClip Equations
Generalizes clip cube as a projective space Uses (xc,yc,zc,wc) clip-space coordinates
Equations -wc ≤ xc ≤ +wc
-wc ≤ yc ≤ +wc
-wc ≤ zc ≤ +wc
Notice Impossible for wc < 0 to survive clipping
Interpretation: wc is distance in front of the eye So negative wc values are “behind your head”
CS 354 18
glVertex3f Generalized
glVertex3f(x,y,z) Provides (x,y,z) affine position Implicit w of 1 supplied
Alternatively glVertex4f(x,y,z,w) Provides (x,y,z,w) projective position Value of w is explicit Rarely used in practice but does work
… Also glVertex2f(x,y) Implicit z of 0 and w of 1 supplied
CS 354 19
Vertex Transformation
So far, we’ve specified vertex positions directly in NDC coordinates Simple approach Everything in [-1,+1]3 cube gets drawn
You can now handle the truth OpenGL actually provides a projective transformation
from the glVertex3f parameters to NDC coordinates Expressed as a combination of two 4x4 matrix
transforms on the (x,y,z,w) object-space position Initial value of both matrices are identity
transforms Hence OpenGL initially takes glVertex* positions
directly to NDC space The simple_trianlge example relies on this
CS 354 20
Vertex Transformation
Object-space vertex position transformed by a general linear projective transformation Expressed as a 4x4 matrix
o
o
o
o
c
c
c
c
w
z
y
x
mmmm
mmmm
mmmm
mmmm
w
z
y
x
151173
141062
13951
12840
CS 354 21
Matrix Multiplication
v’ = M v Where M is a matrix and v is a vector Use: coordinate system changes
v = M-1 v’ Inverse matrix multiplication Uses: back projection, plane equation setup
CS 354 22
Two Transforms in Sequence
OpenGL thinks of the projective transform as really two matrix transforms
o
o
o
o
e
e
e
e
w
z
y
x
MVMVMVMV
MVMVMVMV
MVMVMVMV
MVMVMVMV
w
z
y
x
151173
141062
13951
12840
e
e
e
e
c
c
c
c
w
z
y
x
PPPP
PPPP
PPPP
PPPP
w
z
y
x
151173
141062
13951
12840
FIRSTobject-space
toeye-space
SECONDeye-space
toclip-space
16 Multiply-Addoperations
Another16 Multiply-Addoperations
CS 354 23
Modelview-Projection Transform
Matrixes can associate (combine) Combination of the modelview and projection
matrix = modelview-projection matrix or often simply the “MVP” matrix
151173
141062
13951
12840
151173
141062
13951
12840
151173
141062
13951
12840
MVMVMVMV
MVMVMVMV
MVMVMVMV
MVMVMVMV
PPPP
PPPP
PPPP
PPPP
MVPMVPMVPMVP
MVPMVPMVPMVP
MVPMVPMVPMVP
MVPMVPMVPMVP
concatenation is64 Multiply-Addoperations, done by OpenGL driver
Matrix multiplicationis associative (but not commutative)
A(BC) = (AB)C, but ABC≠CBA
CS 354 24
Setting the Modelview and Projection Matrices
Easy way glLoadMatrixf(const GLfloat *matrix)
matrix is 4x4 array of floats Warning: stored in column-major order
So like FORTRAN, not C
Replaces the current matrix with the new matrix
Which matrix is replaced? Could be modelview or projection matrix? Depends on last call to glMatrixMode
glMatrixMode(GL_MODELVIEW) glMatrixMode(GL_PROJECTION)
CS 354 25
Careful: Beware of Selectors
Danger: glMatrixMode is error-prone If you forget the state of glMatrixMode, you can easily
update the wrong matrix Leads to very frustrating bugs Problem is glMatrixMode sets a selector which
changes which state “other” matrix commands update
The better API would have the matrix mode as a parameter to matrix commands, instead of a selector
New EXT_direct_state_access extension has a “direct” command for setting matrix state glMatrixLoadfEXT(GL_MODELVIEW, matrix) glMatrixLoadfEXT(GL_PROJECTION, matrix)
CS 354 26
Many Matrix Manipulation Commands
glLoadIdentity() Resets matrix to identity matrix Restores initial setting
glMultMatrixf(const GLfloat *m) Multiplies current matrix by
specified 4x4 matrix glTranslatef(x,y,z)
Applies 3D translation to the current matrix
glScalef(xs,ys,zs) Applies 3D (non-uniform) scaling
to the current matrix glRotatef(angle,x,y,z)
Applies rotation around a 3D axis to the current matrix
glPushMatrix() Pushes current matrix to the matrix
state Matrix now can be modified and
later popped back glPopMatrix()
The way to pop back to the prior matrix
Push and pop is good for hierarchical modeling
glOrtho(left, right, bottom, top, near, far) Multiplies current matrix by a 3D
orthographic “box” Maps a box to the NDC
[-1,+1]3 cube glFrustum(left, right, bottom, top,
near, far) Multiplies current matrix by a 3D
perspective frustum Maps a camera view to the NDC
[-1,+1]3 cube
OpenGL API conventionf-suffixed means takes single-precision float parametersd-suffixed means takes double-precision parametersExamples: glTranslated, glScaled, glRotated
CS 354 27
EXT_direct_state_accessVersions of Matrix Commands
Conventional Command
Selector-freeDSA Command
glLoadMatrixf glMatrixLoadfEXT
glLoadTransposeMatrixf glMatrixLoadTransposefEXT
glMultMatrixf glMatrixMultfEXT
glMultTransposeMatrixf glMatrixMultTransposefEXT
glLoadIdentity glMatrixLoadIdentityEXT
glRotatef glMatrixRotatefEXT
glScalef glMatrixScalefEXT
glTranslatef glMatrixTranslatefEXT
glOrthof glMatrixOrthoEXT
glFrustumf glMatrixFrustumEXT
glPushMatrix glMatrixPushEXT
glPopMatrix glMatrixPopEXT
ConvetionsAll f-suffixed entrypoints have d-suffixedversions for doubleprecision too
All selector-freeroutines take aGLenum matrix modeparameter, sameas glMatrixMode
CS 354 28
Scale, Rotate, andTranslate Example
Add matrix codeglShadeModel(GL_SMOOTH); // smooth color interpolationglEnable(GL_DEPTH_TEST); // enable hidden surface removal
glMatrixMode(GL_MODELVIEW);glLoadIdentity(); // reset to null transformglScalef(0.7, 0.4, 1.0); // scale by 70% in X and 40% in Y (and 100% in Z)glRotatef(30, 0, 0, 1); // rotate in XY plane (around Z axis) 30 degreesglTranslatef(-0.1, 0.3, 0.1);// shift -0.1 to the left and 0.3 up (and 0.1 back in Z)
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);glBegin(GL_TRIANGLES); { // every 3 vertexes makes a triangle glColor4ub(255, 0, 0, 255); // RGBA=(1,0,0,100%) glVertex3f(-0.8, 0.8, 0.3); // XYZ=(-8/10,8/10,3/10)
glColor4ub(0, 255, 0, 255); // RGBA=(0,1,0,100%) glVertex3f( 0.8, 0.8, -0.2); // XYZ=(8/10,8/10,-2/10)
glColor4ub(0, 0, 255, 255); // RGBA=(0,0,1,100%) glVertex3f( 0.0, -0.8, -0.2); // XYZ=(0,-8/10,-2/10)} glEnd();
CS 354 29
Load Identity Transform
Prototype glLoadIdentity()
Replace current matrix with this matrix
1000
0100
0010
0001
CS 354 30
Non-uniform Scale Transform
Prototype glScalef(GLfloat xs, GLfloat ys, GLfloat zs)
Post-concatenates this matrix
1000
000
000
000
zs
ys
xs
CS 354 31
Translate Transform
Prototype glTranslatef(GLfloat x, GLfloat y, GLfloat z)
Post-concatenates this matrix
1000
100
010
001
z
y
x
CS 354 32
Rotation Transform
Prototype glRotatef(GLfloat a, // angle in degrees
GLfloat x, GLfloat y, GLfloat z) Post-concatenates a rotation matrix
1000
0cossin0
0sincos0
0001
aa
aa
glRotatef(a,1,0,0)
1000
0cos0sin
0010
0sin0cos
aa
aa
glRotatef(a,0,1,0)
1000
0100
00cossin
00sincos
aa
aa
glRotatef(a,0,0,1)
Axis could be arbitrary un-normalized direction vector
CS 354 33
Orthographic Transform
Prototype glOrthof(GLfloat left, GLfloat right,
GLfloat bottom, GLfloat top, GLfloat near, GLfloat far)
Post-concatenates an orthographic matrix
1000
200
02
0
002
nf
nf
nf
bt
bt
bt
lr
lr
lr
CS 354 34
Frustum Transform
Prototype glFrustumf(GLfloat left, GLfloat right,
GLfloat bottom, GLfloat top, GLfloat near, GLfloat far)
Post-concatenates a frustum matrix
0100
2)(00
02
0
002
nf
fn
nf
nfbt
bt
bt
nlr
lr
lr
n
CS 354 35
Two Transforms Concatenated Multiplying the position by
First by the modelview Then second by the projection …is equivalent to multiplying by their
concatenation so
o
o
o
o
c
c
c
c
w
z
y
x
MVPMVPMVPMVP
MVPMVPMVPMVP
MVPMVPMVPMVP
MVPMVPMVPMVP
w
z
y
x
151173
141062
13951
12840
Just 16 Multiply-Addoperations… even though 2 (combined) transformation matrices!
CS 354 36
Perspective Divide
Divide clip-space (x,y,z) by clip-space w To get Normalized Device Coordinate (NDC) space
Means reciprocal operation is done once And done after clipping Minimizes division by zero concern
c
c
c
c
c
c
n
n
n
wzw
yw
x
z
y
x
CS 354 37
Viewport and Depth Range
Prototypes glViewport(GLint vx, GLint vy, GLsizei vw, GLsizei vh) glDepthRange(GLclampd n, GLclampd f)
Equations Maps NDC space to window space
22
22
22
nfznf
vvy
v
vvx
v
z
y
x
n
hyn
h
wxn
w
w
w
w
CS 354 38
Conceptual Vertex Transformation
glVertex*API
commands
Modelviewmatrix
User-definedclip planes
View-frustumclip planes
to primitiverasterization
object-space coordinates
(xo,yo,zo,wo) eye-space coordinates
(xe,ye,ze,we)
clipped eye-space coordinates
clipped clip-space coordinates Perspective
divisionProjection
matrix
Viewport + Depth Rangetransformation
(xc,yc,zc,wc)
window-spacecoordinates
(xw,yw,zw,1/wc)
normalized device coordinates (NDC)
(xn,yn,zn,1/wc)
clip-spacecoordinates
(xc,yc,zc,wc)
(xe,ye,ze,we)
(xe,ye,ze,we)
CS 354 39
View Frustum Clipping Generalizes Cleanly
Recall moving left vertex so it’s X = -1.8 Result is a clipped triangle
(-1.8, 0.8, 0.3, 1)
(-0.8, 0.8, -0.2,1)
(0, -0.8, -0.2, 1)
origin at (0,0,0,1)
CS 354 40
Clipped Triangle Visualized
Clipped and Rasterized Normally Visualization of NDC space
Notice triangle is “poking out” of the cube;this is the reason that should be clipped
CS 354 41
Break Clipped Triangle intoTwo Triangles
But how do we find these “new” vertices?The edge clipping the triangle is the line at X = -1so we know X = -1 at these points—but what about Y?
CS 354 42
Use Ratios to Interpolate Clipped Positions
(-1.8, 0.8, 0.3, 1)
(-0.8, 0.8, -0.2,1)
(0, -0.8, -0.2)
origin at (0,0,0,1)
X = -1Y = (1.8/2.6)×0.8 + (0.8/2.6)×0.8 = 0.8Z = (1.8/2.6)×0.3 + (0.8/2.6)×-0.2 = 0.1461538W = (1.8/2.6)×1 + (0.8/2.6)×1 = 1
-1-(-1.8)=0.8
0.8-(-1)=1.8
0.8-(-1.8)=2.6(-1,0.8,0.146153,1)
Straightforward becauseall the edges are orthogonal
Weights: 1.8/2.6 0.8/2.6, sum to 1
CS 354 43
Use Ratios to Interpolate Clipped Positions
(-1.8, 0.8, 0.3)
(-0.8, 0.8, -0.2)
(0, -0.8, -0.2)
origin at (0,0,0)
0-(-1.8) = 1.8
0-(-1) = 1
X = -1Y = (1/1.8)×0.8 + (0.8/1.8)×-0.8 = 0.08888… Z = (1/1.8)×0.3 + (0.8/1.8)×-0.2 = 0.07777…
(-1,0.0888,0.0777)
-1-(-1.8) = 0.8
Weights: 1/1.8 0.8/1.8, sum to 1
CS 354 44
Generalize to Non-1 W
Affine clipping plane in example -1 ≤ xc
Generalizes to 1 xc + 0 yc + 0zc + 1 wc ≥ 0
Looks like a plane equation A xc + B yc + C zc + D wc ≥ 0 with coefficients A, B, C, and D
CS 354 45
View Frustum Plane Equations
All six view frustum planes can be described by simple projective plane equations
Name A B C D Plane equation
Left 1 0 0 1 1 xc + 1wc ≥ 0
Right -1 0 0 1 -1 xc + 1wc ≥ 0
Bottom 0 1 0 1 1 yc + 1wc ≥ 0
Top 0 -1 0 1 -1 yc + 1wc ≥ 0
Near 0 0 1 1 1 zc + 1wc ≥ 0
Top 0 0 -1 1 -1 zc + 1wc ≥ 0
CS 354 46
Projective Clipping
Each vertex computes its clip distance w.r.t. a plane Plug vertex’s (x,y,z,w) into Ax+By+Cz+Dw≥0 plane equation…
provides a clip distance For two vertexes forming a triangle edge
Both negative? Discard the edge Both positive? Accept the edge (no clipping) One negative, one positive
Clipping is needed Compute t as s / (s + p) where s and p are clip distances
s is the “inside” distance; p is the “outside” distance Weight all per-vertex attributes based on t Makes new “clipped” vertex on the clip plane Generate 1 triangle if 1 of 3 vertices is inside;
if 2 inside, generate 2 triangles Repeat process (recursively) for all clip planes
Only slightly more complicated than prior clipping algorithm
CS 354 47
Readily Extends toUser-defined Clip Planes
In addition to the six view frustum planes of clip space… OpenGL supports user-defined clip planes Allows slicing into geometry
Operate in eye space instead of clip space Enabled with glEnable(GL_CLIP_PLANE0+num) Plane equation set by glClipPlane
Clip planes are transformed current modelview projection matrix
Plane equation is Axe+Bye+Cze+Wze≥0 Instead of using (xc, yc, zc, wc) as view frustum planes do
CS 354 48
(Clip) Plane Transformation Vertex positions (and direction vectors) are
transformed like column vectors
Plane equations are transformed like row vectors
o
o
o
o
e
e
e
e
w
z
y
x
MVMVMVMV
MVMVMVMV
MVMVMVMV
MVMVMVMV
w
z
y
x
151173
141062
13951
12840
151173
141062
13951
12840
MVMVMVMV
MVMVMVMV
MVMVMVMV
MVMVMVMVwzyx
w
z
y
x clipclipclipclip
e
e
e
e
glClipPlane parameters
glVertex4fparameters
CS 354 49
Conceptual Vertex Transformation
glVertex*API
commands
Modelviewmatrix
User-definedclip planes
View-frustumclip planes
to primitiverasterization
object-space coordinates
(xo,yo,zo,wo) eye-space coordinates
(xe,ye,ze,we)
clipped eye-space coordinates
clipped clip-space coordinates Perspective
divisionProjection
matrix
Viewport + Depth Rangetransformation
(xc,yc,zc,wc)
window-spacecoordinates
(xw,yw,zw,ww)
normalized device coordinates (NDC)
(xn,yn,zn,wn)
clip-spacecoordinates
(xc,yc,zc,wc)
(xe,ye,ze,we)
(xe,ye,ze,we)
CS 354 50
Vertex Shaders in the Pipeline
GeometryProgram
3D Applicationor Game
OpenGL API
GPUFront End
VertexAssembly
VertexShader
Clipping, Setup,and Rasterization
FragmentShader
Texture Fetch
RasterOperations
Framebuffer Access
Memory Interface
CPU – GPU Boundary
OpenGL 3.3
Attribute Fetch
PrimitiveAssembly
Parameter Buffer Readprogrammable
fixed-function
Legend
So far, we’ve discussed “fixed-function” vertex transformationSo far, we’ve discussed “fixed-function” vertex transformation
Modern GPUs make vertex processing Modern GPUs make vertex processing programmableprogrammable
Via vertex shaders!Via vertex shaders!
CS 354 51
Vertex Programmability
Paletted matrixPaletted matrixskinningskinning
Twister vertex programTwister vertex program
Per-vertex Per-vertex cartoon cartoon shadingshading
CS 354 52
Other Vertex Processing Tasks
Per-vertex lighting Given normal vectors at each vertex, view vector, material
parameters, and light parameters, compute the lit appearance of the surface
Texture coordinate generation Texture coordinates help map images (called “textures”) onto
rasterized primitives Often texture coordinates are passed explicitly with each vertex Alternatively, a vertex shader can compute them
Non-linear transformation Animation by blending various matrix transforms Twisting or morphing geometry
Fog computations Arbitrary setup for fragment shaders
CS 354 53
Vertex Shader Example:Key Frame Blending
Frame A Frame BBlended Frame
47%= + 53%
CS 354 54
Key Frame Blending
VertexShader
Frame A
Frame B
Other possible key frames
CS 354 55
Non-linear Vertex Transform + Fragment Shader Setup
2D grid over (s,t)[0,1]Tessellated torus
Fragment program
Vertex program
CS 354 56
Next Lecture
Graphics Math Interpolation, vector math, and number representations for
computer graphics As usual, expect a short quiz on today’s lecture
Know the form of a translate and scale matrix Know the order of operations in transforming a vertex position
Assignments Reading
Chapter 6, 310-322 Next project (Project #1) to be assigned Thursday, February 2
Building a 3D object model loader Due Thursday, February 16 2nd homework is on
class web site,5 pages, 10 problems