Opengl Tutorials
Opengl Tutorials
Opengl Tutorials
of Contents
1. Introduction
2. OpenGL
i.
ii.
iii.
iv.
v.
vi.
vii.
viii.
3. OpenGL
i. VBO
ii.
iii. 2D
iv. OpenGL
v.
vi. :
vii. :
viii. :
ix. :
x. : Billboard
OpenGL Tutorials
OpenGL http://opengl.zilongshanren.com
License
The content of this project itself is licensed under the Creative Commons Attribution 3.0 license, and the
underlying source code used to format and display that content is licensed under the MIT license.
: https://github.com/cybercser/OpenGL_3_3_Tutorial_Translation
OpenGL
()
()
missjing
cybercser
OpenGL
CJavaLispJavascript
+OpenGL
C++template
Java
OpenGLglBegin()
OpenGLOpenGL 34OpenGLOpenGL 1
2
WindowsLinuxMac
C++
CMake
CMake
Windows
Windows
1. NVIDIAAMDGPU:->
->->->IntelDellHP
4. C:/Users/XYZ/Projects/OpenGLTutorials .
5. CMakeCMakeLists.txt
CMake CMakeVisual Studio
C:/Users/XYZ/Projects/OpenGLTutorials-build-Visual2010-32bits
C:/Users/XYZ/Projects/OpenGLTutorials/build/Visual2010-32bits
1. ConfigureconfigureCMake1
Windows646432\
2. ConfigureGenerateVisual StudioVisual Studio
CMake
3. C:/Users/XYZ/Projects/OpenGL/Tutorials-build-Visual2010-32bitsTutorials.sln
CMakeVSVisual Studio
C:/Users/XYZ/Projects/OpenGLTutorials
1. C:/Users/XYZ/Projects/OpenGLTutorials/playgroundplayground.exe
Visual StudioPlayground
DebuggingWorking DirectoryBrowse
C:/Users/XYZ/Projects/OpenGLTutorials/playgroundPlaygroundChoose as
startup projectF5
Linux
Linux
1.
Ubuntu.
2. cmake make g++ libx11-dev libgl1-mesa-dev
libglu1-mesa-dev libxrandr-dev libxext-dev sudo apt-get install * su && yum install **
3. ~/Projects/OpenGLTutorials/
4. :
cd ~/Projects/OpenGLTutorials/
mkdir build
cd build
cmake ..
1. build/makefile
2. make all
~/Projects/OpenGLTutorials/
3. ~/Projects/OpenGLTutorials/playground./playground
Qt CreatorIDEQt CreatorCMake
QtCreator
1.QtCreatorTools->Options->Compile-&Execute->CMake
2.CMake/usr/bin/cmake
3.File->Open Project tutorials/CMakeLists.txt
4.tutorials
5.-DCMAKE_BUILD_TYPE=Debug
6.tutorials/
7.QtCreatorProjects->Execution parameters->Working Directory
~/opengl-tutorial/tutorial02_red_triangle/
Mac
Mac OSOpenGL 3.3MacOS 10.7 LionGPUMacOpenGL 3.2
3.32.1Windows
Makefiles
1.Mac App StoreXCode
2.CMake.dmg
3. 2.1~/Projects/OpenGLTutorials/ .
4.CMake Applications->CMake
CMakeLists.txtCMake~/Projects/OpenGLTutorials_bin_XCode/
5.ConfigureconfigureCMakeXcode
6.ConfigureGenerateXcodeCMake
7.~/Projects/OpenGLTutorials_bin_XCode/Tutorials.xcodeproj
8.XcodeSchemeRun
RunbugCmd-B
/tutorialX/tutorialX
Code::Blocks
C::BCMakebugProject->Build->Options->Make commands
cd
IDE
tutorialXX/
playground/playground.cpp
playground
OpenGL
GLFW
WindowsWin32 APILinuxX11 APIMacCocoa APISFML
FreeGLUTSDL
GLEW
// Include GLEW. Always include it before gl.h and glfw.h, since it's a bit magic.
#include <GL/glew.h>
GLFW
// Include GLFW
#include <GL/glfw.h>
GLMGLM
using namespaceglm::vec3vec3
// Include GLM
#include <glm/glm.hpp>
using namespace glm;
#includeplayground.cppmain
int main(){
GLFW
// Initialise GLFW
if( !glfwInit() )
{
fprintf( stderr, "Failed to initialize GLFW\n" );
return -1;
}
OpenGL
return -1;
}
glfwSetWindowTitle( "Tutorial 01" );
Esc
OpenGL 3
Visual
Studio
(VAO)
GLuint VertexArrayID;
glGenVertexArrays(1, &VertexArrayID);
glBindVertexArray(VertexArrayID);
OpenGLOpenGL
VAO
pointVertex
XYZ
X Y Z
X Y Z
Z
100Z
XYZ
(-1, -1, 0)
(-1, -1)
XY
OpenGL
Shader
Fragment4
GLSL(GL Shader LanguageGL)OpenGLCJava
GLSL
SimpleFragmentShader.fragmentshader
SimpleVertexShader.vertexshader.txt.glsl
common/loadShader.cpp
ID
OpenGL 3
vec3GLSLglm::vec3
C++GLSL
layout(location = 0)vertexPosition_modelspace
OpenGL
vec3glvertexAttribPointer
layout012
glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &v)
vertexPosition_modelspace
inout
mainC
void main(){
main1,1
gl_Position.xyz = vertexPosition_modelspace;
gl_Position.w = 1.0;
}
gl_Position
4
4
vec3(1,0,0)1,0,0
mainLoadShaders
main
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
OpenGL
()
Homogeneous coordinates
(x, y, z)w(x, y, z, w)
w==1(x, y, z, 1)
w==0(x, y, z, 0)
Transformation matrices
23
44(x, y, z, w)
x=
axax b
ybyczdwax + by + cz + dwx
(x, y, z, w)
C++GLM
glm::mat4 myMatrix;
glm::vec4 myVector;
// fill myMatrix and myVector somehow
glm::vec4 transformedVector = myMatrix * myVector; // Again, in this order ! this is important.
GLSL
mat4 myMatrix;
vec4 myVector;
// fill myMatrix and myVector somehow
vec4 transformedVector = myMatrix * myVector; // Yeah, it's pretty much the same than GLM
Translation matrices
XYZ
(10, 10, 10, 1)X10
(0, 0, -1, 0)
C++GLM
GLSLGLSLC++glm::translate()
GLSLGLSL
Identity matrix
A*1.0=A
C++
Scaling matrices
w
(X, Y, Z) = (1, 1,
1)(X, Y, Z)=(0, 0, 0)
C++
Rotation matrices
C++
(10, 0, 0)10
22
2*10=20
--
C++GLM
GLSL
ModelViewProjection
BlenderSuzanne
XYZ
(0, 0, 0)
GLSLC++
World Space
Model Space
X
3X3
Camera Space
GLMglm::LookAt
(0,0)
xyz
xyz
perspective projection
44 :
// Generates a really hard-to-read matrix, but a normal, standard 4x4 matrix nonetheless
glm::mat4 projectionMatrix = glm::perspective(
FoV, // The horizontal Field of View, in degrees : the amount of "zoom". Think "camera le
4.0f / 3.0f, // Aspect Ratio. Depends on the size of your window. Notice that 4/3 == 800/600 == 1
0.1f, // Near clipping plane. Keep as big as possible, or you'll get precision issues.
100.0f // Far clipping plane. Keep as little as possible.
);
Homogeneous Space
frustum
-11
MVP
MVP
// Projection matrix : 45 Field of View, 4:3 ratio, display range : 0.1 unit 100 units
glm::mat4 Projection = glm::perspective(45.0f, 4.0f / 3.0f, 0.1f, 100.0f);
// Camera matrix
glm::mat4 View = glm::lookAt(
glm::vec3(4,3,3), // Camera is at (4,3,3), in World Space
glm::vec3(0,0,0), // and looks at the origin
glm::vec3(0,1,0) // Head is up (set to 0,-1,0 to look upside-down)
);
// Model matrix : an identity matrix (model will be at the origin)
glm::mat4 Model = glm::mat4(1.0f); // Changes for each model !
// Our ModelViewProjection : multiplication of our 3 matrices
glm::mat4 MVP = Projection * View * Model; // Remember, matrix multiplication is the other way
MVPGLSL
GLSLMVP
in vec3 vertexPosition_modelspace;
uniform mat4 MVP;
void main(){
// Output position of the vertex, in clip space : MVP * position
vec4 v = vec4(vertexPosition_modelspace,1); // Transform an homogeneous 4D vector, remember ?
gl_Position = MVP * v;
}
6
45
glm::perspective
orthographic projection glm::ortho
ModelMatrix
--
1 : [...]44affine
WW-Z
ZXY
Z-Buffer
OpenGL12
// Our vertices. Tree consecutive floats give a 3D vertex; Three consecutive vertices give a triangle
// A cube has 6 faces with 2 triangles each, so this makes 6*2=12 triangles, and 12*3 vertices
static const GLfloat g_vertex_buffer_data[] = {
-1.0f,-1.0f,-1.0f, // triangle 1 : begin
-1.0f,-1.0f, 1.0f,
-1.0f, 1.0f, 1.0f, // triangle 1 : end
1.0f, 1.0f,-1.0f, // triangle 2 : begin
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f,-1.0f, // triangle 2 : end
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
1.0f,-1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
-1.0f,-1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
-1.0f,-1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f,-1.0f,
1.0f,-1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
1.0f, 1.0f,-1.0f,
-1.0f, 1.0f,-1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f,-1.0f,
-1.0f, 1.0f, 1.0f,
1.0f, 1.0f, 1.0f,
-1.0f, 1.0f, 1.0f,
1.0f,-1.0f, 1.0f
};
-1.0f,-1.0f,-1.0f
:)
Adding colors
OpenGL
glEnableVertexAttribArray()glVertexAttribPointer()
RGB
GLuint colorbuffer;
glGenBuffers(1, &colorbuffer);
glBindBuffer(GL_ARRAY_BUFFER, colorbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_color_buffer_data), g_color_buffer_data, GL_STATIC_DRAW);
in vec3 fragmentColor;
Z-Buffer
1 : (4,3,-3)
2 : vec3 fragmentColor
OpenGL
gl_Position
Z-BufferThe Z-Buffer
Z
MVP
glBufferData
glBindBuffer
UV
OpenGL
mipmap
GLFW
alpha
UV
OpenGLUV
UV
.BMP
BMPBMP
BMP
BMP
54BMP
BMBMP
BM
if ( header[0]!='B' || header[1]!='M' ){
printf("Not a correct BMP filen");
return 0;
}
width = *(int*)&(header[0x12]);
height = *(int*)&(header[0x16]);
// Create a buffer
data = new unsigned char [imageSize];
// Read the actual data from the file into the buffer
fread(data,1,imageSize,file);
//Everything is in memory now, the file can be closed
fclose(file);
OpenGL
glTexImage2DGL_RGBGL_BGR
BMPRGBBGROpenGL
C++
2power-of-two
128128, 256256, 10241024, 2*2
127128, 35,
128*256
OpenGL
UV
Sampler2D
texture()(R,G,B,A)vec4A
UV
// Two UV coordinatesfor each vertex. They were created with Blender. You'll learn shortly how to do
static const GLfloat g_uv_buffer_data[] = {
0.000059f, 1.0f-0.000004f,
0.000103f, 1.0f-0.336048f,
0.335973f, 1.0f-0.335903f,
1.000023f, 1.0f-0.000013f,
0.667979f, 1.0f-0.335851f,
0.999958f, 1.0f-0.336064f,
0.667979f, 1.0f-0.335851f,
0.336024f, 1.0f-0.671877f,
0.667969f, 1.0f-0.671889f,
1.000023f, 1.0f-0.000013f,
0.668104f, 1.0f-0.000013f,
0.667979f, 1.0f-0.335851f,
0.000059f, 1.0f-0.000004f,
0.335973f, 1.0f-0.335903f,
0.336098f, 1.0f-0.000071f,
0.667979f, 1.0f-0.335851f,
0.335973f, 1.0f-0.335903f,
0.336024f, 1.0f-0.671877f,
1.000004f, 1.0f-0.671847f,
0.999958f, 1.0f-0.336064f,
0.667979f, 1.0f-0.335851f,
0.668104f, 1.0f-0.000013f,
0.335973f, 1.0f-0.335903f,
0.667979f, 1.0f-0.335851f,
0.335973f, 1.0f-0.335903f,
0.668104f, 1.0f-0.000013f,
0.336098f, 1.0f-0.000071f,
0.000103f, 1.0f-0.336048f,
0.000004f, 1.0f-0.671870f,
0.336024f, 1.0f-0.671877f,
0.000103f, 1.0f-0.336048f,
0.336024f, 1.0f-0.671877f,
0.335973f, 1.0f-0.335903f,
0.667969f, 1.0f-0.671889f,
1.000004f, 1.0f-0.671847f,
0.667979f, 1.0f-0.335851f
};
UV
glVertexAttribPointer32
mipmap
loadBMP_custom
texture()(U,V)texel
Linear filtering
texture()UV
Anisotropic filtering
Mipmaps
4
3D
mipmap
1/211
mipmap
nearestlinearanisotropicmipmap
mipmap
OpenGL
// When MAGnifying the image (no bigger mipmap available), use LINEAR filtering
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// When MINifying the image, use a LINEAR blend of two mipmaps, each filtered LINEARLY too
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
// Generate mipmaps, by the way.
glGenerateMipmap(GL_TEXTURE_2D);
GLFW
loadBMP_customGLFW
TGA
JPEGTGA
The Compressonator,ATI
DXT1DXT3DXT5Wikipedia
mipmapmipmap
.DDS
GPUtexture()
20%
BMP
fclose(fp);
return 0;
}
/* get the surface desc */
fread(&header, 124, 1, fp);
unsigned int height = *(unsigned int*)&(header[8 ]);
unsigned int width = *(unsigned int*)&(header[12]);
unsigned int linearSize = *(unsigned int*)&(header[16]);
unsigned int mipMapCount = *(unsigned int*)&(header[24]);
unsigned int fourCC = *(unsigned int*)&(header[80]);
mipmap
DXT1DXT3DXT5fourCCOpenGL
mipmap
UV
DXTDirectXOpenGLDirectXV
(coord.v, 1.0-coord.v)
OpenGL
The
Compressonator
DDS UV
DDS
The Compressonatormipmap3
common/controls.cpp
common/controls.hpptutorial06.cpp
tutorial06.cppMVP
do{
// ...
// Compute the MVP matrix from keyboard and mouse input
computeMatricesFromInputs();
glm::mat4 ProjectionMatrix = getProjectionMatrix();
glm::mat4 ViewMatrix = getViewMatrix();
glm::mat4 ModelMatrix = glm::mat4(1.0);
glm::mat4 MVP = ProjectionMatrix * ViewMatrix * ModelMatrix;
// ...
}
3
computeMatricesFromInputs()
getProjectionMatrix()
getViewMatrix()
controls.cpp
// position
glm::vec3 position = glm::vec3( 0, 0, 5 );
// horizontal angle : toward -Z
float horizontalAngle = 3.14f;
// vertical angle : 0, look at the horizon
float verticalAngle = 0.0f;
// Initial Field of View
float initialFoV = 45.0f;
float speed = 3.0f; // 3 units / second
float mouseSpeed = 0.005f;
FoV is the level of zoom. 80 = very wide angle, huge deformations. 60 45 : standard. 20 : big z
FoV
1024*768glfwGetWindowSize
1024/2 xpos
float()
mouseSpeed
+= : 1024/2-xposhorizontalAngle+=0horizontalAngle
=
YXZ90Pi/2
// Right vector
glm::vec3 right = glm::vec3(
sin(horizontalAngle - 3.14f/2.0f),
0,
cos(horizontalAngle - 3.14f/2.0f)
);
///wsadazertyawsd
zqsdqwerZ
// Move forward
if (glfwGetKey( GLFW_KEY_UP ) == GLFW_PRESS){
position += direction * deltaTime * speed;
}
// Move backward
if (glfwGetKey( GLFW_KEY_DOWN ) == GLFW_PRESS){
position -= direction * deltaTime * speed;
}
// Strafe right
if (glfwGetKey( GLFW_KEY_RIGHT ) == GLFW_PRESS){
position += right * deltaTime * speed;
}
// Strafe left
deltaTime1
6060*speed
2020*speed
deltaTime
601/60speed1speed
201/20speed1speed
deltaTime
// Projection matrix : 45 Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
ProjectionMatrix = glm::perspective(FoV, 4.0f / 3.0f, 0.1f, 100.0f);
// Camera matrix
ViewMatrix = glm::lookAt(
position, // Camera is here
position+direction, // and looks here : at the same position, plus "direction"
up // Head is up (set to 0,-1,0 to look upside-down)
);
GPU
GPU
verticalAngle
( position = ObjectCenter + ( radius cos(time), height, radius
sin(time) ) )///
3D
OBJ
UVOBJ
OBJ
common/objloader.hppcommon/objloader.cpp
bool loadOBJ(
const char * path,
std::vector & out_vertices,
std::vector & out_uvs,
std::vector & out_normals
)
loadOBJout_vertices/out_uvs/out_normalsfalse
std::vectorC++glm::vec3std::vector
vector&
OBJ
OBJ
vt 0.498993 0.250415
vt 0.748953 0.250920
vn 0.000000 0.000000 -1.000000
vn -1.000000 -0.000000 -0.000000
vn -0.000000 -0.000000 1.000000
vn -0.000001 0.000000 1.000000
vn 1.000000 -0.000000 0.000000
vn 1.000000 0.000000 0.000001
vn 0.000000 1.000000 -0.000000
vn -0.000000 -1.000000 0.000000
usemtl Material_ray.png
s off
f 5/1/1 1/2/1 4/3/1
f 5/1/1 4/3/1 8/4/1
f 3/5/2 7/6/2 8/7/2
f 3/5/2 8/7/2 4/8/2
f 2/9/3 6/10/3 3/5/3
f 6/10/4 7/6/4 3/5/4
f 1/2/5 5/1/5 2/9/5
f 5/1/6 6/10/6 2/9/6
f 5/1/7 8/11/7 6/10/7
f 8/11/7 7/12/7 6/10/7
f 1/2/8 2/9/8 3/13/8
f 1/2/8 3/13/8 4/14/8
C++//
usemtlmtlib
v
vt
vn
f
v vt vnff 8/11/7 7/12/7 6/10/7
8/11/7
7/12/7
6/10/7
8-1.000000 1.000000 -1.0000001
C++0
110.748355 0.998230
70.000000 1.000000 -0.000000
V
OpenGL
OpenGL
BlenderOBJ
Blender
OBJ
OK.obj
while( 1 ){
char lineHeader[128];
// read the first word of the line
int res = fscanf(file, "%s", lineHeader);
if (res == EOF)
break; // EOF = End Of File. Quit the loop.
// else : parse lineHeader
128
v3float3glm::vec3
vvt2float2glm::vec2
OpenGL
f v/vt/vn
vertexIndices[i]
out_vertices.push_back(vertex);
UV
OpenGL
1
1
abab1
(normal)normalize()Normalize()
normal1(normal)
OpenGL
OpenGL
OpenGLUV
loadOBJOBJ
GLuint normalbuffer;
glGenBuffers(1, &normalbuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glBufferData(GL_ARRAY_BUFFER, normals.size() * sizeof(glm::vec3), &normals[0], GL_STATIC_DRAW);
// Cosine of the angle between the normal and the light direction,
// clamped above 0
// - light is at the vertical of the triangle -> 1
// - light is perpendicular to the triangle -> 0
float cosTheta = dot( n,l );
color = LightColor * cosTheta;
nl
cosThetanln.lcolour=
clamp()cosTheta0
// Cosine of the angle between the normal and the light direction,
// clamped above 0
LightColor
60
MaterialDiffuseColor
LightColorLightPowerGLSLuniform
cosThetanl
Normal_cameraspaceLightDirection_cameraspace
// Vector that goes from the vertex to the light, in camera space. M is ommited because it's identity
vec3 LightPosition_cameraspace = ( V * vec4(LightPosition_worldspace,1)).xyz;
LightDirection_cameraspace = LightPosition_cameraspace + EyeDirection_cameraspace;
MVMVP
Suzanne
clamp()
Suzanne
(0.1, 0.1, 0.1)
REl
pow(cosAlpha,5)5
microfacet BRDF
VBO
VBO
VBO
index buffer
UVUVOBJ
vs
OpenGL
OpenGLVBO
ELEMENT_ARRAY_BUFFER ARRAY_BUFFER
glDrawArrays
// Index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
// Draw the triangles !
glDrawElements(
GL_TRIANGLES, // mode
indices.size(), // count
GL_UNSIGNED_INT, // type
(void*)0 // element array buffer offset
);
OpenGLOBJ3D
Collada
C++ common/vboindexer.cpp
UV
std::map
FPS
FPS
alpha
alphaRGBRGBA
swizzle operator.xyz.a
color.a = 0.3;
alpha50%
1020
44MSAA
2001Depth Peeling
Dual Depth Peeling
fragmentshader
ATI Mecha Demofragment
Cyril CrassinATI Mecha
Little Big Planet
In order for the previous code to work, you need to setup your
blend function.
// Enable blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
new color = 0.5*(0,1,0) + (1-0.5)*(1,0.5,0.5); // (the red was already blended with the white backgro
new color = (1, 0.75, 0.25) = the same orange
2D
API
common/text2D.h
640*4801080pxy[0-800][0-600]
common/text2D.cpp
initText2D
CBFGCBFGPaint.NET
printText2D()
std::vector<glm::vec2> vertices;
std::vector<glm::vec2> UVs;
UV
glDrawArrays
[0,800][0,600]vertex shader
[-1,1][-1,1]C++
void main(){
// Output position of the vertex, in clip space
// map [0..800][0..600] to [-1..1][-1..1]
vec2 vertexPosition_homoneneousspace = vertexPosition_screenspace - vec2(400,300);
vertexPosition_homoneneousspace /= vec2(400,300);
gl_Position = vec4(vertexPosition_homoneneousspace,0,1);
// UV of the vertex. No special space for this one.
UV = vertexUV;
}
fragment shader
void main(){
color = texture( myTextureSampler, UV );
, , OpenGL 2
UTF-8
Joel SpolskyThe Absolute Minimum Every Software Developer Absolutely,
Positively Must Know About Unicode and Character Sets (No Excuses!)
Valve
OpenGL
GPU
NVIDIA, AMDIntel
ARB_fragment_program
2002GPU
Fixed-Function Pipeline (FFP)OpenGL 1.3
NVIDIA
ARB_fragment_programGLSL
OpenGLOpenGL
ARB_debug_output
ARB_fragment_program
ARB_debug_outputOpenGL 3.3/
GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
GL_DEBUG_SEVERITY_MEDIUM_ARBDebugMessageCallbackARB
OpenGL 3.3
ARB_debug_output
(OpenGL.org wiki)
int NumberOfExtensions;
glGetIntegerv(GL_NUM_EXTENSIONS, &NumberOfExtensions);
for(i=0; i<NumberOfExtensions; i++) {
const GLubyte *ccc=glGetStringi(GL_EXTENSIONS, i);
if ( strcmp(ccc, (const GLubyte *)"GL_ARB_debug_output") == 0 ){
// The extension is supported by our hardware and driver
// Try to get the "glDebugMessageCallbackARB" function :
glDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC) wglGetProcAddress("glDebugMessage
}
}
GLEW, GLee, gl3wGLEW
glewInit()
if (GLEW_ARB_debug_output){ // Ta-Dah ! }
(debug_outputGLFW
glfwOpenWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1))
ARB vs EXT vs
OpenGL 3.3
GL_NV_path_rendering
if ( GLEW_NV_path_rendering ){
glPathStringNV( ... ); // Draw the shape. Easy !
}else{
// Else what ? You still have to draw the lines
// on older NVIDIA hardware, on AMD and on INTEL !
// So you have to implement it yourself anyway !
}
Braid,
OpenGL 3.399%
GL_AMD_pinned_memory,GL_ARB_framebuffer_object()
10
OpenGL 3+OpenGL 2+
Conclusion
OpenGLOpenGLGPU
GLEW OpenGL
gl3w OpenGL 3/4
normal mapping
RGBXYZ01-1
1
ZOpenGLY=
tangent
spaceimage space
UpBlender
TB
TBN
TBN
invTBN = transpose(TBN)
VBO
void computeTangentBasis(
// inputs
std::vector<glm::vec3> & vertices,
std::vector<glm::vec2> & uvs,
std::vector<glm::vec3> & normals,
// outputs
std::vector<glm::vec3> & tangents,
std::vector<glm::vec3> & bitangents
){
deltaPos deltaUV
// Set the same tangent for all three vertices of the triangle.
// They will be merged later, in vboindexer.cpp
tangents.push_back(tangent);
tangents.push_back(tangent);
tangents.push_back(tangent);
// Same thing for binormals
bitangents.push_back(bitangent);
bitangents.push_back(bitangent);
bitangents.push_back(bitangent);
}
VBO
Shader
uniform
GLuint tangentbuffer;
glGenBuffers(1, &tangentbuffer);
glBindBuffer(GL_ARRAY_BUFFER, tangentbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_tangents.size() * sizeof(glm::vec3), &indexed_tangents[
GLuint bitangentbuffer;
glGenBuffers(1, &bitangentbuffer);
glBindBuffer(GL_ARRAY_BUFFER, bitangentbuffer);
glBufferData(GL_ARRAY_BUFFER, indexed_bitangents.size() * sizeof(glm::vec3), &indexed_bitangents[
uniform
[...]
GLuint NormalTexture = loadTGA_glfw("normal.tga");
[...]
GLuint NormalTextureID = glGetUniformLocation(programID, "NormalTextureSampler");
uniform3x3
3x3
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 3rd attribute buffer : normals
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, normalbuffer);
glVertexAttribPointer(
2, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 4th attribute buffer : tangents
glEnableVertexAttribArray(3);
glBindBuffer(GL_ARRAY_BUFFER, tangentbuffer);
glVertexAttribPointer(
3, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// 5th attribute buffer : bitangents
glEnableVertexAttribArray(4);
glBindBuffer(GL_ARRAY_BUFFER, bitangentbuffer);
glVertexAttribPointer(
4, // attribute
3, // size
GL_FLOAT, // type
GL_FALSE, // normalized?
0, // stride
(void*)0 // array buffer offset
);
// Index buffer
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, elementbuffer);
// Draw the triangles !
glDrawElements(
GL_TRIANGLES, // mode
indices.size(), // count
GL_UNSIGNED_INT, // type
(void*)0 // element array buffer offset
);
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);
// Swap buffers
glfwSwapBuffers();
Vertex shader
TBN
TBN
XXX_modelspace
Fragment shader
nln
lclamp( dot( n,l ), 0,1 )clamp( dot( E,R ), 0,1 )E
RS
Orthogonalization
Vertex shader
computeTangentBasis() I
nt t -n dot(n,t) applet
UVT
TBN cross(n,t) b
AB dot(A,B)>0 dot( cross(n,t) , b )
0
dot( cross(n,t) , b ) < 0 t
computeTangentBasis()
Specular texture
vec3(0.3,0.3,0.3)
3.3 Core Profile
glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
OpenGL
hacking
glMatrixMode(GL_PROJECTION);
glLoadMatrixf((const GLfloat*)&ProjectionMatrix[0]);
glMatrixMode(GL_MODELVIEW);
glm::mat4 MV = ViewMatrix * ModelMatrix;
glLoadMatrixf((const GLfloat*)&MV[0]);
glUseProgram(0);
0.1
glColor3f(0,0,1);
glBegin(GL_LINES);
for (int i=0; i<indices.size(); i++){
glm::vec3 p = indexed_vertices[indices[i]];
glVertex3fv(&p.x);
glm::vec3 o = glm::normalize(indexed_normals[indices[i]]);
p+=o*0.1f;
glVertex3fv(&p.x);
}
glEnd();
Core Profile
LightDirection_tangentspace
color.xyz = LightDirection_tangentspace;
+X
0
alpha
>
(v+1.0)/2.0
-1+1
_modelspace
James OHare
indexVBO_TBN
instance EyeDirection_tangentspace
Crazybump
Nvidia photoshopPhotoshop
Lengyel, Eric. Computing Tangent Space Basis Vectors for an Arbitrary Mesh. Terathon Software
3D Graphics Library, 2001.
Real Time Rendering, third edition
ShaderX4
in-gamepost-processing.
Render Target
(depth buffer)
OpenGL:
RGB
depth buffer
Suzanne
frameBuffer
GPU
fragment shader
color0
`glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, renderedTexture, 0);
mipmap0GL_COLOR_ATTACHMENT0
buffershaderID
glBindBuffer(GL_ARRAY_BUFFER, quad_vertexbuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(g_quad_vertex_buffer_data), g_quad_vertex_buffer_data, GL_STATIC
// Create and compile our GLSL program from the shaders
GLuint quad_programID = LoadShaders( "Passthrough.vertexshader", "SimpleTexture.fragmentshader"
GLuint texID = glGetUniformLocation(quad_programID, "renderedTexture");
GLuint timeID = glGetUniformLocation(quad_programID, "time");
glBindFramebuffer0
shader
(2416,24,3224)
Hi-Z
= Z0 =
= Z1 =
C++glTexImage2D
glTexImage2DMultisamplefragment shader sampler2D/texture
sampler2DMS/texelFetch
texelFetch
resolution
glFramebufferTexture
color attachement (2,
{GL_COLOR_ATTACHMENT0,GL_COLOR_ATTACHMENT1,GL_DEPTH_ATTACHMENT}) glDrawBuffers
116328
glTexImage2DGL_FLOAT 2OpenGLglFragData[1]
= myvalue
glViewport(0,0,512,768) glViewport(0,0,1024,768)
fragment shaderUV
controls.hpp
http://www.opengl-tutorial.org/
Written with StackEdit.
Lightmap
OpenGL/
Blenderbakelightmap
Blender
2009Mirror Edge
1024x768
Youku Vimeo
OpenGL
mipmapmipmap
BlenderUVlimitsmarginmarginbake
margin20
bias
-2bias+2OpenGL
mipmap1/16
Shadow mapping
2012
2012
MVP
shader
1024x10241616;
MVP
AABBaxis-aligned box,
XYZ(-10,10)(-10,10)(-10,20)
-Z[]
Shaders
void main(){
gl_Position = depthMVP * vec4(vertexPosition_modelspace,1);
}
fragment shaderlocation 0
GPU
zz=1
shader
fragment
MVP depthMVP
depthMVP[-1,1]
[0,1]
fragment(0,0)UV
(0.5,0.5)
glm::mat4 biasMatrix(
0.5, 0.0, 0.0, 0.0,
0.0, 0.5, 0.0, 0.0,
0.0, 0.0, 0.5, 0.0,
0.5, 0.5, 0.5, 1.0
);
glm::mat4 depthBiasMVP = biasMatrix*depthMVP;
vertex shader
gl_Position
ShadowCoord
fragment shader
texture2D( shadowMap, ShadowCoord.xy ).z
ShadowCoord.z
fragment
color =
// Ambiant : simulates indirect lighting
MaterialAmbiantColor +
// Diffuse : "color" of the object
visibility * MaterialDiffuseColor * LightColor * LightPower * cosTheta+
// Specular : reflective highlight, like a mirror
visibility * MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5);
Shadow acne
error marginfragment
bias
0.005
Peter Panning
// We don't use bias in the shader, but instead we draw back faces,
// which are already separated from the front faces by a small distance
Peter Panning
[0,1]float
0.5
truefalsePCF4true
false
Poisson Sampling
NPCF
poissonDisk
fragment
700.0
PCF16
poissonDisk
[0,1]
tutorial16/ShadowMapping.fragmentshader
Early bailing
1616
16
Spot lights
texture2Dproj
shader
w
w1
GLSL textureProj
Point lights
cubemap6
UV
T
1Km x 1Km1024x1024
1
()
LiSPSMduelling frustra
duelling frustra
()
LiSPSM
CSMCascaded shadow map CSMLiSPSM
CSM2~4
CSM/
LiSPSMCSMPCF
OpenGL
Euler anglesQuaternion
orientation
XYZvec3
Y-Z-X
XZY
float
FPSYX
common/controls.cpp
XYZ
(Gimbal Lock)
-180180
YZXYZX
N
4[x y z w]
// RotationAngle is in radians
x = RotationAxis.x * sin(RotationAngle / 2)
y = RotationAxis.y * sin(RotationAngle / 2)
z = RotationAxis.z * sin(RotationAngle / 2)
w = cos(RotationAngle / 2)
RotationAxis RotationAngle
xyz
w=acos(/2)[ 0.7 0 0 0.7 ]x=0.7yz
X2*acos(0.7) = 1.5990
[0 0 0 1] (w=1) = 2acos(1) = 0*unit quaternion
C++
// Don't forget to #include <glm/gtc/quaternion.hpp> and <glm/gtx/quaternion.hpp>
// Creates an identity quaternion (no rotation)
quat MyQuaternion;
// Direct specification of the 4 components
// You almost never use this directly
MyQuaternion = quat(w,x,y,z);
// Conversion from Euler angles (in radians) to Quaternion
vec3 EulerAngles(90, 45, 0);
MyQuaternion = quat(EulerAngles);
// Conversion from axis-angle
// In GLM the angle must be in degrees here, so convert it.
MyQuaternion = gtx::quaternion::angleAxis(degrees(RotationAngle), RotationAxis);
GLSL
shader
MVP
shaderGPUGLSL
vec4shader
3D
3D
FPS
1.
2. 1Game Programming Gems I
3. [GDC]http://www.essentialmath.com/GDC2012/GDC2012_JMV_Rotations.pdf
4. The Game Programing Wiki Quaternion tutorial
5. Ogre3D FAQ on quaternions OGRE
6. Ogre3D Vector3D.hQuaternion.cpp
acosq1q2
v1v2
cos
common/quaternion_utils.cpp
gluLookAt
RotationBetweenVectors
// Find the rotation between the front of the object (that we assume towards +Z,
// but this depends on your model) and the desired direction
quat rot1 = RotationBetweenVectors(vec3(0.0f, 0.0f, 1.0f), direction);
LookAt
SLERP glm::mix
mix
RotateTowards
common/quaternion_utils.cpp
Billbard
3D2D2D3D
1:2D
2D2D
2D
2:3D
2D3D
The idea is
that each corner of the billboard is at the center position, displaced by the cameras up and right vectors :
up/right
up(0,1,0)up
vec3 vertexPosition_worldspace =
particleCenter_wordspace
+ CameraRight_worldspace * squareVertices.x * BillboardSize.x
+ CameraUp_worldspace * squareVertices.y * BillboardSize.y;
particleCenter_worldspace vec3uniform
squareVertices squareVertices.x -0.5which are thus
squareVertices
33D
vertexPosition_worldspace = particleCenter_wordspace;
// Get the screen-space position of the particle's center
gl_Position = VP * vec4(vertexPosition_worldspace, 1.0f);
// Here we have to do the perspective division ourselves.
gl_Position /= gl_Position.w;
// Move the vertex in directly screen space. No need for CameraUp/Right_worlspace here.
gl_Position.xy += squareVertices.xy * vec2(0.2, 0.05);
4
So you need an
hybrid system that rotates only around one axis.
ParticlesInstancing
3D
glDrawArrays
GTX 51299%
VBO
geometry shader50%
instancing
bufferinstancing
buffer
bufferindex buffer6 vec3
buffer
buffer
bufferbuffer
glBindBuffer(GL_ARRAY_BUFFER, particles_position_buffer);
glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLfloat), NULL, GL_STREAM_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, ParticlesCount * sizeof(GLfloat) * 4, g_particule_position_size_d
glBindBuffer(GL_ARRAY_BUFFER, particles_color_buffer);
glBufferData(GL_ARRAY_BUFFER, MaxParticles * 4 * sizeof(GLubyte), NULL, GL_STREAM_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, ParticlesCount * sizeof(GLubyte) * 4, g_particule_color_data);
buffer
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, ParticlesCount);
OpenGLbufferbuffer
glVertexAttribDivisor
instancing AttribDivisor
'glVertexAttribDivisor(2, 10)'10
buffer
4
new Particle()
ParticleContainer
int LastUsedParticle = 0;
// Finds a Particle in ParticlesContainer which isn't used yet.
// (i.e. life < 0);
int FindUnusedParticle(){
10000
=)
ParticlesContainer GPUbuffer
GPUbuffer
[][1]
void SortParticles(){
std::sort(&ParticlesContainer[0], &ParticlesContainer[MaxParticles]);
}
std::sort Particle::operator<
ParticleContainer
texture atlasGPU[2D
][2]shaderUV
UV
Z-BufferZ-Buffer[
][3] glBlitFrameBuffer Z-Buffer
http://developer.download.nvidia.com/whitepapers/2007/SDK10/SoftParticles_hi.pdf
GPU16.6ms60FPS
10
glDrawArraysInstanced()
[http://www.humus.name/index.php?page=Cool&ID=8][4]Emil Person
raycasting
[][5]
k-DOP
Z-Buffer
CPUZ-Buffer()GPU
[http://www.altdevblogaday.com/2012/06/19/hack-day-report/][6]
[http://www.gdcvault.com/search.php#&category=free&firstfocus=&keyword=Chris+Tchous%2BHalo%2B
Reach%2BEffects&conference_id=][7]
GPU
GPUCPU