<meta charset="utf-8">
<script id="shader-vs" type="x-shader/x-vertex">
// Vertex shader implemented to perform lighting according to the
// Phong reflection model. Forwards texture coordinates to fragment
// shader.
attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aTextureCoordinates;
uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform mat3 uNMatrix;
uniform vec3 uLightPosition;
uniform vec3 uAmbientLightColor;
uniform vec3 uDiffuseLightColor;
uniform vec3 uSpecularLightColor;
varying vec2 vTextureCoordinates;
varying vec3 vLightWeighting;
const float shininess = 32.0;
void main() {
// Get the vertex position in eye coordinates
vec4 vertexPositionEye4 = uMVMatrix \* vec4(aVertexPosition, 1.0);
vec3 vertexPositionEye3 = vertexPositionEye4.xyz / vertexPositionEye4.w;
// Calculate the vector (l) to the light source
vec3 vectorToLightSource = normalize(uLightPosition - vertexPositionEye3);
// Transform the normal (n) to eye coordinates
vec3 normalEye = normalize(uNMatrix \* aVertexNormal);
// Calculate n dot l for diffuse lighting
float diffuseLightWeightning = max(dot(normalEye,
vectorToLightSource), 0.0);
// Calculate the reflection vector (r) that is needed for specular light
vec3 reflectionVector = normalize(reflect(-vectorToLightSource,
normalEye));
// The camera in eye coordinates is located in the origin and is pointing
// along the negative z-axis. Calculate viewVector (v) in eye coordinates as:
// (0.0, 0.0, 0.0) - vertexPositionEye3
vec3 viewVectorEye = -normalize(vertexPositionEye3);
float rdotv = max(dot(reflectionVector, viewVectorEye), 0.0);
float specularLightWeightning = pow(rdotv, shininess);
// Sum up all three reflection components and send to the fragment shader
vLightWeighting = uAmbientLightColor +
uDiffuseLightColor \* diffuseLightWeightning +
uSpecularLightColor \* specularLightWeightning;
// Finally transform the geometry
gl\_Position = uPMatrix \* uMVMatrix \* vec4(aVertexPosition, 1.0);
vTextureCoordinates = aTextureCoordinates;
}
</script>
<!--片元着色器-->
<script id="shader-fs" type="x-shader/x-fragment">
precision mediump float;
varying vec2 vTextureCoordinates;
varying vec3 vLightWeighting;
uniform sampler2D uSampler;
void main() {
vec4 texelColor = texture2D(uSampler, vTextureCoordinates);
//结合了纹理和光照的片段着色器(vLightWeighting包含已经计算得到的环境光和漫反射光)
gl\_FragColor = vec4(vLightWeighting.rgb \* texelColor.rgb, texelColor.a);
}
</script>
<script type="text/javascript">
// globals
var gl;
var pwgl = {};
// Keep track of ongoing image loads to be able to handle lost context
pwgl.**ongoingImageLoads** \= \[\];
var canvas;
function createGLContext(canvas) {
var names = \["webgl", "experimental-webgl"\];
var context = null;
for (var i=0; i < names.**length**; i++) {
try {
context = canvas.**getContext**(names\[i\]);
} catch(e) {}
if (context) {
break;
}
}
if (context) {
context.**viewportWidth** \= canvas.**width**;
context.**viewportHeight** \= canvas.**height**;
} else {
alert("Failed to create WebGL context!");
}
return context;
}
function loadShaderFromDOM(id) {
var shaderScript = **document**.getElementById(id);
// If we don't find an element with the specified id
// we do an early exit
if (!shaderScript) {
return null;
}
// Loop through the children for the found DOM element and
// build up the shader source code as a string
var shaderSource = "";
var currentChild = shaderScript.**firstChild**;
while (currentChild) {
if (currentChild.**nodeType** \== 3) { // 3 corresponds to TEXT\_NODE
shaderSource += currentChild.**textContent**;
}
currentChild = currentChild.**nextSibling**;
}
var shader;
if (shaderScript.**type** \== "x-shader/x-fragment") {
shader = gl.**createShader**(gl.**FRAGMENT\_SHADER**);
} else if (shaderScript.**type** \== "x-shader/x-vertex") {
shader = gl.**createShader**(gl.**VERTEX\_SHADER**);
} else {
return null;
}
gl.shaderSource(shader, shaderSource);
gl.compileShader(shader);
if (!gl.**getShaderParameter**(shader, gl.**COMPILE\_STATUS**) &&
!gl.isContextLost()) {
alert(gl.getShaderInfoLog(shader));
return null;
}
return shader;
}
function setupShaders() {
var vertexShader = loadShaderFromDOM("shader-vs");
var fragmentShader = loadShaderFromDOM("shader-fs");
var shaderProgram = gl.createProgram();
gl.attachShader(shaderProgram, vertexShader);
gl.attachShader(shaderProgram, fragmentShader);
gl.linkProgram(shaderProgram);
if (!gl.**getProgramParameter**(shaderProgram, gl.**LINK\_STATUS**) &&
!gl.isContextLost()) {
alert("Failed to link shaders: " + gl.getProgramInfoLog(shaderProgram));
}
gl.useProgram(shaderProgram);
pwgl.**vertexPositionAttributeLoc** \=
gl.**getAttribLocation**(shaderProgram, "aVertexPosition");
pwgl.**vertexNormalAttributeLoc** \=
gl.**getAttribLocation**(shaderProgram, "aVertexNormal");
pwgl.**vertexTextureAttributeLoc** \=
gl.**getAttribLocation**(shaderProgram, "aTextureCoordinates");
pwgl.**uniformMVMatrixLoc** \=
gl.getUniformLocation(shaderProgram, "uMVMatrix");
pwgl.**uniformProjMatrixLoc** \=
gl.getUniformLocation(shaderProgram, "uPMatrix");
pwgl.**uniformNormalMatrixLoc** \=
gl.getUniformLocation(shaderProgram, "uNMatrix");
pwgl.**uniformSamplerLoc** \=
gl.getUniformLocation(shaderProgram, "uSampler");
pwgl.**uniformLightPositionLoc** \=
gl.getUniformLocation(shaderProgram, "uLightPosition");
pwgl.**uniformAmbientLightColorLoc** \=
gl.getUniformLocation(shaderProgram, "uAmbientLightColor");
pwgl.**uniformDiffuseLightColorLoc** \=
gl.getUniformLocation(shaderProgram, "uDiffuseLightColor");
pwgl.**uniformSpecularLightColorLoc** \=
gl.getUniformLocation(shaderProgram, "uSpecularLightColor");
gl.enableVertexAttribArray(pwgl.**vertexPositionAttributeLoc**);
gl.enableVertexAttribArray(pwgl.**vertexNormalAttributeLoc**);
gl.enableVertexAttribArray(pwgl.**vertexTextureAttributeLoc**);
pwgl.**modelViewMatrix** \= mat4.create();
pwgl.**projectionMatrix** \= mat4.create();
pwgl.**modelViewMatrixStack** \= \[\];
}
function pushModelViewMatrix() {
var copyToPush = mat4.create(pwgl.**modelViewMatrix**);
pwgl.**modelViewMatrixStack**.push(copyToPush);
}
function popModelViewMatrix() {
if (pwgl.**modelViewMatrixStack**.**length** \== 0) {
throw "Error popModelViewMatrix() - Stack was empty ";
}
pwgl.**modelViewMatrix** \= pwgl.**modelViewMatrixStack**.pop();
}
function setupFloorBuffers() {
pwgl.**floorVertexPositionBuffer** \= gl.createBuffer();
gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**floorVertexPositionBuffer**);
var floorVertexPosition = \[
// Plane in y=0
5.0, 0.0, 5.0, //v0
5.0, 0.0, -5.0, //v1
-5.0, 0.0, -5.0, //v2
-5.0, 0.0, 5.0\]; //v3
gl.**bufferData**(gl.**ARRAY\_BUFFER**, new Float32Array(floorVertexPosition),
gl.**STATIC\_DRAW**);
pwgl.**FLOOR\_VERTEX\_POS\_BUF\_ITEM\_SIZE** \= 3;
pwgl.**FLOOR\_VERTEX\_POS\_BUF\_NUM\_ITEMS** \= 4;
//指定地板的法向量的方向
// Specify normals to be able to do lighting calculations
pwgl.**floorVertexNormalBuffer** \= gl.createBuffer();
gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**floorVertexNormalBuffer**);
var floorVertexNormals = \[
0.0, 1.0, 0.0, //v0
0.0, 1.0, 0.0, //v1
0.0, 1.0, 0.0, //v2
0.0, 1.0, 0.0\]; //v3
gl.**bufferData**(gl.**ARRAY\_BUFFER**, new Float32Array(floorVertexNormals),
gl.**STATIC\_DRAW**);
pwgl.**FLOOR\_VERTEX\_NORMAL\_BUF\_ITEM\_SIZE** \= 3;
pwgl.**FLOOR\_VERTEX\_NORMAL\_BUF\_NUM\_ITEMS** \= 4;
// Setup texture coordinates buffer
pwgl.**floorVertexTextureCoordinateBuffer** \= gl.createBuffer();
gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**floorVertexTextureCoordinateBuffer**);
var floorVertexTextureCoordinates = \[
2.0, 0.0,
2.0, 2.0,
0.0, 2.0,
0.0, 0.0
\];
gl.**bufferData**(gl.**ARRAY\_BUFFER**, new Float32Array(floorVertexTextureCoordinates),
gl.**STATIC\_DRAW**);
pwgl.**FLOOR\_VERTEX\_TEX\_COORD\_BUF\_ITEM\_SIZE** \= 2;
pwgl.**FLOOR\_VERTEX\_TEX\_COORD\_BUF\_NUM\_ITEMS** \= 4;
// Setup index buffer
pwgl.**floorVertexIndexBuffer** \= gl.createBuffer();
gl.**bindBuffer**(gl.**ELEMENT\_ARRAY\_BUFFER**, pwgl.**floorVertexIndexBuffer**);
var floorVertexIndices = \[0, 1, 2, 3\];
gl.**bufferData**(gl.**ELEMENT\_ARRAY\_BUFFER**, new Uint16Array(floorVertexIndices),
gl.**STATIC\_DRAW**);
pwgl.**FLOOR\_VERTEX\_INDEX\_BUF\_ITEM\_SIZE** \= 1;
pwgl.**FLOOR\_VERTEX\_INDEX\_BUF\_NUM\_ITEMS** \= 4;
}
function setupCubeBuffers() {
pwgl.**cubeVertexPositionBuffer** \= gl.createBuffer();
gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**cubeVertexPositionBuffer**);
var cubeVertexPosition = \[
// Front face
1.0, 1.0, 1.0, //v0
-1.0, 1.0, 1.0, //v1
-1.0, -1.0, 1.0, //v2
1.0, -1.0, 1.0, //v3
// Back face
1.0, 1.0, -1.0, //v4
-1.0, 1.0, -1.0, //v5
-1.0, -1.0, -1.0, //v6
1.0, -1.0, -1.0, //v7
// Left face
-1.0, 1.0, 1.0, //v8
-1.0, 1.0, -1.0, //v9
-1.0, -1.0, -1.0, //v10
-1.0, -1.0, 1.0, //v11
// Right face
1.0, 1.0, 1.0, //12
1.0, -1.0, 1.0, //13
1.0, -1.0, -1.0, //14
1.0, 1.0, -1.0, //15
// Top face
1.0, 1.0, 1.0, //v16
1.0, 1.0, -1.0, //v17
-1.0, 1.0, -1.0, //v18
-1.0, 1.0, 1.0, //v19
// Bottom face
1.0, -1.0, 1.0, //v20
1.0, -1.0, -1.0, //v21
-1.0, -1.0, -1.0, //v22
-1.0, -1.0, 1.0, //v23
\];
gl.**bufferData**(gl.**ARRAY\_BUFFER**, new Float32Array(cubeVertexPosition),
gl.**STATIC\_DRAW**);
pwgl.**CUBE\_VERTEX\_POS\_BUF\_ITEM\_SIZE** \= 3;
pwgl.**CUBE\_VERTEX\_POS\_BUF\_NUM\_ITEMS** \= 24;
// Specify normals to be able to do lighting calculations
pwgl.**cubeVertexNormalBuffer** \= gl.createBuffer();
gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**cubeVertexNormalBuffer**);
//指定立方体的每一个面的法向量
var cubeVertexNormals = \[
// Front face
0.0, 0.0, 1.0, //v0
0.0, 0.0, 1.0, //v1
0.0, 0.0, 1.0, //v2
0.0, 0.0, 1.0, //v3
// Back face
0.0, 0.0, -1.0, //v4
0.0, 0.0, -1.0, //v5
0.0, 0.0, -1.0, //v6
0.0, 0.0, -1.0, //v7
// Left face
-1.0, 0.0, 0.0, //v8
-1.0, 0.0, 0.0, //v9
-1.0, 0.0, 0.0, //v10
-1.0, 0.0, 0.0, //v11
// Right face
1.0, 0.0, 0.0, //12
1.0, 0.0, 0.0, //13
1.0, 0.0, 0.0, //14
1.0, 0.0, 0.0, //15
// Top face
0.0, 1.0, 0.0, //v16
0.0, 1.0, 0.0, //v17
0.0, 1.0, 0.0, //v18
0.0, 1.0, 0.0, //v19
// Bottom face
0.0, -1.0, 0.0, //v20
0.0, -1.0, 0.0, //v21
0.0, -1.0, 0.0, //v22
0.0, -1.0, 0.0, //v23
\];
gl.**bufferData**(gl.**ARRAY\_BUFFER**, new Float32Array(cubeVertexNormals),
gl.**STATIC\_DRAW**);
pwgl.**CUBE\_VERTEX\_NORMAL\_BUF\_ITEM\_SIZE** \= 3;
pwgl.**CUBE\_VERTEX\_NORMAL\_BUF\_NUM\_ITEMS** \= 24;
// Setup buffer with texture coordinates
pwgl.**cubeVertexTextureCoordinateBuffer** \= gl.createBuffer();
gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**cubeVertexTextureCoordinateBuffer**);
var textureCoordinates = \[
//Front face
0.0, 0.0, //v0
1.0, 0.0, //v1
1.0, 1.0, //v2
0.0, 1.0, //v3
// Back face
0.0, 1.0, //v4
1.0, 1.0, //v5
1.0, 0.0, //v6
0.0, 0.0, //v7
// Left face
0.0, 1.0, //v8
1.0, 1.0, //v9
1.0, 0.0, //v10
0.0, 0.0, //v11
// Right face
0.0, 1.0, //v12
1.0, 1.0, //v13
1.0, 0.0, //v14
0.0, 0.0, //v15
// Top face
0.0, 1.0, //v16
1.0, 1.0, //v17
1.0, 0.0, //v18
0.0, 0.0, //v19
// Bottom face
0.0, 1.0, //v20
1.0, 1.0, //v21
1.0, 0.0, //v22
0.0, 0.0, //v23
\];
gl.**bufferData**(gl.**ARRAY\_BUFFER**, new Float32Array(textureCoordinates),gl.**STATIC\_DRAW**);
pwgl.**CUBE\_VERTEX\_TEX\_COORD\_BUF\_ITEM\_SIZE** \= 2;
pwgl.**CUBE\_VERTEX\_TEX\_COORD\_BUF\_NUM\_ITEMS** \= 24;
pwgl.**cubeVertexIndexBuffer** \= gl.createBuffer();
gl.**bindBuffer**(gl.**ELEMENT\_ARRAY\_BUFFER**, pwgl.**cubeVertexIndexBuffer**);
var cubeVertexIndices = \[
0, 1, 2, 0, 2, 3, // Front face
4, 6, 5, 4, 7, 6, // Back face
8, 9, 10, 8, 10, 11, // Left face
12, 13, 14, 12, 14, 15, // Right face
16, 17, 18, 16, 18, 19, // Top face
20, 22, 21, 20, 23, 22 // Bottom face
\];
gl.**bufferData**(gl.**ELEMENT\_ARRAY\_BUFFER**, new Uint16Array(cubeVertexIndices),
gl.**STATIC\_DRAW**);
pwgl.**CUBE\_VERTEX\_INDEX\_BUF\_ITEM\_SIZE** \= 1;
pwgl.**CUBE\_VERTEX\_INDEX\_BUF\_NUM\_ITEMS** \= 36;
}
function textureFinishedLoading(image, texture) {
gl.**bindTexture**(gl.**TEXTURE\_2D**, texture);
gl.**pixelStorei**(gl.**UNPACK\_FLIP\_Y\_WEBGL**, true);
gl.**texImage2D**(gl.**TEXTURE\_2D**, 0, gl.**RGBA**, gl.**RGBA**, gl.**UNSIGNED\_BYTE**,
image);
gl.**generateMipmap**(gl.**TEXTURE\_2D**);
gl.**texParameteri**(gl.**TEXTURE\_2D**, gl.**TEXTURE\_MAG\_FILTER**, gl.**LINEAR**);
gl.**texParameteri**(gl.**TEXTURE\_2D**, gl.**TEXTURE\_MIN\_FILTER**, gl.**LINEAR**);
gl.**texParameteri**(gl.**TEXTURE\_2D**, gl.**TEXTURE\_WRAP\_S**, gl.**MIRRORED\_REPEAT**);
gl.**texParameteri**(gl.**TEXTURE\_2D**, gl.**TEXTURE\_WRAP\_T**, gl.**MIRRORED\_REPEAT**);
gl.**bindTexture**(gl.**TEXTURE\_2D**, null);
}
function loadImageForTexture(url, texture) {
var image = new **Image**();
image.**onload** \= function() {
pwgl.**ongoingImageLoads**.splice(pwgl.**ongoingImageLoads**.indexOf(image), 1);
textureFinishedLoading(image, texture);
}
pwgl.**ongoingImageLoads**.push(image);
image.**src** \= url;
}
function setupTextures() {
// Texture for the table
pwgl.**woodTexture** \= gl.createTexture();
loadImageForTexture("./resources/wood\_128x128.jpg", pwgl.**woodTexture**);
// Texture for the floor
pwgl.**groundTexture** \= gl.createTexture();
loadImageForTexture("./resources/wood\_floor\_256.jpg", pwgl.**groundTexture**);
// Texture for the box on the table
pwgl.**boxTexture** \= gl.createTexture();
loadImageForTexture("./resources/wicker\_256.jpg", pwgl.**boxTexture**);
//创建一个立方体
pwgl.**colorCube** \= gl.createTexture();
loadImageForTexture("./resources/xiuxiuba.bmp", pwgl.**colorCube**);
}
function setupBuffers() {
setupFloorBuffers();
setupCubeBuffers();
}
//设置光源位置,环境光颜色,漫反射光颜色,镜面反射光
function setupLights() {
gl.uniform3fv(pwgl.**uniformLightPositionLoc**, \[0.0, 20.0, 0.0\]);
gl.uniform3fv(pwgl.**uniformAmbientLightColorLoc**, \[0.2, 0.2, 0.2\]);
gl.uniform3fv(pwgl.**uniformDiffuseLightColorLoc**, \[0.7, 0.7, 0.7\]);
gl.uniform3fv(pwgl.**uniformSpecularLightColorLoc**, \[0.8, 0.8, 0.8\]);
}
function uploadModelViewMatrixToShader() {
gl.uniformMatrix4fv(pwgl.**uniformMVMatrixLoc**, false, pwgl.**modelViewMatrix**);
}
function uploadProjectionMatrixToShader() {
gl.uniformMatrix4fv(pwgl.**uniformProjMatrixLoc**,
false, pwgl.**projectionMatrix**);
}
//上传法向量的矩阵到着色器
function uploadNormalMatrixToShader() {
var normalMatrix = mat3.create();
//计算矩阵的逆
mat4.toInverseMat3(pwgl.**modelViewMatrix**, normalMatrix);
//计算转置矩阵
mat3.transpose(normalMatrix);
//把法向量矩阵传给着色器
gl.uniformMatrix3fv(pwgl.**uniformNormalMatrixLoc**, false, normalMatrix);
}
function drawFloor() {
// Bind position buffer
gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**floorVertexPositionBuffer**);
gl.**vertexAttribPointer**(pwgl.**vertexPositionAttributeLoc**,
pwgl.**FLOOR\_VERTEX\_POS\_BUF\_ITEM\_SIZE**,
gl.**FLOAT**, false, 0, 0);
// Bind normal buffer
gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**floorVertexNormalBuffer**);
gl.**vertexAttribPointer**(pwgl.**vertexNormalAttributeLoc**,
pwgl.**FLOOR\_VERTEX\_NORMAL\_BUF\_ITEM\_SIZE**,
gl.**FLOAT**, false, 0, 0);
// Bind texture coordinate buffer
gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**floorVertexTextureCoordinateBuffer**);
gl.**vertexAttribPointer**(pwgl.**vertexTextureAttributeLoc**,
pwgl.**FLOOR\_VERTEX\_TEX\_COORD\_BUF\_ITEM\_SIZE**,
gl.**FLOAT**, false, 0, 0);
gl.**activeTexture**(gl.**TEXTURE0**);
gl.**bindTexture**(gl.**TEXTURE\_2D**, pwgl.**groundTexture**);
// Bind index buffer and draw the floor
gl.**bindBuffer**(gl.**ELEMENT\_ARRAY\_BUFFER**, pwgl.**floorVertexIndexBuffer**);
gl.**drawElements**(gl.**TRIANGLE\_FAN**, pwgl.**FLOOR\_VERTEX\_INDEX\_BUF\_NUM\_ITEMS**,
gl.**UNSIGNED\_SHORT**, 0);
}
function drawCube(texture) {
// Bind position buffer
gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**cubeVertexPositionBuffer**);
gl.**vertexAttribPointer**(pwgl.**vertexPositionAttributeLoc**,
pwgl.**CUBE\_VERTEX\_POS\_BUF\_ITEM\_SIZE**,
gl.**FLOAT**, false, 0, 0);
// Bind normal buffer
gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**cubeVertexNormalBuffer**);
gl.**vertexAttribPointer**(pwgl.**vertexNormalAttributeLoc**,
pwgl.**CUBE\_VERTEX\_NORMAL\_BUF\_ITEM\_SIZE**,
gl.**FLOAT**, false, 0, 0);
// Bind texture coordinate buffer
gl.**bindBuffer**(gl.**ARRAY\_BUFFER**, pwgl.**cubeVertexTextureCoordinateBuffer**);
gl.**vertexAttribPointer**(pwgl.**vertexTextureAttributeLoc**,
pwgl.**CUBE\_VERTEX\_TEX\_COORD\_BUF\_ITEM\_SIZE**,
gl.**FLOAT**, false, 0, 0);
gl.**activeTexture**(gl.**TEXTURE0**);
gl.**bindTexture**(gl.**TEXTURE\_2D**, texture);
// Bind index buffer and draw cube
gl.**bindBuffer**(gl.**ELEMENT\_ARRAY\_BUFFER**, pwgl.**cubeVertexIndexBuffer**);
gl.**drawElements**(gl.**TRIANGLES**, pwgl.**CUBE\_VERTEX\_INDEX\_BUF\_NUM\_ITEMS**,
gl.**UNSIGNED\_SHORT**, 0);
}
function drawTable(){
// Draw a simple table by modifying the modelview matrix
// (translate and scale) and then use the function drawCube()
// to draw a table top and four table legs.
pushModelViewMatrix();
mat4.translate(pwgl.**modelViewMatrix**, \[0.0, 1.0, 0.0\], pwgl.**modelViewMatrix**);
mat4.scale(pwgl.**modelViewMatrix**, \[2.0, 0.1, 2.0\], pwgl.**modelViewMatrix**);
uploadModelViewMatrixToShader();
uploadNormalMatrixToShader();
// Draw the actual cube (now scaled to a cuboid) with woodTexture
drawCube(pwgl.**woodTexture**);
popModelViewMatrix();
// Draw the table legs
for (var i=-1; i<=1; i+=2) {
for (var j= -1; j<=1; j+=2) {
pushModelViewMatrix();
mat4.translate(pwgl.**modelViewMatrix**, \[i\*1.9, -0.1, j\*1.9\], pwgl.**modelViewMatrix**);
mat4.scale(pwgl.**modelViewMatrix**, \[0.1, 1.0, 0.1\], pwgl.**modelViewMatrix**);
uploadModelViewMatrixToShader();
uploadNormalMatrixToShader();
drawCube(pwgl.**woodTexture**);
popModelViewMatrix();
}
}
}
//var currentAngle;
function draw(currentTime) {
pwgl.**requestId** \= **requestAnimFrame**(draw);
if (currentTime === **undefined**) {
currentTime = Date.now();
}
currentTime = Date.now();
// Update FPS if a second or more has passed since last FPS update
if(currentTime - pwgl.**previousFrameTimeStamp** \>= 1000) {
pwgl.**fpsCounter**.**innerHTML** \= pwgl.**nbrOfFramesForFPS**;
pwgl.**nbrOfFramesForFPS** \= 0;
pwgl.**previousFrameTimeStamp** \= currentTime;
}
gl.viewport(0, 0, gl.**viewportWidth**, gl.**viewportHeight**);
gl.clear(gl.**COLOR\_BUFFER\_BIT** | gl.**DEPTH\_BUFFER\_BIT**);
mat4.perspective(60, gl.**viewportWidth** / gl.**viewportHeight**,
1, 100.0, pwgl.**projectionMatrix**);
mat4.identity(pwgl.**modelViewMatrix**);
mat4.lookAt(\[8, 12, 8\],\[0, 0, 0\], \[0, 1,0\], pwgl.**modelViewMatrix**);
mat4.rotateY(pwgl.**modelViewMatrix**, pwgl.**yRot**, pwgl.**modelViewMatrix**);
//旋转
pwgl.**yRot** += 0.01;
//鼠标移动
mat4.rotateX(pwgl.**modelViewMatrix**, pwgl.**currentAngle**\[0\], pwgl.**modelViewMatrix**);
mat4.rotateY(pwgl.**modelViewMatrix**, pwgl.**currentAngle**\[1\], pwgl.**modelViewMatrix**);
//鼠标滚轮
mat4.translate(pwgl.**modelViewMatrix**, \[0, 0, pwgl.**zTri**\], pwgl.**modelViewMatrix**);
uploadModelViewMatrixToShader();
uploadProjectionMatrixToShader();
uploadNormalMatrixToShader();
gl.uniform1i(pwgl.**uniformSamplerLoc**, 0);
drawFloor();
// Draw table
pushModelViewMatrix();
mat4.translate(pwgl.**modelViewMatrix**, \[0.0, 1.1, 0.0\], pwgl.**modelViewMatrix**);
uploadModelViewMatrixToShader();
uploadNormalMatrixToShader();
drawTable();
popModelViewMatrix();
// Calculate the position for the box that is initially
// on top of the table but will then be moved during animation
pushModelViewMatrix();
if (currentTime === **undefined**) {
currentTime = Date.now();
}
if (pwgl.**animationStartTime** \=== **undefined**) {
pwgl.**animationStartTime** \= currentTime;
}
// Update the position of the box
if (pwgl.**y** < 5) {
// First move the box vertically from its original position on top of
// the table (where y = 2.7) to 5 units above the floor (y = 5).
// Let this movement take 3 seconds
pwgl.**y** \= 2.7 + (currentTime - pwgl.**animationStartTime**)/3000 \* (5.0-2.7);
}
else {
// Then move the box in a circle where one revolution takes 2 seconds
pwgl.**angle** \= (currentTime - pwgl.**animationStartTime**)/2000\*2\*Math.**PI** % (2\*Math.**PI**);
pwgl.**x** \= Math.cos(pwgl.**angle**) \* pwgl.**circleRadius**;
pwgl.**z** \= Math.sin(pwgl.**angle**) \* pwgl.**circleRadius**;
}
mat4.translate(pwgl.**modelViewMatrix**, \[pwgl.**x**, pwgl.**y**, pwgl.**z**\], pwgl.**modelViewMatrix**);
mat4.scale(pwgl.**modelViewMatrix**, \[0.5, 0.5, 0.5\], pwgl.**modelViewMatrix**);
uploadModelViewMatrixToShader();
uploadNormalMatrixToShader();
drawCube(pwgl.**boxTexture**);
popModelViewMatrix();
// Update number of drawn frames to be able to count fps
pwgl.**nbrOfFramesForFPS**++;
}
function handleContextLost(event) {
event.preventDefault();
**cancelRequestAnimFrame**(pwgl.**requestId**);
// Ignore all ongoing image loads by removing
// their onload handler
for (var i = 0; i < pwgl.**ongoingImageLoads**.**length**; i++) {
pwgl.**ongoingImageLoads**\[i\].**onload** \= **undefined**;
}
pwgl.**ongoingImageLoads** \= \[\];
}
function init() {
// Initialization that is performed during first startup, but when the
// event webglcontextrestored is received is included in this function.
setupShaders();
setupBuffers();
setupLights();
setupTextures();
gl.clearColor(0.0, 0.0, 0.0, 1.0);
gl.**enable**(gl.**DEPTH\_TEST**);
// Initialize some varibles for the moving box
pwgl.**x** \= 0.0;
pwgl.**y** \= 2.7;
pwgl.**z** \= 0.0;
pwgl.**circleRadius** \= 4.0;
pwgl.**angle** \= 0;
//Y轴旋转角度
pwgl.**yRot** \= 0;
//Z轴移动角度
pwgl.**zTri** \= 0;
// Initialize some variables related to the animation
pwgl.**animationStartTime** \= **undefined**;
pwgl.**nbrOfFramesForFPS** \= 0;
pwgl.**previousFrameTimeStamp** \= Date.now();
}
function handleContextRestored(event) {
init();
pwgl.**requestId** \= **requestAnimFrame**(draw,canvas);
}
//处理鼠标的事件
var dragging = false; // Dragging or not
var lastX = -1, lastY = -1; // Last position of the mouse
function handleMouseDown(ev) {
var x = ev.**clientX**, y = ev.**clientY**;
// Start dragging if a moue is in <canvas>
var rect = ev.**target**.getBoundingClientRect();
if (rect.**left** <= x && x < rect.**right** && rect.**top** <= y && y < rect.**bottom**) {
lastX = x; lastY = y;
dragging = true;
}
}
function handleMouseMove(ev) {
var x = ev.**clientX**, y = ev.**clientY**;
if (dragging) {
var factor = 100/canvas.**height**; // The rotation ratio
var dx = factor \* (x - lastX);
var dy = factor \* (y - lastY);
// Limit x-axis rotation angle to -90 to 90 degrees
pwgl.**currentAngle**\[0\] = Math.max(Math.min(pwgl.**currentAngle**\[0\] + dy, 90.0), -90.0);
pwgl.**currentAngle**\[1\] = pwgl.**currentAngle**\[1\] + dx;
}
lastX = x, lastY = y;
}
function handleMouseUp() {
dragging = false;
}
/\*
\* 在非firefox浏览器中,滚轮向上滚动返回的数值是120,向下滚动返回-120
而在firefox浏览器中,滚轮向上滚动返回的数值是-3,向下滚动返回3
\* \*/
//鼠标滚轮
var scrollFunc = function (e) {
e = e || **window**.**event**;
var t1 = **document**.getElementById("wheelDelta");
var t2 = **document**.getElementById("detail");
if (e.**wheelDelta**) {//IE/Opera/Chrome
t1.**value** \= "IE、Opera、Safari、Chrome";
t2.**value** \= e.**wheelDelta**;
if (e.**wheelDelta** \== 120){
pwgl.**zTri** += 1.0;
} else {
pwgl.**zTri** \-= 1.0;
}
} else if (e.**detail**) {//Firefox
t1.**value** \= "Firefox";
t2.**value** \= e.**detail**;
if (e.**wheelDelta** \== -3){
pwgl.**zTri** += 1.0;
} else {
pwgl.**zTri** \-= 1.0;
}
}
//ScrollText(direct);
}
/\*注册事件\*/
if (**document**.addEventListener) {
**document**.addEventListener('DOMMouseScroll', scrollFunc, false);
}//W3C
**window**.**onmousewheel** \= **document**.onmousewheel = scrollFunc;//IE/Opera/Chrome/Safari
function startup() {
canvas = **document**.getElementById("myGLCanvas");
canvas = **WebGLDebugUtils**.makeLostContextSimulatingContext(canvas);
canvas.addEventListener('webglcontextlost', handleContextLost, false);
canvas.addEventListener('webglcontextrestored', handleContextRestored, false);
//canvas.addEventListener("", )
canvas.addEventListener('mousedown', handleMouseDown, false);
canvas.addEventListener('mousemove', handleMouseMove, false);
canvas.addEventListener('mouseup', handleMouseUp, false);
//canvas.addEventListener('onmousewheel', handlemosew)
gl = createGLContext(canvas);
init();
//注册一个事件响应的函数【鼠标移动控制】
pwgl.**currentAngle** \= \[0.0, 0.0\];
//initEventHandlers(canvas, currentAngle);
pwgl.**fpsCounter** \= **document**.getElementById("fps");
// Uncomment the three lines of code below to be able to test lost context
// window.addEventListener('mousedown', function() {
// canvas.loseContext();
// });
// Draw the complete scene
draw();
}
</script>
(IE/Opera)
手机扫一扫
移动阅读更方便
你可能感兴趣的文章