WebGL: Hands On Zhenyao Mo Software Engineer, Google, Inc. Chrome GPU Team.

Slides:



Advertisements
Similar presentations
Animation and Input CSCI Day Six. Animation Basic Steps to Draw Something: var vertices = [ … ]; var BufferId = gl.CreateBuffer(); gl.bindBuffer.
Advertisements

 The success of GL lead to OpenGL (1992), a platform-independent API that was  Easy to use  Close enough to the hardware to get excellent performance.
As well as colors, normals, and other vertex data PUSHIN’ GEO TO THE GPU JEFF CHASTINE 1.
MAT 594CM S10Fundamentals of Spatial ComputingAngus Forbes Week 4 : GLSL Shaders Topics: Shader programs, vertex & fragment shaders, passing data into.
WebGL: a New Platform for 3D Games Advanced Games Programming by Jarek Francik 2011.
2D graphics 3D graphics Segoe UI Fonts, text analysis, layout Image & video decoding GPGPU Too.
Michael Robertson Yuta Takayama. WebGL is OpenGL on a web browser. OpenGL is a low-level 3D graphics API Basically, WebGL is a 3D graphics API that generates.
1 Introduction to Computer Graphics with WebGL Ed Angel Professor Emeritus of Computer Science Founding Director, Arts, Research, Technology and Science.
WebGL Patrick Cozzi University of Pennsylvania CIS Spring 2012.
1 Introduction to Computer Graphics with WebGL Ed Angel Professor Emeritus of Computer Science Founding Director, Arts, Research, Technology and Science.
Programming Concepts. Derive a new class from Activity of the framework Prepare the data beforehand, e.g., vertices, colours, normal vectors, texture.
A Really (too) Short Introduction to OpenGL Peter Rautek.
Programming with OpenGL Part 2: Complete Programs Ed Angel Professor of Emeritus of Computer Science University of New Mexico.
Programming with OpenGL Part 2: Complete Programs Ed Angel Professor of Emeritus of Computer Science University of New Mexico.
CS 418: Interactive Computer Graphics Introduction to WebGL: HelloTriangle.html Eric Shaffer.
WebGL: in-browser 3D graphics Nick Whitelegg Maritme and Technology Faculty Southampton Solent University.
Real-Time High Quality Rendering CSE 291 [Winter 2015], Lecture 4 Brief Intro to Programmable Shaders
1 Graphics CSCI 343, Fall 2015 Lecture 4 More on WebGL.
به نام خدا تنظیم کننده : فرانه حدادی استاد : مهندس زمانیان تابستان 92.
GRAPHICS PIPELINE & SHADERS SET09115 Intro to Graphics Programming.
80 줄로 웹지엘 입문하기. canvas javascript WebGL Library GLSL 개발환경.
OpenGL Shader Language Vertex and Fragment Shading Programs.
1 Introduction to Computer Graphics with WebGL Ed Angel Professor Emeritus of Computer Science Founding Director, Arts, Research, Technology and Science.
Shaders in OpenGL Marshall Hahn. Introduction to Shaders in OpenGL In this talk, the basics of OpenGL Shading Language will be covered. This includes.
CSE 381 – Advanced Game Programming GLSL. Rendering Revisited.
OpenGL-ES 3.0 And Beyond Boston Photo credit :Johnson Cameraface OpenGL Basics.
1 Graphics CSCI 343, Fall 2015 Lecture 5 Color in WebGL.
WebGL Presentation by: Viet Nguyen.  Final Project Outline  Introduction  History  Support  Implementation  Advantages  Disadvantages  Conclusion.
Vertex Buffer Objects and Shader Attributes. For Further Reading Angel 7 th Ed: –Most parts of Chapter 2. Beginning WebGL: –Chapter 1: vertex Buffer Objects,
Programming with OpenGL Part 0: 3D API. For Further Reading Angel 7 th Ed: –2.2: JavaScript –2.3: OpenGL & WebGL –2.8: fragment & vertex shaders Beginning.
CS 480/680 Computer Graphics Programming with Open GL Part 5: Putting it all together Dr. Frederick C Harris, Jr. Fall 2011.
Programming with OpenGL Part 5: More GLSL Isaac Gang University of Mary Hardin-Baylor E. Angel and D. Shreiner: Interactive Computer Graphics 6E © Addison-Wesley.
1 Graphics CSCI 343, Fall 2015 Lecture 25 Texture Mapping.
 Learn some important functions and process in OpenGL ES  Draw some triangles on the screen  Do some transformation on each triangle in each frame.
What are shaders? In the field of computer graphics, a shader is a computer program that runs on the graphics processing unit(GPU) and is used to do shading.
MP3 Frequently Asked Questions (IN OFFICE HOURS).
Programming with OpenGL Part 3: Shaders Ed Angel Professor of Emeritus of Computer Science University of New Mexico 1 E. Angel and D. Shreiner: Interactive.
GLSL I.  Fixed vs. Programmable  HW fixed function pipeline ▪ Faster ▪ Limited  New programmable hardware ▪ Many effects become possible. ▪ Global.
COMP 175 | COMPUTER GRAPHICS Remco Chang1/XX13 – GLSL Lecture 13: OpenGL Shading Language (GLSL) COMP 175: Computer Graphics April 12, 2016.
CS 480/680 Computer Graphics Programming with Open GL Part 2: Complete Programs Dr. Frederick C Harris, Jr. Fall 2011.
Non-photorealistic rendering
Shaders, part 2 alexandri zavodny.
WebGL The HTML5/JavaScript 3D Computer Graphics API
Real-Time Rendering Buffers in OpenGL 3.3
The Basics: HTML5, Drawing, and Source Code Organization
Introduction to OpenGL
Chapter 6 GPU, Shaders, and Shading Languages
Introduction to Computer Graphics with WebGL
Objectives Simple Shaders Programming shaders with GLSL
Programming with OpenGL Part 2: Complete Programs
Introduction to Computer Graphics with WebGL
Introduction to Computer Graphics with WebGL
Chapter VI OpenGL ES and Shader
Graphics Processing Unit
Introduction to Computer Graphics with WebGL
Introduction to Shaders
Introduction to Computer Graphics with WebGL
Introduction to Computer Graphics with WebGL
Introduction to Computer Graphics with WebGL
Programming with OpenGL Part 3: Shaders
Programming with OpenGL Part 5: More GLSL
Mickaël Sereno Shaders Mickaël Sereno 25/04/2019 Mickaël Sereno -
CIS 441/541: Introduction to Computer Graphics Lecture 15: shaders
Introduction to Computer Graphics with WebGL
Programming with OpenGL Part 5: More GLSL
Introduction to OpenGL
CS 480/680 Computer Graphics GLSL Overview.
Introduction to Computer Graphics with WebGL
OpenGL-Rendering Pipeline
CS 480/680 Fall 2011 Dr. Frederick C Harris, Jr. Computer Graphics
Presentation transcript:

WebGL: Hands On Zhenyao Mo Software Engineer, Google, Inc. Chrome GPU Team

What is WebGL? Plug-in free 3D graphics for the web Based on OpenGL ES 2.0 – Same on desktops, laptops, mobile devices Javascript + Shaders

WebGL Availability Available: Firefox, Chrome, Opera Available but behind a switch: Safari/Webkit Unavailable: IE – Install Chrome Frame

WebGL Availability: Chrome Windows: 68.13% users have WebGL – 31.87%: Mostly XP users with old GPUs/drivers – Have SwiftShader, an optional software renderer Mac: 99.36% Linux: 34.06%

GPU Pipeline

Shaders Small stateless programs which run on the GPU with a high degree of parallelism A vertex shader applies to each vertex A fragment shader applies to each pixel – GPU automatically decides which pixel belongs to which triangle – GPU automatically blends vertex shader’s output – Output each pixel’s color

A Concrete Example Adapted from Giles Thomas' Learning WebGL Lesson 2 Code is checked in to ode.com/ under hello-webgl/

Vertex Shader attribute vec3 positionAttr; attribute vec4 colorAttr; varying vec4 vColor; void main(void) { gl_Position = vec4(positionAttr, 1.0); vColor = colorAttr; } Executed THREE times (because we have ONE triangle with THREE vertices)

Vertex Shader attribute vec3 positionAttr; attribute vec4 colorAttr; varying vec4 vColor; void main(void) { gl_Position = vec4(positionAttr, 1.0); vColor = colorAttr; } Input stream

Vertex Shader attribute vec3 positionAttr; attribute vec4 colorAttr; varying vec4 vColor; void main(void) { gl_Position = vec4(positionAttr, 1.0); vColor = colorAttr; } Output: passing down to fragment shader

Vertex Shader attribute vec3 positionAttr; attribute vec4 colorAttr; varying vec4 vColor; void main(void) { gl_Position = vec4(positionAttr, 1.0); vColor = colorAttr; } Final position of each vertex

Fragment Shader precision mediump float; varying vec4 vColor; void main(void) { gl_FragColor = vColor; } The value of vColor comes from three vertices, a weighted combination. Executed a dozen to tens of thousands of times, depending on the canvas size.

Fragment Shader precision mediump float; varying vec4 vColor; void main(void) { gl_FragColor = vColor; } Data from vertex shader

Fragment Shader precision mediump float; varying vec4 vColor; void main(void) { gl_FragColor = vColor; } Final color of each pixel

Vertex vs Fragment Shader - Where to compute the color? Teapot Per Vertex and Teaport Per Pixel

Vertex vs Fragment Shader - Where to compute the color? Teapot Per Vertex and Teaport Per Pixel

Shader Text The shader text for this sample is embedded in the web page using script elements. attribute vec3 positionAttr; attribute vec4 colorAttr;... precision mediump float; varying vec4 vColor;...

Initialize WebGL var gl; function initGL(canvas) { try { gl = canvas.getContext("experimental-webgl"); } catch (e) { } if (!gl) alert("Could not initialise WebGL, sorry :-("); } The type of context

Loading a Shader Create the shader object – vertex or fragment. Specify its source code. Compile it. Check whether compilation succeeded. Complete code follows. Some error checking elided.

function getShader(gl, id) { var script = document.getElementById(id); var shader; if (script.type == "x-shader/x-vertex") { shader = gl.createShader(gl.VERTEX_SHADER); } else if (script.type == "x-shader/x-fragment") { shader = gl.createShader(gl.FRAGMENT_SHADER); } gl.shaderSource(shader, script.text); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { alert(gl.getShaderInfoLog(shader)); return null; } return shader; }

function getShader(gl, id) { var script = document.getElementById(id); var shader; if (script.type == "x-shader/x-vertex") { shader = gl.createShader(gl.VERTEX_SHADER); } else if (script.type == "x-shader/x-fragment") { shader = gl.createShader(gl.FRAGMENT_SHADER); } gl.shaderSource(shader, script.text); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { alert(gl.getShaderInfoLog(shader)); return null; } return shader; } Create shader

function getShader(gl, id) { var script = document.getElementById(id); var shader; if (script.type == "x-shader/x-vertex") { shader = gl.createShader(gl.VERTEX_SHADER); } else if (script.type == "x-shader/x-fragment") { shader = gl.createShader(gl.FRAGMENT_SHADER); } gl.shaderSource(shader, script.text); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { alert(gl.getShaderInfoLog(shader)); return null; } return shader; } Upload shader source code

function getShader(gl, id) { var script = document.getElementById(id); var shader; if (script.type == "x-shader/x-vertex") { shader = gl.createShader(gl.VERTEX_SHADER); } else if (script.type == "x-shader/x-fragment") { shader = gl.createShader(gl.FRAGMENT_SHADER); } gl.shaderSource(shader, script.text); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { alert(gl.getShaderInfoLog(shader)); return null; } return shader; } Compile shader

function getShader(gl, id) { var script = document.getElementById(id); var shader; if (script.type == "x-shader/x-vertex") { shader = gl.createShader(gl.VERTEX_SHADER); } else if (script.type == "x-shader/x-fragment") { shader = gl.createShader(gl.FRAGMENT_SHADER); } gl.shaderSource(shader, script.text); gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { alert(gl.getShaderInfoLog(shader)); return null; } return shader; } Check compile status

Loading the Shader Program A program object combines the vertex and fragment shaders. Load each shader separately. Attach each to the program. Link the program. Check whether linking succeeded. Prepare vertex attributes for later assignment. Complete code follows.

var program; function initShaders() { program = gl.createProgram(); var vertexShader = getShader(gl, "shader-vs"); gl.attachShader(program, vertexShader); var fragmentShader = getShader(gl, "shader-fs"); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) alert("Could not initialise shaders"); gl.useProgram(program); program.positionAttr = gl.getAttribLocation(program, "positionAttr"); gl.enableVertexAttribArray(program.positionAttr); program.colorAttr = gl.getAttribLocation(program, "colorAttr"); gl.enableVertexAttribArray(program.colorAttr); }

var program; function initShaders() { program = gl.createProgram(); var vertexShader = getShader(gl, "shader-vs"); gl.attachShader(program, vertexShader); var fragmentShader = getShader(gl, "shader-fs"); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) alert("Could not initialise shaders"); gl.useProgram(program); program.positionAttr = gl.getAttribLocation(program, "positionAttr"); gl.enableVertexAttribArray(program.positionAttr); program.colorAttr = gl.getAttribLocation(program, "colorAttr"); gl.enableVertexAttribArray(program.colorAttr); } Create program

var program; function initShaders() { program = gl.createProgram(); var vertexShader = getShader(gl, "shader-vs"); gl.attachShader(program, vertexShader); var fragmentShader = getShader(gl, "shader-fs"); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) alert("Could not initialise shaders"); gl.useProgram(program); program.positionAttr = gl.getAttribLocation(program, "positionAttr"); gl.enableVertexAttribArray(program.positionAttr); program.colorAttr = gl.getAttribLocation(program, "colorAttr"); gl.enableVertexAttribArray(program.colorAttr); } Attach vertex shader

var program; function initShaders() { program = gl.createProgram(); var vertexShader = getShader(gl, "shader-vs"); gl.attachShader(program, vertexShader); var fragmentShader = getShader(gl, "shader-fs"); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) alert("Could not initialise shaders"); gl.useProgram(program); program.positionAttr = gl.getAttribLocation(program, "positionAttr"); gl.enableVertexAttribArray(program.positionAttr); program.colorAttr = gl.getAttribLocation(program, "colorAttr"); gl.enableVertexAttribArray(program.colorAttr); } Attach fragment shader

var program; function initShaders() { program = gl.createProgram(); var vertexShader = getShader(gl, "shader-vs"); gl.attachShader(program, vertexShader); var fragmentShader = getShader(gl, "shader-fs"); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) alert("Could not initialise shaders"); gl.useProgram(program); program.positionAttr = gl.getAttribLocation(program, "positionAttr"); gl.enableVertexAttribArray(program.positionAttr); program.colorAttr = gl.getAttribLocation(program, "colorAttr"); gl.enableVertexAttribArray(program.colorAttr); } Link program and check link status

var program; function initShaders() { program = gl.createProgram(); var vertexShader = getShader(gl, "shader-vs"); gl.attachShader(program, vertexShader); var fragmentShader = getShader(gl, "shader-fs"); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) alert("Could not initialise shaders"); gl.useProgram(program); program.positionAttr = gl.getAttribLocation(program, "positionAttr"); gl.enableVertexAttribArray(program.positionAttr); program.colorAttr = gl.getAttribLocation(program, "colorAttr"); gl.enableVertexAttribArray(program.colorAttr); } Tell GPU to use this program

var program; function initShaders() { program = gl.createProgram(); var vertexShader = getShader(gl, "shader-vs"); gl.attachShader(program, vertexShader); var fragmentShader = getShader(gl, "shader-fs"); gl.attachShader(program, fragmentShader); gl.linkProgram(program); if (!gl.getProgramParameter(program, gl.LINK_STATUS)) alert("Could not initialise shaders"); gl.useProgram(program); program.positionAttr = gl.getAttribLocation(program, "positionAttr"); gl.enableVertexAttribArray(program.positionAttr); program.colorAttr = gl.getAttribLocation(program, "colorAttr"); gl.enableVertexAttribArray(program.colorAttr); } Prepare vertex attributes for later use.

Setting Up Geometry Allocate buffer object on the GPU. Upload geometric data containing all vertex streams. Many options: interleaved vs. non-interleaved data, using multiple buffer objects, etc. Generally, want to use as few buffer objects as possible. Switching is expensive.

var buffer; function initGeometry() { buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); // Interleave vertex positions and colors var vertexData = [ // Vertex 1 position 0.0, 0.8, 0.0, // Vertex 1 Color 1.0, 0.0, 0.0, 1.0, // Vertex 2 position -0.8, -0.8, 0.0, // Vertex 2 color 0.0, 1.0, 0.0, 1.0, // Vertex 3 position 0.8, -0.8, 0.0, // Vertex 3 color 0.0, 0.0, 1.0, 1.0 ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData), gl.STATIC_DRAW); }

var buffer; function initGeometry() { buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); // Interleave vertex positions and colors var vertexData = [ // Vertex 1 position 0.0, 0.8, 0.0, // Vertex 1 Color 1.0, 0.0, 0.0, 1.0, // Vertex 2 position -0.8, -0.8, 0.0, // Vertex 2 color 0.0, 1.0, 0.0, 1.0, // Vertex 3 position 0.8, -0.8, 0.0, // Vertex 3 color 0.0, 0.0, 1.0, 1.0 ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData), gl.STATIC_DRAW); } Create a buffer and make it the current buffer for future operation

var buffer; function initGeometry() { buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); // Interleave vertex positions and colors var vertexData = [ // Vertex 1 position 0.0, 0.8, 0.0, // Vertex 1 Color 1.0, 0.0, 0.0, 1.0, // Vertex 2 position -0.8, -0.8, 0.0, // Vertex 2 color 0.0, 1.0, 0.0, 1.0, // Vertex 3 position 0.8, -0.8, 0.0, // Vertex 3 color 0.0, 0.0, 1.0, 1.0 ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData), gl.STATIC_DRAW); }

var buffer; function initGeometry() { buffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); // Interleave vertex positions and colors var vertexData = [ // Vertex 1 position 0.0, 0.8, 0.0, // Vertex 1 Color 1.0, 0.0, 0.0, 1.0, // Vertex 2 position -0.8, -0.8, 0.0, // Vertex 2 color 0.0, 1.0, 0.0, 1.0, // Vertex 3 position 0.8, -0.8, 0.0, // Vertex 3 color 0.0, 0.0, 1.0, 1.0 ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData), gl.STATIC_DRAW); } Upload data to the buffer on GPU

Draw the Scene Clear the viewing area. Set up vertex attribute streams. Issue the draw call.

function drawScene() { gl.viewport(0, 0, canvas.width, canvas.height); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); // There are 7 floating-point values per vertex var stride = 7 * Float32Array.BYTES_PER_ELEMENT; // Set up position stream gl.vertexAttribPointer(program.positionAttr, 3, gl.FLOAT, false, stride, 0); // Set up color stream gl.vertexAttribPointer(program.colorAttr, 4, gl.FLOAT, false, stride, 3 * Float32Array.BYTES_PER_ELEMENT); gl.drawArrays(gl.TRIANGLES, 0, 3); }

function drawScene() { gl.viewport(0, 0, canvas.width, canvas.height); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); // There are 7 floating-point values per vertex var stride = 7 * Float32Array.BYTES_PER_ELEMENT; // Set up position stream gl.vertexAttribPointer(program.positionAttr, 3, gl.FLOAT, false, stride, 0); // Set up color stream gl.vertexAttribPointer(program.colorAttr, 4, gl.FLOAT, false, stride, 3 * Float32Array.BYTES_PER_ELEMENT); gl.drawArrays(gl.TRIANGLES, 0, 3); } Set up a region to draw

function drawScene() { gl.viewport(0, 0, canvas.width, canvas.height); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); // There are 7 floating-point values per vertex var stride = 7 * Float32Array.BYTES_PER_ELEMENT; // Set up position stream gl.vertexAttribPointer(program.positionAttr, 3, gl.FLOAT, false, stride, 0); // Set up color stream gl.vertexAttribPointer(program.colorAttr, 4, gl.FLOAT, false, stride, 3 * Float32Array.BYTES_PER_ELEMENT); gl.drawArrays(gl.TRIANGLES, 0, 3); }

function drawScene() { gl.viewport(0, 0, canvas.width, canvas.height); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); // There are 7 floating-point values per vertex var stride = 7 * Float32Array.BYTES_PER_ELEMENT; // Set up position stream gl.vertexAttribPointer(program.positionAttr, 3, gl.FLOAT, false, stride, 0); // Set up color stream gl.vertexAttribPointer(program.colorAttr, 4, gl.FLOAT, false, stride, 3 * Float32Array.BYTES_PER_ELEMENT); gl.drawArrays(gl.TRIANGLES, 0, 3); } Draw one triangle

Achieving High Performance OpenGL "big rules" are to minimize: – Draw calls – Buffer, texture, and program binds – Uniform variable changes – State switches (enabling/disabling) WebGL "big rule": – Offload as much JavaScript to the GPU as possible

Picking in Google Body Highly detailed 3D model – over a MILLION triangles Selection is very fast (Thanks to Body team for this information)

Picking in Google Body Through Ray Tracing Could consider doing ray-casting in JavaScript – Attempt to do quick discards if ray doesn't intersect bounding box Still a lot of math to do in JavaScript

Picking in Google Body Through GPU When model is loaded, assign different color to each organ Upon mouse click: – Render body offscreen with different set of shaders – Use threshold to determine whether to draw translucent layers – Read back color of pixel under mouse pointer Same technique works at different levels of granularity

Particle Systems Particle demo from WebGL wiki – author: – Animates ~2000 particles at 60 FPS Does all the animation math on the GPU

Particle Systems: Implementation Each particle's motion is defined by a set of parameters Set up motion parameters when particle is created – Initial position, velocity, acceleration, spin Send down one parameter each frame: time Vertex shader evaluates equation of motion, moves particle Absolute minimum amount of JavaScript work done per frame

Physical Simulation Store the state of a physical simulation on the GPU Any iterative computation where each step relies only on nearby neighbors is a good candidate for moving to GPU Floating point textures: through WebGL extensions Several examples (waves, interference patterns): –

Non Photo-realistic Rendering Toon Shading demo: – It is as simple as color mapping in fragment shader: Regular rendering: Compute color; Gl_FragColor = color; NPR: Compute color; if (color.intensity > threashold) gl_FragColor = brighterColor; else gl_FragColor = darjerColor;

Resources: libraries Many libraries already exist to make it easier to use WebGL. A list (not comprehensive): – A few suggestions: – TDL (Aquarium, etc.) – Three.js ( mr. doob's demos) – CubicVR (Mozilla's WebGL demos like No Comply) – CopperLicht (same developer as Irrlicht) – PhiloGL (focus on data visualization) – SpiderGL (lots of interesting visual effects) – GLGE (used for early prototypes of Google Body) – SceneJS (Interesting declarative syntax)

Resources: talks and demos Gregg Tavares' Google I/O 2011 talk on WebGL Techniques and Performance – techniques-and-performance.html Giles Thomas' WebGL blog – Mozilla's WebGL articles – WebGL Chrome Experiments –

Resources: wiki and mailing list WebGL wiki – Public WebGL mailing list (spec discussion only) – WebGL Developers' List –

Resources: the WEB Go to any WebGL application Tools -> View Source

Q & A Thank You!