程序代写代做代考 scheme PowerPoint Presentation

PowerPoint Presentation

Circle Modeling

Computer Graphics
Instructor: Sungkil Lee

More on State Setup

3

Vertex Ordering for a Triangle

• In general, triangles are not double-sided.

• Hence, we need to set the direction of a triangle face.

• In OpenGL, we use the order of vertices to distinguish front-facing vs.
back-facing triangles.

• Counter-clockwise encirclement of outward-pointing normal.

• The order {v1, v2, v7} and {v2, v7, v1} (front-facing) define the same
polygon with the same face direction, but the order {v1, v7, v2} (back-
facing) is different.

v1

v2

v7

4

Back-Face Culling

• By default, OpenGL will render back-facing triangles as well
as front-facing triangles.

• You need to explicitly command not to render back-facing triangles.

• This mechanism is called the back-face culling.

• You can query the current state of the face culling as follows.

glEnable( GL_CULL_FACE ); // enable face culling
glCullFace( GL_BACK ); // cull back faces
glFrontFace( GL_CCW ); // counterclockwise encirclement determine

// the direction of a face.

glIsEnabled( GL_CULL_FACE );

5

Wireframe mode rendering

• Wireframe mode (desktop only):

• To see how triangles are organized, we can turn on the wireframe mode.

• Set glPolygonMode as GL_LINE for wireframe mode or GL_FILL for solid
mode.

• You can change the line width using glLineWidth().

void keyboard( GLFWwindow* window, int key, int scancode, int action, int mods )
{


else if(key==GLFW_KEY_W)
{

bWireframe = !bWireframe;
glPolygonMode( GL_FRONT_AND_BACK, bWireframe ? GL_LINE:GL_FILL );
printf( “> using %s mode\n”, bWireframe ? “wireframe” : “solid” );

}

}

Definition of Geometry

7

Where you make a geometry in your code

• It actually does not matter.

• as long as OpenGL stuffs are initialized.

• However, it is clean and easy to do it in user_init().

• This is because we usually create geometric objects only once.

// user_init() is usually called after basics GL stuffs are initialized
void user_init()
{

… // create objects here …
}

8

Circle Definition

• Polygonal approximation of a circle

• Modern OpenGL supports only triangles as polygonal primitives.

• Implicit curves, such as a circle, are not supported.

• Hence, we need to approximate a circle using a finite set of triangles.

• As we increase the number of triangles, the shape becomes close to circle.

An octagonal approximation of a circle

9

Circle Definition

• Definition of vertex indices of vertices

• Polar coordinates of vertices

• k-th boundary vertex of N-gon of a radius one has the following polar
coordinates:

(𝑥, 𝑦) = ( cos
2𝜋

𝑁
× 𝑘, sin

2𝜋

𝑁
× 𝑘 )

2

1/9

3

4

5

6 8

7

0

10

Circle Definition

• Define arrays for vertices

• Be sure that the positions here are defined in LHS form of the canonical
view volume; z-axis goes farther from the eye.

• Actually, this circle is defined in 3D (z=0), but its normal vectors are (0,0,-1).

• When you model 3D objects, pay more attention to the z axis.

std::vector vertex_list;
void update_circle_vertices( uint N )
{

vertex_list.clear();
// define the position of four corner vertices
vertex_list.push_back( { vec3(0,0,0), vec3(0.0f,0.0f,-1.0f), vec2(0.5f)} ); // the origin
for( uint k=0; k <= N; k++ ) { float t = PI*2.0f/float(N)*float(k); float c=cos(t), s=sin(t); vertex_list.push_back ({ vec3(c,s,0.0f), // vertex position vec3(0.0f,0.0f,-1.0f), // normal vector facing your eye vec2(c*0.5f+0.5f,s*0.5f+0.5f) // texture coordinate in ([0,1], [0,1]) }); } } 11 Two Ways of Object Specification • Simple vertex buffering • Vertex buffer only • Not using indices (i.e., topology is not separated). • Index buffering: vertex buffer + index buffer • Topology is separated from geometry by indexing scheme. • In typical scenarios, the index buffering is faster than the vertex buffering. This is because index buffering performs less vertex processing and the vertex-only buffering has redundant/duplicate vertices in its definition. Simple Vertex-Only Buffering 13 Simple Vertex Buffering • For an N-gon, we need N×3 vertices. • Pay attention to make out-facing triangles (counter-clockwise orders) void update_vertex_buffer( uint N ) { ... std::vector triangle_vertices;
for( uint k=0; k < N; k++ ) { triangle_vertices.push_back(vertex_list.front()); // the origin triangle_vertices.push_back(vertex_list[k+1]); triangle_vertices.push_back(vertex_list[k+2]); } // generation of vertex buffer: use triangle_vertices instead of vertex_list glGenBuffers( 1, &vertex_buffer ); glBindBuffer( GL_ARRAY_BUFFER, vertex_buffer ); glBufferData( GL_ARRAY_BUFFER, sizeof(vertex)*triangle_vertices.size(), &triangle_vertices[0], GL_STATIC_DRAW); } 14 Simple Vertex Buffering • render() • Render N×3 vertices instead of 3 vertices in the hello example. void render() { ... // render vertices: trigger shader programs to process vertex data glDrawArrays( GL_TRIANGLES, 0, NUM_TESS*3 ); // NUM_TESS = N ... } Index Buffering 16 Index Buffering • Index definition • We only indicate the topology for indices. • Index buffer will indicate topology of vertices. • Use the vertex buffer array as it is. • We use N×3 indices unlike the simple vertex buffering with N×3 vertices. void update_vertex_buffer( uint N ) { ... index_list.clear(); for( uint k=0; k < N; k++ ) { index_list.push_back(0); // the origin index_list.push_back(k+1); index_list.push_back(k+2); } } 17 Index Buffering • Vertex/index buffer definition • We need two buffers, vertex buffer and index buffer, simultaneously. • The index buffer uses GL_ELEMENT_ARRAY_BUFFER as a buffer type. • Vertex buffer will use the initial vertices directly (without connectivity). void update_vertex_buffer( uint N ) { ... // generation of vertex buffer: use vertex_list as it is glGenBuffers( 1, &vertex_buffer ); glBindBuffer( GL_ARRAY_BUFFER, vertex_buffer ); glBufferData( GL_ARRAY_BUFFER, sizeof(vertex)*vertex_list.size(), &vertex_list[0], GL_STATIC_DRAW); // geneation of index buffer glGenBuffers( 1, &index_buffer ); glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, index_buffer ); glBufferData( GL_ELEMENT_ARRAY_BUFFER, sizeof(uint)*index_list.size(), &index_list[0], GL_STATIC_DRAW ); } 18 Index Buffering • render() • The setup for vertex buffer is the same. • That means that binding of the vertex buffer is still necessary. • Now, we need to the index buffer object, too. • Render N×3 indices instead of N×3 vertices in the simple vertex buffering. • Use glDrawElements() instead of glDrawArrays() to use the index buffering. void render() { ... glBindBuffer( GL_ELEMENT_ARRAY_BUFFER, index_buffer ); glDrawElements( GL_TRIANGLES, index_list.size(), GL_UNSIGNED_INT, nullptr ); ... } 19 Your vertex shader • One last stuff to do is the correction of the aspect ratio. • Since we specify the vertex position in the default viewing volume, the resulting shape in the horizontally/vertically wider screen will be distorted. • Pass aspect_ratio = width/height to your shader as a uniform variable. • In your shader, modify vertex positions as: • Later, we will see how to apply this in general cases using projection matrix. ... uniform float aspect_ratio; // correct a distortion of the shape void main() { gl_Position = model_matrix * vec4( position*radius, 1 ); gl_Position.xy *= aspect_ratio>1 ? vec2(1/aspect_ratio,1) : vec2(1,aspect_ratio);

}

20

Your fragment shader

• Nearly the same as the hello example.

• Additionally, we visualize texture coordinates as color output.

// inputs from vertex shader
in vec2 tc; // used for texture coordinate visualization

void main()
{

fragColor = bUseSolidColor ? solid_color : vec4(tc.xy,0,1);
}

21

Results

• Octagonal approximation

• Color indicates the texture coordinates.

22

Results

• 64-gon approximation

• Now, it looks like a circle.

23

Results

• Wireframe-mode rendering (not supported in OpenGL ES)

• Now, you can see the triangular structure.