blob: ef2fd7925c22d42625f2b0a283626102ddc8c837 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<title>WebGL + CSS Effects</title>
<script src="resources/J3DI.js"> </script>
<script src="resources/J3DIMath.js" type="text/javascript"> </script>
<script id="vshader" type="x-shader/x-vertex">
/*
Copyright (c) 2008 Seneca College
Licenced under the MIT License (http://www.c3dl.org/index.php/mit-license/)
*/
// We need to create our own light structure since we can't access
// the light() function in the 2.0 context.
struct Light
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec4 position;
vec3 halfVector;
};
struct Material
{
vec4 emission;
vec4 ambient;
vec4 diffuse;
vec4 specular;
float shininess;
};
//
// vertex attributes
//
attribute vec4 a_vertex;
attribute vec3 a_normal;
attribute vec4 a_texCoord;
// for every model we multiply the projection, view and model matrices
// once to prevent having to do it for every vertex, however we still need
// the view matrix to calculate lighting.
uniform mat4 u_modelViewMatrix;
// we can calculate this once per model to speed up processing done on the js side.
uniform mat4 u_modelViewProjMatrix;
// matrix to transform the vertex normals
uniform mat4 u_normalMatrix;
// custom light structures need to be used since we don't have access to
// light states.
uniform Light u_light;
// material
uniform vec4 u_globalAmbientColor;
uniform Material u_frontMaterial;
uniform Material u_backMaterial;
// passed to fragment shader
varying vec4 v_diffuse, v_ambient;
varying vec3 v_normal, v_lightDir;
varying vec2 v_texCoord;
/*
Given a reference to the ambient and diffuse lighting variables,
this function will calculate how much each component contributes to the scene.
Light light - the light in view space
vec3 normal -
vec4 ambient -
vec4 diffuse -
*/
vec3 directionalLight(inout vec4 ambient, inout vec4 diffuse)
{
ambient += u_light.ambient;
diffuse += u_light.diffuse;
return normalize(vec3(u_light.position));
}
void main()
{
v_normal = normalize(u_normalMatrix * vec4(a_normal, 1)).xyz;
vec4 ambient = vec4(0.0, 0.0, 0.0, 1.0);
vec4 diffuse = vec4(0.0, 0.0, 0.0, 1.0);
vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
// place the current vertex into view space
// ecPos = eye coordinate position.
vec4 ecPos4 = u_modelViewMatrix * a_vertex;
// the current vertex in eye coordinate space
vec3 ecPos = ecPos4.xyz/ecPos4.w;
v_lightDir = directionalLight(ambient, diffuse);
v_ambient = u_frontMaterial.ambient * ambient;
v_ambient += u_globalAmbientColor * u_frontMaterial.ambient;
v_diffuse = u_frontMaterial.diffuse * diffuse;
gl_Position = u_modelViewProjMatrix * a_vertex;
v_texCoord = a_texCoord.st;
}
</script>
<script id="fshader" type="x-shader/x-fragment">
#ifdef GL_ES
precision mediump float;
#endif
struct Light
{
vec4 ambient;
vec4 diffuse;
vec4 specular;
vec4 position;
vec3 halfVector;
};
struct Material
{
vec4 emission;
vec4 ambient;
vec4 diffuse;
vec4 specular;
float shininess;
};
uniform sampler2D u_sampler2d;
uniform Light u_light;
uniform Material u_frontMaterial;
uniform Material u_backMaterial;
varying vec4 v_diffuse, v_ambient;
varying vec3 v_normal, v_lightDir;
varying vec2 v_texCoord;
void main()
{
vec4 color = v_diffuse;
vec3 n = normalize(v_normal);
Light light = u_light;
vec3 lightDir = v_lightDir;
float nDotL = max(dot(n, lightDir), 0.0);
if (nDotL > 0.0) {
color = vec4(color.rgb * nDotL, color.a);
float nDotHV = max(dot(n, light.halfVector), 0.0);
vec4 specular = u_frontMaterial.specular * light.specular;
color += vec4(specular.rgb * pow(nDotHV, u_frontMaterial.shininess), specular.a);
}
gl_FragColor = color + v_ambient;
}
</script>
<script>
function setDirectionalLight(ctx, program, eyeVector, direction, ambient, diffuse, specular)
{
var lightString = "u_light.";
ctx.uniform4f(ctx.getUniformLocation(program, lightString+"ambient"),
ambient[0], ambient[1], ambient[2], ambient[3]);
ctx.uniform4f(ctx.getUniformLocation(program, lightString+"diffuse"),
diffuse[0], diffuse[1], diffuse[2], diffuse[3]);
ctx.uniform4f(ctx.getUniformLocation(program, lightString+"specular"),
specular[0], specular[1], specular[2], specular[3]);
ctx.uniform4f(ctx.getUniformLocation(program, lightString+"position"),
direction[0], direction[1], direction[2], direction[3]);
// compute the half vector
var halfVector = [ eyeVector[0] + direction[0], eyeVector[1] + direction[1], eyeVector[2] + direction[2] ];
var length = Math.sqrt(halfVector[0] * halfVector[0] +
halfVector[1] * halfVector[1] +
halfVector[2] * halfVector[2]);
if (length == 0)
halfVector = [ 0, 0, 1 ];
else {
halfVector[0] /= length;
halfVector[1] /= length;
halfVector[2] /= length;
}
ctx.uniform3f(ctx.getUniformLocation(program, lightString+"halfVector"),
halfVector[0], halfVector[1], halfVector[2]);
}
function setMaterial(ctx, program, emission, ambient, diffuse, specular, shininess)
{
var matString = "u_frontMaterial.";
ctx.uniform4f(ctx.getUniformLocation(program, matString+"emission"),
emission[0], emission[1], emission[2], emission[3]);
ctx.uniform4f(ctx.getUniformLocation(program, matString+"ambient"),
ambient[0], ambient[1], ambient[2], ambient[3]);
ctx.uniform4f(ctx.getUniformLocation(program, matString+"diffuse"),
diffuse[0], diffuse[1], diffuse[2], diffuse[3]);
ctx.uniform4f(ctx.getUniformLocation(program, matString+"specular"),
specular[0], specular[1], specular[2], specular[3]);
ctx.uniform1f(ctx.getUniformLocation(program, matString+"shininess"), shininess);
}
function init()
{
var gl = initWebGL("example", "vshader", "fshader",
[ "a_normal", "a_texCoord", "a_vertex"],
[ 0, 0, 0, 0 ], 10000);
gl.uniform1i(gl.getUniformLocation(gl.program, "u_sampler2d"), 0);
gl.uniform4f(gl.getUniformLocation(gl.program, "u_globalAmbientColor"), 0.2, 0.2, 0.2, 1);
setDirectionalLight(gl, gl.program,
[ 0, 0, 1 ], // eyeVector
[0, 0, 1, 1], // position
[0.1, 0.1, 0.1, 1], // ambient
[1, 1, 1, 1], // diffuse
[1, 1, 1, 1]); // specular
setMaterial(gl, gl.program,
[ 0, 0, 0, 0 ], // emission
[ 0.1, 0.1, 0.1, 1 ], // ambient
[ 0.8, 0.2, 0, 1 ], // diffuse
[ 0, 0, 1, 1 ], // specular
32); // shininess
obj = loadObj(gl, "resources/teapot.obj");
mvMatrix = new J3DIMatrix4();
normalMatrix = new J3DIMatrix4();
return gl;
}
width = -1;
height = -1;
loaded = false;
function reshape(ctx)
{
var canvas = document.getElementById('example');
if (canvas.clientWidth == width && canvas.clientHeight == height)
return;
width = canvas.clientWidth;
height = canvas.clientHeight;
ctx.viewport(0, 0, width, height);
ctx.perspectiveMatrix = new J3DIMatrix4();
ctx.perspectiveMatrix.perspective(30, width/height, 1, 10000);
ctx.perspectiveMatrix.lookat(0,0,50, 0, 0, 0, 0, 1, 0);
}
function drawPicture(ctx)
{
var startRenderTime = new Date().getTime();
reshape(ctx);
ctx.clear(ctx.COLOR_BUFFER_BIT | ctx.DEPTH_BUFFER_BIT);
if (!loaded && obj.loaded) {
loaded = true;
ctx.enableVertexAttribArray(0);
ctx.enableVertexAttribArray(1);
ctx.enableVertexAttribArray(2);
ctx.bindBuffer(ctx.ARRAY_BUFFER, obj.vertexObject);
ctx.vertexAttribPointer(2, 3, ctx.FLOAT, false, 0, 0);
ctx.bindBuffer(ctx.ARRAY_BUFFER, obj.normalObject);
ctx.vertexAttribPointer(0, 3, ctx.FLOAT, false, 0, 0);
ctx.bindBuffer(ctx.ARRAY_BUFFER, obj.texCoordObject);
ctx.vertexAttribPointer(1, 2, ctx.FLOAT, false, 0, 0);
ctx.bindBuffer(ctx.ELEMENT_ARRAY_BUFFER, obj.indexObject);
}
if (!loaded)
return;
// generate the model-view matrix
mvMatrix.makeIdentity();
mvMatrix.rotate(10, 1,0,0);
mvMatrix.rotate(currentAngle, 0, 1, 0);
mvMatrix.setUniform(ctx, ctx.getUniformLocation(ctx.program, "u_modelViewMatrix"), false);
// construct the normal matrix from the model-view matrix
normalMatrix.load(mvMatrix);
normalMatrix.invert();
normalMatrix.transpose();
normalMatrix.setUniform(ctx, ctx.getUniformLocation(ctx.program, "u_normalMatrix"), false);
// Construct the model-view * projection matrix and pass it in
var mvpMatrix = new J3DIMatrix4();
mvpMatrix.load(ctx.perspectiveMatrix);
mvpMatrix.multiply(mvMatrix);
mvpMatrix.setUniform(ctx, ctx.getUniformLocation(ctx.program, "u_modelViewProjMatrix"), false);
ctx.drawElements(ctx.TRIANGLES, obj.numIndices, ctx.UNSIGNED_SHORT, 0);
ctx.flush();
framerate.snapshot();
currentAngle += incAngle;
if (currentAngle > 360)
currentAngle -= 360;
}
function start()
{
// set up event listener on the canvas
var canvas = document.getElementById('example');
var body = document.getElementById('body');
body.addEventListener('click', function () {
isTilted = !isTilted;
container.className = isTilted ? 'tilted' : '';
}, false);
body.addEventListener('touchstart', function () {
isTilted = !isTilted;
container.className = isTilted ? 'tilted' : '';
}, false);
var ctx = init();
currentAngle = 0;
incAngle = 0.2;
framerate = new Framerate("framerate");
var f = function() { drawPicture(ctx) };
setInterval(f, 10);
}
var isTilted = false;
</script>
<style type="text/css">
body {
background-color:grey;
}
#container {
-webkit-transform-origin:400px 300px;
-webkit-transform: perspective(800) translateX(0) rotateY(0) rotateZ(0) translateZ(-10px);
-webkit-transition: -webkit-transform 2s;
}
#container.tilted {
-webkit-transform: perspective(800) translateX(200px) rotateY(60deg) rotateZ(320deg) translateZ(-250px);
}
canvas {
width:800px;
height:600px;
}
#bg {
border:4px solid #242;
position:absolute;
width:800px;
height:600px;
}
#rocker {
position:absolute;
top:200px;
left:300px;
font-size:3em;
text-shadow: white 2px 2px 4px;
-webkit-animation:5s rock infinite alternate ease-in-out;
}
@-webkit-keyframes rock {
0% { -webkit-transform: translateX(-250px) rotate3d(0,0,1, -30deg) }
25% { -webkit-transform: translateX(-150px) rotate3d(0,0,1, 30deg) }
50% { -webkit-transform: translateX(-50px) rotate3d(0,0,1, -30deg) }
75% { -webkit-transform: translateX(50px) rotate3d(0,0,1, 30deg) }
100% { -webkit-transform: translateX(150px) rotate3d(0,0,1, -30deg) }
}
#framerate {
position:absolute;
top:10px;
margin:10px;
text-shadow: black 2px 2px 4px;
font-size:2em;
font-family:helvetica;
color:white;
}
</style>
</head>
<body id="body" onload="start()">
<div id="rocker">WebGL Rocks!</div>
<div id="framerate"></div>
<div id="container">
<img id="bg" src="resources/BambooBridge.jpg" />
<canvas id="example" width="800px" height="600px">
There is supposed to be an example drawing here, but it's not important.
</canvas>
</div>
</body>
</html>