Modeling - Purdue University

OpenGL Buffers
CGT520
Modeling
Bedrich Benes, Ph.D.
Purdue University
Department of Computer Graphics
frame buffer
consists of pixel (RGB values)
alpha buffer
pixel’s transparency 0-opaque,255-transparent
© Bedrich Benes
OpenGL Buffers
z-buffer (depth)
z is the distance of a pixel from the viewer
z-test is used for visibility
stencil buffer
controls special writing operations
• Some values are set explicitly by the user
• Some are set by rendering
© Bedrich Benes
OpenGL Buffers
Clearing a buffer
1) specify the value
2) clear the buffer
© Bedrich Benes
Specifying the Clear Value
Clearing the Buffer
glClearColor(GLclampf r,GLclampf g,
GLclampf b,GLclampf a)
void glClear(GLbitfield mask)
glClearDepth(GLclampd d)
glClearStencil(GLint s)
• mask is a logical OR
color
GL_COLOR_BUFFER_BIT
depth
GL_DEPTH_BUFFER_BIT
stencil
GL_STENCIL_BUFFER_BIT
• typically:
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
© Bedrich Benes
© Bedrich Benes
Forcing Completion of Drawing
Vertex Array and Vertex Buffer
•
due to optimizations some command may be stuck
•
there are two “chimney-sweeper” commands
• OpenGL uses a concept of buffers
void glFlush()
void glFinish()
the glFlush() command forces OpenGL to finish all previously
executed commands in finite time
• So called vertex-array object
is a GPU-oriented data structure that
allows multiple vertex-buffers to be
associated with it
the glFinish() command forces the OpenGL to finish all previously
executed commands and waits for the result
if you think of CPU and OpenGL as a parallel processes
what kind of synchronization task is it?
© Bedrich Benes
© Bedrich Benes
Vertex Array and Vertex Buffer
Vertex Array
• The data is created on the CPU
GLuint vaID;
• The data is bound to the GPU
//allocate single VA
glGenVertexArrays(1,&vaID);
• The data is rendered
//bind it
glBindVertexArray(va);
© Bedrich Benes
Vertex Buffer
GLuint buf;
glGenBuffers(1, &buf);
glBindBuffer(GL_ARRAY_BUFFER,buf);
glBufferData(GL_ARRAY_BUFFER,
size,v,GL_STATIC_DRAW);
glVertexAttribPointer((GLuint)0,
3,GL_FLOAT,GL_FALSE,0,0);
glEnableVertexAttribArray(0);
© Bedrich Benes
© Bedrich Benes
Data Definition
const int points=128;
GLfloat* v=new float[3*points];
© Bedrich Benes
Creating a Circle
GLuint i=0;
GLfloat d=2*M_PI/steps;
for (GLfloat a=0;a<=2*M_PI;a+=d){
a[i++]=sin(a);
a[i++]=cos(a);
a[i++]=0;}
Rendering
OpenGL primitives
glDrawArrays(GL_POINTS,0,points);
Unit circle
© Bedrich Benes
© Bedrich Benes
OpenGL Primitives
points
GL_POINTS
lines
GL_LINES
polylines
GL_LINE_STRIP
closed polylines
GL_LINE_LOOP
triangles
GL_TRIANGLES
triangle strips
GL_TRIANGLE_STRIP
triangle fans
GL_TRIANGLE_FAN
© Bedrich Benes
OpenGL Primitives
GL_LINE_STRIP_ADJACENCY,
GL_LINES_ADJACENCY,
GL_TRIANGLE_STRIP_ADJACENCY,
GL_TRIANGLES_ADJACENCY
GL_PATCHES
© Bedrich Benes
OpenGL Primitives
Lines in OpenGL
2
• Note:
3
5
GL_LINES
6
4
• GL_QUADS
• GL_QUAD_STRIP
• GL_POLYGON
1
2
3
5
GL_LINE_STRIP
6
4
1
are deprecated!
2
3
5
GL_LINE_LOOP
6
© Bedrich Benes
4
© Bedrich Benes
1
Triangles
Triangle Strips
6
4
GL_TRIANGLES
2
• less than three vertices per !
5
1
3
6
4
• an ordered vertex list
2
GL_TRIANGLE_STRIP
• the i-th triangle 
5
1
3
3
4
1
5
1
1
triangles
• average # of vertices per triangle
1
© Bedrich Benes
0
• the vertex list includes
2
GL_TRIANGLE_LOOP
• a sequential triangle strip is defined by
© Bedrich Benes
Triangle Strips
Triangle Strips vs. Triangle Fans
• average # of vertices per triangle
• the same stands for triangle fans
• where
• some providers (NVIDA) suggest
using strips
is the length of the list
→
• imagine
,
• we save
of space
(wow!)
© Bedrich Benes
• they are better optimized
© Bedrich Benes
Generalized Triangle Strips
Triangle Fans
• the sequence of  is not strictly
sequential
• a general convex polygon can be
converted into a single  fan or a
simple  strip
• to use them, we need a vertex cache or
the swap operation
• The vertex must be
resend
© Bedrich Benes
is the same as for  strips
(the same startup)
• any  fan can be converted into
generalized  strip (repeat the center or
many swaps), but not vice versa
© Bedrich Benes
Some Attributes
OpenGL Back Face Culling
glPointSize(GLfloat size)
• each polygon has two sides
the front face and the back face
glLineWidth(GLfloat width)
• back face culling means discarding back
faces before rasterization
• default OpenGL value:
both faces are rendered - time
consuming!
© Bedrich Benes
© Bedrich Benes
OpenGL Back Face Culling
OpenGL Back Face Culling
• front face has the projected vertices on
the screen in the counterclockwise order
what is culled can be set by
void glCullFace(GLenum mode);
where
mode is GL_FRONT or GL_BACK or
GL_FRONT_AND_BACK
the face culling is set by
glEnable(GL_CULL_FACE);
glDisable(GL_CULL_FACE);
© Bedrich Benes
© Bedrich Benes
OpenGL Face Rendering
OpenGL Face Rendering
Front and Back faces can be rendered in
different modes
• determining the drawing mode of a face
void glPolygonMode(GLenum face, GLenum mode)
face =GL_FRONT|GL_BACK|GL_FRONT_AND_BACK
mode=GL_POINT |GL_LINE | GL_FILL
default:
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)
© Bedrich Benes
GL_POINT
GL_LINE
GL_FILL
© Bedrich Benes
OpenGL Face Orientation
OpenGL Face Orientation
How can we change the face orientation?
• Triangle strip has orientation defined by
the first triangle
• change vertex order

• change polygon mode 
void glFrontFace(GLenum mode)
mode is GL_CCW (counterclockwise)
or GL_CW (clockwise)
© Bedrich Benes
© Bedrich Benes
Modeling a Cube
Modeling a Cube
H
#define A {-0.5,-0.5,-0.5}
#define B {+0.5,-0.5,-0.5} E
#define C {+0.5, +0.5,-0.5}
G
F
…
D
C
vector <GLfloat> v;
v.push_back(A[0]);
v.push_back(A[1]);
…
A
• Using STL vector:
glBufferData(GL_ARRAY_BUFFER,
v.size()*sizeof(GLfloat),&v[0],
GL_STATIC_DRAW);
B
glDrawArrays(GL_TRIANGLES,0,12);
© Bedrich Benes
Considerations
© Bedrich Benes
Tessellation
• Keep a list of smallest versatile elements
• Usually the best is a list of triangle strips
• Avoid T-vertices!
• They can crack when transformed
• They cause bad illumination artifacts
© Bedrich Benes
Tessellation is a process of converting a
complex object into simpler primitives such as
triangles or quadrilaterals
Tessellation is the most frequently
wrongly spelled word in Computer Graphics
© Bedrich Benes
Sphere Tessellation (approach 1)
Sphere Tessellation (approach 1)
Stacks and Slices:
Parametric equation of sphere
• not a very good approach:
• generates very different
=
• generates long
• involves
and
© Bedrich Benes
© Bedrich Benes
Sphere Tessellation (approach 1)
Sphere Tessellation (approach 1)
• Leads to a tessellation:
,
Δ ,
mΔ
Δ
2Δ ,
• Implementation:
Δ ,
Δ
Δ
…
…
…
,
Δ
Δ ,
Δ
2Δ ,
Δ
Δ ,
…
,
© Bedrich Benes
Δ ,
2Δ ,
Δ
Vect3d v;
Glfloat deltaTheta=2*M_PI/(GLfloat)slices;
GLfloat deltaPhi = M_PI/(GLfloat)stacks;
for (GLuint i=0;i<stacks;i++){
GLfloat phi=i*deltaPhi;
for (GLuint j=0;j<slices;j++){
GLfloat theta=j*deltaTheta;
Δ ,
© Bedrich Benes
Sphere Tessellation (approach 1)
Sphere Tessellation (approach 1)
//the first triangle
//the second triangle
v.Set(r*cos(theta)*sin(phi),
r*sin(theta)*sin(phi),
r*cos(phi));
v.Set(r*cos(theta+deltaTheta)*sin(phi),
r*sin(theta+deltaTheta)*sin(phi),
r*cos(phi));
v.Set(r*cos(theta)*sin(phi+deltaPhi),
r*sin(theta)*sin(phi+deltaPhi),
r*cos(phi+deltaPhi));
v.Set(r*cos(theta+deltaTheta)*sin(phi),
r*sin(theta+deltaTheta)*sin(phi),
r*cos(phi));
v.Set(r*cos(theta+deltaTheta)*sin(phi+deltaPhi),
r*sin(theta+deltaTheta)*sin(phi+deltaPhi),
r*cos(phi+deltaPhi));
v.Set(r*cos(theta+deltaTheta)*sin(phi+deltaPhi),
r*sin(theta+deltaTheta)*sin(phi+deltaPhi),
r*cos(phi+deltaPhi));
}
© Bedrich Benes
Sphere Tessellation (approach 1)
© Bedrich Benes
Sphere Tessellation (approach 1)
• Results:
• Summary:
•
•
•
•
© Bedrich Benes
© Bedrich Benes
Very simple to implement
Very simple to control (
Not very efficient – large and ugly triangles
Uses trigonometric functions (can be slow)
Sphere Tessellation (approach 2)
Circle Tessellation (approach 2)
Recursive subdivision
• Subdivision
much better approach
Two vertices on
the unit circle
Find the midpoint
Move it on
the unit circle
Let’s do it for a circle first:
Do it for all line segments
© Bedrich Benes
© Bedrich Benes
Circle Tessellation (approach 2)
Circle Tessellation (approach 2)
• All vertices have unit dist. from the origin
• Algorithm:
Subdivide(Vert3d , Vert3d , GLuint )
Input: Vertices , , number of steps
Output:
2 vertices on the circle
1) if (n==0) return and 2) find
© Bedrich Benes
3) Normalize(
); //this will put it on the unit circle
4) Subdivide(a, mid, n-1);
5) Subdivide(mid, b, n-1);
© Bedrich Benes
Circle Tessellation (approach 2)
Sphere Tessellation (approach 2)
• Considerations:
Now this generalizes to the sphere
• The input vertices must already be
on the unit circle
• It needs to be rendered using GL_LINES
as the algorithm does not provide a
continuous polyline
© Bedrich Benes
© Bedrich Benes
Sphere Tessellation (approach 2)
Sphere Tessellation (approach 2)
Implementation:
top
Each sub-triangle has
vertices as given here
© Bedrich Benes
mid
left
right
void Subdivide(CTriangle *t, int n){
if (n==0){OutputTriangle();return;}
Vect3d v12, v23, v31;
v12=(t‐>v1+t‐>v2)/2.f;v12.Normalize();
v23=(t‐>v2+t‐>v3)/2.f;v23.Normalize();
v31=(t‐>v3+t‐>v1)/2.f;v31.Normalize();
© Bedrich Benes
Sphere Tessellation (approach 2)
top=new CTriangle(v31,v23,v‐>v3);
Subdivide(a, top, n‐1);delete top;
mid=new CTriangle(v12,v23,v31);
Subdivide(a, mid, n‐1); delete mid;
left=new CTriangle(t‐>v1,v12,v31);
Subdivide(a, left, n‐1); delete left;
right=new Ctriangle(v12,t‐>v2,v23);
Subdivide(a, right, n‐1);
delete right;
Sphere Tessellation (approach 2)
• Initial position of the triangles:
two tetrahedra
• Top view:
120
120
}
© Bedrich Benes
Sphere Tessellation (approach 2)
© Bedrich Benes
Cone Tessellation
Circle to point ruled surface
• make tessallation of a circle and connect
each line with the apex
• can be rendered as a triangle fan
© Bedrich Benes
© Bedrich Benes
Cone Tessellation
Cone Tessellation
• Implementation:
AddVertex(a,Vect3d(0,1,0)); //apex of the cone
GLfloat delta=2.f*M_PI/(n‐1);
for (int i=0;i<=n;i++)
AddVertex(a,Vect3d(cos(delta*i),0,sin(delta*i)));
• Rendering:
glDrawArrays(GL_TRIANGLE_FAN, 0, points);
© Bedrich Benes
© Bedrich Benes
Cylinder Tessellation
General Ruled Surface Tessellation
•
•
•
•
• Cylinder is a special case of
ruled surface
and
• Defined by two curves
• Assuming both are parameterized
Two circles
The same stride
Two triangles
One triangle strip
• The resulting surface is
© Bedrich Benes
• Note, the connecting curves
are line segments
© Bedrich Benes
General Ruled Surface Tessellation
• Example (sin to line):
General Ruled Surface Tessellation
• Example (sin to line)
Gives
© Bedrich Benes
General Ruled Surface Tessellation
• Implementation:
If all is nicely overloaded, can be simple…
Vect3d P(GLfloat t){return Vect3d(t,0,0);}
Vect3d Q(GLfloat t)
{return Vect3d(t,sin(2*M_PI*t),1);}
Vect3d S(GLfloat u, GLfloat t)
{return Vect3d(u*P(t)+(1‐u)*Q(t));}
© Bedrich Benes
© Bedrich Benes
General Ruled Surface Tessellation
• Implementation (tessellation)
It is the same as stacked and sliced sphere:
GLfloat step=1.f/n;
for (int i=0;i<n;i++){
for (int j=0;j<n;j++){//lower triangle
AddVertex(a,S(i*step,j*step));
AddVertex(a,S((i+1)*step,j*step));
AddVertex(a,S((i+1)*step,(j+1)*step));
//upper triangle similarly
}
}
© Bedrich Benes
General Ruled Surface Tessellation
•
•
•
•
•
and
can be anything
Two lines
quadrilateral
Circle and circle
cylinder
Circle and point
cone
Quad and quad
cube
etc.
© Bedrich Benes
General Ruled Surface Tessellation
• Can we generalize the connecting curve?
© Bedrich Benes
Surface of Revolution
Surface of Revolution
• Surface of revolution is given by a curve
rotated around an axis
• Assuming
• the axis of rotation is
• The defined curve is
• The surface
is a set of co-centric
circles around the axis
(
© Bedrich Benes
© Bedrich Benes
modifies the radius of a circle at level )
Surface of Revolution
Surface of Revolution
• Implementation:
If all is nicely overloaded, can be simple…
GLfloat P(GLfloat u){//def. func returns a number
return 0.2*sin(4*M_PI*u)+1.f;
}
Vect3d S(GLfloat u, GLfloat v){
return Vect3d(P(u)*sin(2*M_PI*v),
u,
P(u)*cos(2*M_PI*v));
}
© Bedrich Benes
Surface of Revolution
•
•
•
•
can be anything
Line parallel to axis of rotation
cylinder
Line from the origin
cone
Half circle
sphere
etc.
© Bedrich Benes
© Bedrich Benes
Surface of Revolution
• Sphere as a surface of revolution
• We need radius of the sphere as the
function of a single parameter
We need to reparametrize
© Bedrich Benes
to be
Surface of Revolution
Reading
GLfloat P(GLfloat u){
u=1‐2*u;//reparametrize to <‐1,1>
return (sqrt(1.f‐u*u));
}
• Jackie Neider, Tom Davis, Mason Woo
OpenGL Programming Guide,
Addison-Wesley Publication Company
• Edward Engel
Interactive Computer Graphics:
A Top-Down Approach with
Shader-Based OpenGL
(6th Edition)
© Bedrich Benes
© Bedrich Benes