Vous êtes sur la page 1sur 46

Introduction to OpenGL/GLSL and

WebGL

GLSL
Objectives
!  Give you an overview of the software
that you will be using this semester
!  OpenGL, WebGL, and GLSL
!  What are they?
!  How do you use them?
!  What does the code look like?
!  Evolution
!  All of them are required to write modern
graphics code, although alternatives exist
What is OpenGL?
!  An application programming interface (API)
!  A (low-level) Graphics rendering API
!  Generate high-quality images from geometric
and image primitives
Maximal Portability
!  Display device independent
!  Window system independent
!  Operating system independent
Without a standard API (such as OpenGL) - impossible to port

(100, 50) Line(100,50,150,80) - device/lib 1

(150, 100) Moveto(100,50) - device/lib 2


Lineto(150,100)
Brief History of OpenGL
!  Originated from a proprietary API called Iris GL from Silicon
Graphics, Inc.
!  Provide access to graphics hardware capabilities at the
lowest possible level that still provides hardware
independence
!  The evolution is controlled by OpenGL Architecture Review
Board, or ARB.
!  OpenGL 1.0 API finalized in 1992, first implementation in
1993
!  In 2006, OpenGL ARB became a workgroup of the Khronos
Group
!  10+ revisions since 1992
OpenGL Evolution
!  1.1 (1997): vertex arrays and texture objects
!  1.2 (1998): 3D textures
!  1.3 (2001): cubemap textures, compressed
textures, multitextures
!  1.4 (2002): mipmap generation, shadow map
textures, etc
!  1.5 (2003): vertex buffer object, shadow
comparison functions, occlusion queries, non-
power-of-2 textures
OpenGL Evolution
!  2.0 (2004): vertex and fragment shading (GLSL
1.1), multiple render targets, etc
!  2.1 (2006): GLSL 1.2, pixel buffer objects, etc
!  3.0 (2008): GLSL 1.3, deprecation model, etc
!  3.1 (2009): GLSL 1.4, texture buffer objects, move
much of deprecated functions to ARB compatible
extension
!  3.2 (2009)
!  4.X (2012 and on)
OpenGL Basics

!  OpenGL’s primary function – Rendering

!  Rendering? – converting geometric/mathematical


object descriptions into frame buffer values

!  OpenGL can render:


!  Geometric primitives
!  Bitmaps and Images (Raster primitives)
OpenGL Example

Cube with flat color Cube with lighting Cube with textures
WebGL
!  JavaScript implementation of OpenGL
!  Run in all modern browsers (Chrome, Safari,
Firefox, IE, etc).
!  Application can be located on a remote server

!  Rendering is done within browser using local


hardware
!  Uses HTML5 canvas

!  Integrated with standard Web packages and


apps (CSS, jQuery, etc.)
What do you need to know
!  Web Environment and Execution
!  Modern OpenGL basics
!  Pipeline architecture

!  Shaders (vertex and fragment) based OpenGL

!  OpenGL Shading Language (GLSL)

!  Javascript
OpenGL ES and WebGL
!  OpenGL ES
!  A subset of OpenGL 3.1 API (lightweight)

!  Designed for embedded system (mobile phones


etc.)
!  Shader based

!  WebGL
!  Javascript implementation of ES 2.0

!  Runs on browswers
WebGL Rendering Pipeline
WebGL Programming

!  General Structure:
!  Set up canvas to render to
!  Generate data/geometry in application
!  Create shader programs
!  Create buffer objects and load data to them
!  Connect buffer objects and data to shader variables
!  Set up proper viewing and lighting conditions
!  Render
WebGL Programming

!  WebGL needs a place to render into


!  HTML5 canvas element
!  All the code can be put in a single HTML file
!  Or you can put setup code in an HTML file and
your application code in separate Javascript files
!  HTML file includes shaders
!  HTML file reads in application and utilities
Example 0

!  A very simple example that creates a canvas but


display nothing except a yellow background

<!DOCTYPE html>
<html>
<head>
<title>hwshen WebGL &mdash; code00 </title>
WebGL <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
Javascript <script type="text/javascript" src="code00.js"></script>
</head>
<body onload="webGLStart();”>
canvas <canvas id="code00-canvas" style="border: none;" width="700" height="500"></
canvas>
<br/>
</body>
</html>
code00.js
var gl; function webGLStart() {
function initGL(canvas) { var canvas = document.getElementById("code00-
try { canvas");
gl = canvas.getContext("experimental-webgl"); initGL(canvas);
gl.viewportWidth = canvas.width; gl.clearColor(1.0, 1.0, 0.0, 1.0); // yellow
gl.viewportHeight = canvas.height; drawScene();
} catch (e) { }
}
if (!gl) {
alert("Could not initialise WebGL, sorry :-(");
} viewport
}

function drawScene() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
}
Simple OpenGL commands
!  HTML will call webGLStart();
!  canvas is an HTML5 element for drawing
!  You need a OpenGL context from the canvas for
storing internal states
!  canvas.getContext();
!  All OpenGL commands in WebGL start with ‘gl.’
!  gl.viewport(); specify the display area
!  gl.clearColor(); specify the background color
!  gl.clear(); clear the foreground and background
Output
Example 1
!  Now let’s draw something (two triangles) on the
canvas
!  You will need to provide vertex and fragment
shaders
code01.html
<!DOCTYPE html>
<html>
<head>
<title>hwshen WebGL &mdash; code01 </title>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<!-- ************** Fragment Shader ************* -->
Fragment <script id="shader-fs" type="x-shader/x-fragment">
Shader
void main(void) {
gl_FragColor = vec4(1.0, 0, 0, 1.0);
}

</script>
Vertex <!-- ************** Vertex Shader ************* -->
Shader <script id="shader-vs" type="x-shader/x-vertex">

attribute vec3 aVertexPosition;


void main(void) {
gl_Position = vec4(aVertexPosition, 1.0);
}

</script>
code01.html (cont’d)
<script type="text/javascript" src="shaders_setup.js"></script>
<script type="text/javascript" src="code01.js"></script>
</head>
<body onload="webGLStart();”>
<canvas id="code00-canvas" style="border: none;" width="700" height="500"></
canvas>
<br/>
</body>
</html>
code01.js
var gl;
function initGL(canvas) { function webGLStart() {
var canvas = document.getElementById("code00-
// same as before ….
canvas");

initGL(canvas);
}
initShaders();
function initShaderers() {
initBuffers();
// setup shaders
gl.clearColor(1.0, 1.0, 0.0, 1.0); // yellow
// load the source, compile and link the code
drawScene();
// in shaders_setup.js
}
}
function initBuffers() {
// set up vertex buffer objects for geometry
// I will explain next
… function drawScene()
} gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, squareVertexPositionBuffer.itemSize,
gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);
}
Output
code01.js
!  In order to fully understand code01.js, we need to
explain
!  Vertex Buffer Objects – this is how you define your
geometry
!  Shader setup and simple GLSL concepts
!  How to draw the scene
!  Below I will start with Shaders setup and then
Vertex Buffer Objects (VBO)
OpenGL Shading Language
(GLSL)
!  A C-like language and incorporated into
OpenGL 2.0 and on
!  Used to write vertex program and
fragment program
!  No distinction in the syntax between a
vertex program and a fragment
program
!  Platform independent
Setup of Shader Prgorams
!  A shader is defined as an array of
strings
!  Steps to set up shaders
1.  Create a shader program
2.  Create shader objects (vertex and fragment)
3.  Send source code to the shader objects
4.  Compile the shader
1.  Create program object by linking
compiled shaders together
2.  Use the linked program object
shaders_setup.js
function initShaders() {

shaderProgram = gl.createProgram(); // create a shader program

var fragmentShader = getShader(gl, "shader-fs"); // create and compile a vertex shader object
var vertexShader = getShader(gl, "shader-vs"); // create and compile a fragment shader object

gl.attachShader(shaderProgram, vertexShader); // attach the vertex shader to the shader program


gl.attachShader(shaderProgram, fragmentShader); // attach the fragment shader
gl.linkProgram(shaderProgram); // link the vertex and fragment shaders

if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) {
alert("Could not initialise shaders");
}

gl.useProgram(shaderProgram); // use the shader program


}
shaders_setup.js
function getShader(gl, id) {
var shaderScript = document.getElementById(id);
if (!shaderScript) {
return null;
}
var str = "";
var k = shaderScript.firstChild; var shader;
if (shaderScript.type == "x-shader/x-fragment") {
while (k) {
shader = gl.createShader(gl.FRAGMENT_SHADER);
if (k.nodeType == 3) {
str += k.textContent; } else if (shaderScript.type == "x-shader/x-vertex") {
shader = gl.createShader(gl.VERTEX_SHADER);
}
} else {
k = k.nextSibling;
return null;
}
}
gl.shaderSource(shader, str);
gl.compileShader(shader);

if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
Vertex Buffer Objects
!  Provide per-vertex input to the GPU
!  Vertex: a point where the edges of geometry meet
!  All geometric primitives are composed of vertices, their
attributes, and the connectivity
!  Allow significant increases in vertex throughput
between CPU and GPU
!  The mechanism to provide generic attributes to the
shader, and store vertex data in video memory
!  User’s program is free to define an arbitrary set of per-
vertex attributes to the vertex shader
Create a VBO
!  Step 1: generate a new buffer object with gl.createBuffer()
!  This function returns an identifier for the buffer object
!  Step 2: Bind the buffer with a particular buffer type with
gl.bindBuffer()
!  Specify the target (i.e. what kind of buffer) to which the buffer
object is bound
!  Choice: gl.ARRAY_BUFFER, gl.ELEMENTARY_BUFFER,
gl.PIXEL_PACK_BUFFER, gl.PIXEL_UNPACK_BUFFER
!  gl.ARRAY_BUFFER is to provide vertex attributes, and
!  gl.ELEMENTARY_BUFFER is to provide triangle indices
!  Step 3: Copy the vertex data to the buffer object
!  gl.bufferData(target, data, usage)
!  Usage is the access pattern: gl.STATIC_, gl.STREAM_,
gl.DYNAMIC_{DRAW, COPY, READ}
code01.js
function initBuffers() {
squareVertexPositionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
vertices = [
0.5, 0.5, 0.0,
-0.5, 0.5, 0.0,
0.5, -0.5, 0.0,
-0.5, -0.5, 0.0
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
squareVertexPositionBuffer.itemSize = 3;
squareVertexPositionBuffer.numItems = 4; 3 numbers (x,y,z) per vertex
} 4 vertices total

The data are now sent to GPU


I will talk about how to draw the buffer in a moment, but let me first talk
about setting up shaders
code01.js (cont’d)
Use VBO for drawing:
1.  Make the vbo created earlier as active - gl.bindBuffer()
2.  Connect the buffer to an vertex attribute in the shader (explained
next)
3.  Draw the vertex array – gldrawArrays(type, offset, numbers of
vertices)

function drawScene() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);
}
code01.js (cont’d)
Use VBO for drawing:
1.  Make the vbo created earlier as active - gl.bindBuffer()
2.  Connect the buffer to an vertex attribute in the shader (explained
next)
3.  Draw the vertex array – gldrawArrays(type, offset, numbers of
vertices)

function drawScene() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);
}
code01.js (cont’d)
Use VBO for drawing:
1.  Make the vbo created earlier as active - gl.bindBuffer()
2.  Connect the buffer to an vertex attribute in the shader
3.  Draw the vertex array – gldrawArrays(type, offset, numbers of
vertices)
Location of the vertex attribute in the shader

function drawScene() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);
}
code01.js (cont’d)
What is “Location of Vertex Attribute in the shader” and how to
get it? Vertex shader in HTML
This is the attribute variable in the attribute vec3 aVertexPosition;
shader where the vertex position buffer
object is connected to void main(void) {
gl_Position =
vec4(aVertexPosition, 1.0);
code01.js }

Query the location of the variable


code01.js (cont’d)

Now Connect the buffer to an vertex attribute in the shader

code01.js

function drawScene() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);
}
code02.js

!  How to add more than one vertex attributes?


!  You can add as many vertex attributes as you want
!  code02.html

attribute vec3 aVertexPosition;


How to pass vertex color?
attribute vec4 aVertexColor;
varying vec4 vColor;

void main(void) {
gl_Position = vec4(aVertexPosition, 1.0);
vColor = aVertexColor;
}
code02.js
!  Query the locations of both aVertexPosition and
aVeretxColor
code02.js
shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition");
gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute);

shaderProgram.vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor");


gl.enableVertexAttribArray(shaderProgram.vertexColorAttribute);

!  Create another VBO for color (next page)


code02.js
!  Create a color VBO

code02.js
squareVertexColorBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer);
var colors = [
1.0, 0.0, 0.0, 1.0,
0.0, 1.0, 0.0, 1.0,
0.0, 0.0, 1.0, 1.0,
1.0, 0.0, 0.0, 1.0,
];
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
squareVertexColorBuffer.itemSize = 4; // RGBA four components
squareVertexColorBuffer.numItems = 4; // four colors

Again, note these two are not part of VBO. Just record it down
For later use in drawScene()
code02.js
!  Now draw with both position and color VBOs

code02.js
function drawScene() {
gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
squareVertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.vertexColorAttribute,
squareVertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);

gl.drawArrays(gl.TRIANGLE_STRIP, 0, squareVertexPositionBuffer.numItems);

}
WebGL Geometric Primitives
POINTS, LINES, TRIANGLES
WebGL Geometric Primitives
More
TRIANGLES Compact TRIANGLE FAN
Var vertices = [
v1 v3.x , v3.y, v3.z,
Var vertices = [ v1.x , v1.y, v1.z,
v1.x , v1.y, v1.z, v2.x , v2.y, v2.z,
T1 v3 v2.x , v2.y, v2.z,
v2 T1 v4.x , v4.y, v4.z,
T2 v3.x , v3.y, v3.z, v5.x , v5.y, v5.z
T3 v2.x , v2.y, v2.z, ];
v4 v3.x , v3.y, v3.z, T2
v5 v4.x , v4.y, v4.z, TRIANGLE STRIP
v3.x , v3.y, v3.z,
v4.x , v4.y, v4.z, T3 Var vertices = [
v5.x , v5.y, v5.z v1.x , v1.y, v1.z,
]; v2.x , v2.y, v2.z,
v3.x , v3.y, v3.z,
v4.x , v4.y, v4.z,
v5.x , v5.y, v5.z
];
Indexed Triangles
!  A more general way to represent a triangle set
!  Store vertex positions and their connectivity
separately

v1 var vertices = [ var indices = [


v1.x , v1.y, v1.z, 0, 1, 2, 1, 3, 2, 2, 3, 4
v2.x , v2.y, v2.z, ]
T1 v3
v2 v3.x , v3.y, v3.z,
T2 v4.x , v4.y, v4.z,
T3 v5.x , v5.y, v5.z T1 T2 T3
v4 ];
v5

!  How to represent this way using VBO?


Element Array for Triangle Indices
!  A more general way to represent a triangle set

// create an Array Buffer for the vertex positions as before



// now create an element array buffer for the indices

var indices = [0,1,2,1,3,2,2,3,4];


VertexIndexBuffer = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, VertexIndexBuffer);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW);
VertexIndexBuffer.itemsize = 1;
VertexIndexBuffer.numItems = 9; // 9 index numbers in the buffer, used later
Element Array for Triangle Indices (cont’d)
!  Now draw the triangles
….
gl.bindBuffer(gl.ARRAY_BUFFER, VertexPositionBuffer);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute,
VertexPositionBuffer.itemSize, gl.FLOAT, false, 0, 0);

gl.bindBuffer(gl.ARRAY_BUFFER, VertexColorBuffer);
gl.vertexAttribPointer(shaderProgram.ColorAttribute,
VertexColorBuffer.itemSize, gl.FLOAT, false, 0, 0);

// draw elementary arrays - triangle indices


gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, VertexIndexBuffer);

gl.drawElements(gl.TRIANGLES, VertexIndexBuffer.numItems, gl.UNSIGNED_SHORT, 0);

Offset, meaning you can


draw a partial set if you
want

Vous aimerez peut-être aussi