15. Elastic Image Software LLC
15
for each object in the scene
! determine its corresponding pixels
! for each corresponding pixel
! ! calculate depth of object at pixel
! ! if depth is closer than any object yet seen
! ! ! put this object in the pixel
! ! endif
! end
end
The GPU implements a z-buffer algorithm in hardware
16. Elastic Image Software LLC
In OpenGL, the Look is evaluated at the same time that
depth comparison is performed.
Together these are the core activities of computer graphics.
They are the raison d'être of the GPU. Compute intensive,
Highly optimized and parallelized.
16
17. Elastic Image Software LLC
17
Update Model State. This could entail geometric
transformation or perhaps taking a time step in
the physic engine.
27. Elastic Image Software LLC
27
Posing models. Positioning light sources.
Aiming the camera. All these task require
and understanding of transformation
matrices.
28. Elastic Image Software LLC
28
Transformation matrix. Coordinate frame
World space, Screen space, etc.
All are different ways of thinking about
the same underlying concept.
29. Elastic Image Software LLC
29
When we move an object we apply a
transformation via a transformation
matrix. This transformation is defined in
terms of a coordinate frame.
A specific location on the transformed
object can be interpreted in terms of any
coordinate frame we choose.
30. Elastic Image Software LLC
30
The motivation for a coordinate frame
transformation is not only motivated by the need
to pose a model or aim a camera as in the
physical world.
In computer graphics land it often has to do with
the convenience of performing a particular
calculation in one space rather then another.
31. Elastic Image Software LLC
31
We refer to the transformation pipeline: the successive
application of a series of transformations as a 3D model wends
its way from application land to GPU land.
32. Elastic Image Software LLC
Hierarchical modeling is based on the hierarchical
organization of transformations matrices. Many objects
- trees, robots, cars - form natural hierarchies.
32
33. Elastic Image Software LLC
33
The UIView class supports all the key concepts
of transformations and hierarchy. It is a nice,
friendly way to gain intuition about facility with
this powerful concept.
41. Elastic Image Software LLC
In what follows, we will be referring to the ES1
“fixed-function” transformation pipeline provided
by the GPU.
In ES2 (GLSL) the transformation pipeline must
be handled entirely in application space.
41
43. Elastic Image Software LLC
43
A camera with a spotlight attached to it orbits
around a stationary teapot model lit by three
stationary colored point light sources.
44. Elastic Image Software LLC
In iOS we never explicitly say “render scene”. Rather we
inform the system that now would be a good time to
redisplay the scene:
[myView setNeedsDisplay] and [myView drawRect]
44
47. Elastic Image Software LLC
! Position the camera
! glMatrixMode(GL_MODELVIEW);!
! glLoadIdentity();
! glLoadMatrixf(_openGLCameraInverseTransform);
47
http://github.com/turner/HelloTeapot/blob/master/Classes/GLViewController.m
48. Elastic Image Software LLC
Position spotlight at camera location
glPushMatrix();
! glMultMatrixf(_cameraTransform);!
!
! // A white spotlight for a camera headlight!
GLfloat spotLightColor[] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat spotLightPosition[] = { 0.0, 0.0, 2.0, 1.0 };
GLfloat spotLightDirection[] = { 0.0, 0.0, -1.0, 1.0 };
GLfloat spotCutOff!! ! = 3.5;
!
! glEnable(GL_LIGHT3);
! glLightfv(GL_LIGHT3, GL_DIFFUSE, spotLightColor);!
! glLightfv(GL_LIGHT3, GL_POSITION, spotLightPosition);
! glLightfv(GL_LIGHT3, GL_SPOT_DIRECTION, spotLightDirection);
! glLightf(GL_LIGHT3, GL_SPOT_CUTOFF, spotCutOff);
!
! glPopMatrix();!
48
http://github.com/turner/HelloTeapot/blob/master/Classes/GLViewController.m
49. Elastic Image Software LLC
49
glPushMatrix & glPopMatrix
These functions push/pop a transformation matrix on/off the
transformation stack.
This stack is the key data structure for presenting a
hierarchical model to the GPU in fixed-function OpenGL.
50. Elastic Image Software LLC
50
glPushMatrix - Create a new matrix and push
it on the stack. Subsequent matrix concatenation
is done with stack.top.
stack.top is the current coordinate frame.
glPopMatrix - Pop the stack. The pre-existing
matrix is now stack.top.
We revert to the coordinate frame the existed
prior to the push.
! glPushMatrix();
! glMultMatrixf(_cameraTransform);
!
! glEnable(GL_LIGHT3);
! glLightfv(GL_LIGHT3, GL_DIFFUSE, spotLight);
! glPopMatrix();!
54. Elastic Image Software LLC
54
http://github.com/turner/HelloTeapot/blob/master/Classes/GLViewController.m
Position and draw the teapot
! glPushMatrix();
! JLMMatrix3DSetZRotationUsingDegrees(rotation, -45.0f);
! JLMMatrix3DSetScaling(scale, sx, sy, sz);
! JLMMatrix3DMultiply(rotation, scale, concatenation);
! glMultMatrixf(concatenation);
! for(int i = 0; i < num_teapot_indices; i += new_teapot_indicies[i] + 1) {
! ! glDrawElements(
GL_TRIANGLE_STRIP, indices[i],
GL_UNSIGNED_SHORT, &indices[i+1]
);
! } // for (num_teapot_indices)
! glPopMatrix();
55. Elastic Image Software LLC
55
http://github.com/turner/HelloTeapot/blob/master/Classes/GLViewController.m
Position and draw the teapot
! glPushMatrix();
! JLMMatrix3DSetZRotationUsingDegrees(rotation, -45.0f);
! JLMMatrix3DSetScaling(scale, sx, sy, sz);
! JLMMatrix3DMultiply(rotation, scale, concatenation);
! glMultMatrixf(concatenation);
! for(int i = 0; i < num_teapot_indices; i += new_teapot_indicies[i] + 1) {
! ! glDrawElements(
GL_TRIANGLE_STRIP, indices[i],
GL_UNSIGNED_SHORT, &indices[i+1]
);
! } // for (num_teapot_indices)
! glPopMatrix();
56. Elastic Image Software LLC
56
http://github.com/turner/HelloTeapot/blob/master/Classes/GLViewController.m
Position and draw the teapot
! glPushMatrix();
! JLMMatrix3DSetZRotationUsingDegrees(rotation, -45.0f);
! JLMMatrix3DSetScaling(scale, sx, sy, sz);
! JLMMatrix3DMultiply(rotation, scale, concatenation);
! glMultMatrixf(concatenation);
! for(int i = 0; i < num_teapot_indices; i += new_teapot_indicies[i] + 1) {
! ! glDrawElements(
GL_TRIANGLE_STRIP, indices[i],
GL_UNSIGNED_SHORT, &indices[i+1]
);
! } // for (num_teapot_indices)
! glPopMatrix();
57. Elastic Image Software LLC
57
Notice the absence of GL_CAMERA?
You may be surprised to learn there is no concept of
camera in OpenGL. Camera posing is equivalent to
inverting the camera transform and applying it to the
scene observed by the camera.
63. Elastic Image Software LLC
The vertices comprising the 3D geometry of the teapot
float teapot_vertices [] = {
0.0663, 0.1178, 0.0,
0.0672, 0.1152, 0.0,
0.0639, 0.1178, 0.0178043,
...
};
The surface normals associated with each vertex
// The list of surface normals corresponding to the vertices
float teapot_normals[] = {
-0.987635, -0.156768, 0,
-0.902861, -0.429933, 0,
-0.953562, -0.156989, -0.257047,
...
};
63
64. Elastic Image Software LLC
The teapot model is defined as a collection of triangle stripes
that combine to form the teapot surface.
short indicies[] = {
// how many vertices in vertex strip
26,
// vertex strip indices
1122, 1243, 1272, 1242, ... ,1283, 1199,
...
};
64
67. Elastic Image Software LLC
67
We now begin leaving behind the fixed-
function pipeline of ES1 and focus on
ES2, GLSL, and visual coolness in
general.
68. Elastic Image Software LLC
The Look: the lighting, illumination model,
and surface shaders that in combination
achieve the desired look of a model in a
scene.
68
76. Elastic Image Software LLC
Surface shaders were introduced to the field of computer graphics
by Pixar with its rendering API and shading language called
RenderMan.
A shader is a small functions evaluated at every location on a
being rendered.
GLSL borrows heavily from the RenderMan model.
76
82. Elastic Image Software LLC
82
Before we dive into shaders lets get a lay of the land. There are two
flavors of shaders in GLSL.
A vertex shader is evaluated at each vertex.
A fragment shader is evaluated at each screen space pixel
corresponding to a sampled on the facet being rasterized.
83. Elastic Image Software LLC
83
Vertex and fragment shaders work together in a pipeline fashion. Vertex
attributes - color, surface normal, texture coordinate - are evaluated in
the vertex shader then passed on to the fragment shader where those
values are interpolated across the surface.
84. Elastic Image Software LLC
84
ShowST. A shader that visualizes the texture
coordinate parameterization of a surface.
89. Elastic Image Software LLC
89
http://github.com/turner/HelloiPadGLSL/blob/master/Shaders/ShowST.fsh
// ShowST.fsh
varying vec2 v_st;
void main() {
// Visualize the s-t parameterization of the underlying surface
gl_FragColor.r = v_st.s;
gl_FragColor.g = v_st.t;
gl_FragColor.b = 0.0;
gl_FragColor.a = 1.0;
}
The texture coordinate values v_st.s and v_st.t
are for the red and green channels of the shader color.
90. Elastic Image Software LLC
90
TexturePairShader. A shader that mixes the
colors of a pair of textures using the tweaked
alpha channel of one of the pair.
Fail Whale over Mandril
94. Elastic Image Software LLC
94
attribute vec2 myVertexST - Vertex attribute
varying vec2 v_st - Varies across the surface
uniform sampler2D myTexture_0 - Invariant throughout rendering cycle
Shader variables come in different flavors
95. Elastic Image Software LLC
95
An application communicates with its shaders in the follow ways:
• attributes - geometry, color, normal, texture coordinate
• uniforms - texture sampler, matrix, eye vector, light vector
• textures - texture channels - r, g, b, a - are not just for color
attribute vec2 myVertexST - Vertex attribute
varying vec2 v_st - Varies across the surface
uniform sampler2D myTexture_0 - Invariant throughout rendering cycle
96. Elastic Image Software LLC
96
Lets look at how we wire our iOS app together
with our shaders. We will use a texture shading
example.
https://github.com/turner/HelloShader/blob/master/HelloShader/Classes/Renderer/GLRenderer.m
97. Elastic Image Software LLC
97
First make a texture object ...
TEITexture *t =
[[ [TEITexture alloc] initWithImageFile:@"twitter_fail_whale_red_channnel_knockout"
extension:@"png"
mipmap:YES ] autorelease];
[glView.renderer.rendererHelper.renderables setObject:t forKey:@"texture_0"];
99. Elastic Image Software LLC
99
Associate shader uniform with application object instance ...
TEITexture *t =
(TEITexture *)[self.rendererHelper.renderables objectForKey:@"texture_0"];
t.location = glGetUniformLocation(m_program, "myTexture_0");
glActiveTexture( GL_TEXTURE0 );
glBindTexture(GL_TEXTURE_2D, t.name);
glUniform1i(t.location, 0);
Activate a texture unit, bind it to a texture object, and assign a number to the
corresponding texture sampler used in the fragment shader
100. Elastic Image Software LLC
100
We now have a linkage between our application texture object and a texture
sampler in our fragment shader. Rock.
104. Elastic Image Software LLC
104
Texture mapping is the fundamental tool for creating visual complexity
105. Elastic Image Software LLC
105
By establishing a mapping between a surface and a texture we can “attach”
the texture to the surface.
The interpretation of the a can go far beyond that of a decal to be applied to
a surface. Bumps, opacity, displacement, and much more can be designed
with a texture.
107. Elastic Image Software LLC
107
Shaders can have it both ways: Compute surface
color (or surface roughness, or opacity) algorithmically
or look it up in a texture. Or a bit of both.
109. Elastic Image Software LLC
• OpenGL is mostly M
• Keep V dumb
• Lots of chatter between M and C
MVC
109
110. Elastic Image Software LLC
110
Lets take a look at how iOS and OpenGL interact. We will us
Hello iPad OpenGL as our guide.
https://github.com/turner/HelloShader
112. Elastic Image Software LLC
112
Rendering frame rate is sync-ed to the screen refresh rate.
The actual rendering is handled via a selector.
- (void)startAnimation {
if (!self.isAnimating) {
self.displayLink =
[NSClassFromString(@"CADisplayLink") displayLinkWithTarget:self
selector:@selector(drawView:)];
[self.displayLink setFrameInterval:animationFrameInterval];
[self.displayLink addToRunLoop:[NSRunLoop currentRunLoop]
forMode:NSDefaultRunLoopMode];
self.animating = YES;
} // if (!self.isAnimating)
}
113. Elastic Image Software LLC
113
// framebuffer
glGenFramebuffers(1, &m_framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
// rgb buffer
glGenRenderbuffers(1, &m_colorbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, m_colorbuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorbuffer);
[m_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:layer];
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &m_backingWidth);
glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_HEIGHT, &m_backingHeight);
// z-buffer
glGenRenderbuffers(1, &m_depthbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, m_depthbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, m_backingWidth, m_backingHeight);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, m_depthbuffer);
A framebuffer object is created. A color and depth buffer
are attached.
114. Elastic Image Software LLC
114
- (void) render {
! !
[EAGLContext setCurrentContext:m_context];
glBindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
// transform, light, shade, etc.
glBindRenderbuffer(GL_RENDERBUFFER, m_colorbuffer);
[m_context presentRenderbuffer:GL_RENDERBUFFER];
}
The render loop. Draw to the colorbuffer then present to
the display. This is the classic “ping pong” between back
buffer and front buffer.