Computer Graphics
OPENGL AND SHADER PROGRAMMING
By Amanuel N.
Overview
OpenGL Primitives
Data In OpenGL Buffers
Vertex Specification
OpenGL Drawing Commands
Shader Program
Shader Program and Vertex Attribute Object
Lab 3 – Drawing
OpenGL Primitives
OpenGL draws models by constructing it from basic primitives
There are many primitives, generally categorized to 3 types: Point, Line, Triangle
.
. .
Point
Line Triangle
Primitives - Point
Point is represented by a single vertex having (x, y, z) coordinates.
Point has no area.
Point is drawn by lighting the pixels that the point fall in to
Point has size which determines how big it is when it is drawn. By default it is 1.0 but can be
set using the following method:
Primitives - Line
Lines is represented, in OpenGL, by line segment connecting to vertexes
Line width can be set using the following method, by default 1.0
Primitives - Line
Lines can be connected to create 2 more primitives that are Line type, Line Stripe and Line Loop
. .
. . .
. . .
. . Line Strip
Line Loop
Line
Primitives - Triangle
Triangle is a surface made up 3 vertexes
Triangles can be connected to create to more triangle type primitives: Triangle Fan and Strip
. .
. . . . . . .
. . . . . . . .
Triangle Triangle Fan Triangle Stripe
Data in OpenGL Buffer
Computer Graphics applications need lots of memory and processing power
For that, there should be efficient way of memory management
OpenGL offers a way to load vertex data to memory, accessing those memory for processing
and finally destroying them.
Data in OpenGL Buffer
Buffer is a temporary storage of data that is currently waiting for some processing
OpenGL uses buffers for storing vertex data temporarily so that those vertexes are displayed
and destroyed at any time
Buffers
Creating and allocating buffers
Loading data into and out of buffers
Accessing buffer data
Discarding buffer data
Buffers – Creating and Allocating
There are different types of buffers (vertex array buffer, texture buffer …)
OpenGL allows us to create buffers, load vertex data and finally clear them
Create buffer name (to locate where our memory is)
Allocate memory space (create the actual memory)
vertex buffers are called Vertex Buffer Object (VBO)
GL_BUFFER_ARRAY – for vertex array
GL_ELEMENT_ARRAY_BUFFER – for index of vertexes
GL_TEXTURE_BUFFER – for texture
Buffers – Creating and Allocating
# create buffer name
bufferName = glGenBuffers(1)
# create memory space with that buffer name
glBindBuffer(GL_ARRAY_BUFFER, bufferName)
Buffers – Loading Data
To load vertex data to a buffer we need four things:
target buffer – which is currently bound
the size of the data
the vertex data itself
usage – hint on how is the data going to used
Buffers – Loading Data
To load vertex data to a buffer we need four things:
target buffer # Create vertexes
vertexes = np.array([
the size of the data
[0.5, 0.0, 0.0],
the vertex data itself [-0.5, 0.0, 0.0],
usage – hint on how is the data going to used [0, 0.5, 0.0]],
dtype=np.float32)
# load the vertex data into buffer
glBufferData(GL_ARRAY_BUFFER, vertexes.nbytes, vertexes, GL_STATIC_DRAW)
Buffer – Getting data out of and Discarding
Data
Buffer
Loading data to OpenGL buffer by itself doesn’t tell anything about the vertexes to OpenGL
Vertex has attributes that describe that vertex
Position attribute – (x, y, z)
Color attribute – (r, g, b)
Texture attribute (s, t)
after successfully loading the vertex data, we need to tell OpenGL, which part of the data is
position, color … and their elements
After describing
Before
0.0 0.5 0.7 0.5 0.3 0.7 0.2 0.5 0.7 1.0
Vertex Specification
We must describe the vertex data to OpenGL:
What type of data we loaded on the buffer (integer, float, double…)
the size of the individual attribute in bytes (position, color … and their component – [x, y, z], [RGB])
how many elements in the attributes (position has – 3 - [X, Y, Z])
Vertex Array Pointer Object describes the data and allows shader program to access individual
attributes and their elements
vertexes =
np.array([
[0.0, 0.5, 0.0],
Vertex Specification [-.5, 0.0, 0.0],
[0.5, 0.0, 0.0]
])
Vertex Attribute information is stored on Vertex Array Buffer
We need to generate name for the buffer
Bind it to vertex array buffer
0.0 0.5 0.0 -.5 0.0 0.0 0.5 0.0 0.0
0.0, 0.5, 0.0 -.5, 0.0, 0.0, 0.5, 0.0,
0.0 Vertex 1 Vertex 2 Vertex 3
triangleVAO = glGenVertexArrays(1)
positionLocation = glGetAttribLocation(program, "position")
glBindVertexArray(triangleVAO)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * vertexes.itemsize,
None)
glEnableVertexAttribArray(positionLocation)
Drawing Commands
There are many drawing commands and most of them start with Draw word
glDrawArrays() is the simplest and it needs the following arguments:
Mode – specifies what kind of primitive it should draw
first – specifies which vertex is going to be the first to be drawn
count – specifies how many vertexes to draw
Drawing Commands
There are two kinds of drawing commands, Indexed and nonindexed
glDrawElements() is the nonindexed drawing:
It needs the following arguments:
Mode – specifies what kind of primitive it should draw
Count – specifies how many vertexes to draw
Type – the data type of the indexes
Shader Programs
Shaders are small programs that are written with C or Java Like programming language called
GLSL(Graphics Library Shading Language)
In most of the stages in Graphics Pipeline, shaders are used to execute the operation in those
stages
Shaders are important to computer graphics as the only operation done on the drawing with
out shader is Clearing the window
Shader Programs
Like every program, Shaders have basic programming constructs like variables, functions, main
method, data types, conditionals and loops …
Shaders make the graphics pipeline and for that data must pass from a shader to an other
shader through specialized variables
Shader Programs
Shader Programs
Variables and Data Types
Shader Programs – Matrix &
Vector
Shader Program
There are special variable modifiers that allow shaders to exchange data between them and
the graphics application
in modifier specifies a variable that is going to input to a shader
the input could be from vertex attribute or from another preceding shader
out modifier specifies a variable that will be output of a shader program – maybe input for a successor
uniform modifier specifies a variable that allows a shader to communicate with the application
Vertex shader Tessellation Shader Fragment
Shader
In out In out In out
Our Vertexes
Vertex Shader
#version 330 core
layout (location = 0) in vec4 position;
void main()
{
gl_Position = vec4(position.x, position.y, position.z,
1.0);
}
Fragment Shader
#version 330 core
void main()
{
gl_FragColor = vec4(1.0, 0.0, 0.0,
1.0);
}
Shader Program
Shaders may contain built-in variables that are need to be assigned with some value
used to pass data from shader to shader
In vertex shader, position of a vertex must be set, so it contains position variable - gl_position
in fragment shader, color can be set with any variable.
gl_FragColor is available for OpenGL versions less than 3.1
Shader and Vertex Attribute
Basically in shaders, we process the vertexes attributes
Position (X, Y, Z), Color (R, G, B)
we access those attributes if Vertex Attrib Object describes the data in the buffer
Vertexes in the buffer Vertexes in structured format
Must be changed to
0.0 0.5 0.7 0.5 0.3 0.7 0.2 0.5 0.7 1.0
#version 330 core
layout (location = 0) in vec4 position;
void main()
{
gl_Position = vec4(position.x + 1, position.y, position.z,
1.0);
} triangleVAO = glGenVertexArrays(1)
positionLocation = glGetAttribLocation(program, "position")
glBindVertexArray(triangleVAO)
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * vertexes.itemsize, None)
glEnableVertexAttribArray(positionLocation)
0.0 0.5 0.0 -.5 0.0 0.0 0.5 0.0 0.0
Vertex 1 Vertex 2 Vertex 3
Vertex Describing
vertexes =
np.array([ Buffer loading
0.0, 0.5, 0.0 -.5, 0.0, 0.0, 0.5, 0.0,
[0.0, 0.5, 0.0],
[-.5, 0.0, 0.0], 0.0
[0.5, 0.0, 0.0]
])
Lab 3 – Drawing Shapes