HTML和JS代码已经贴出,其依赖代码文件Common
以及相关资料均请在此处下载
或者请移步我的CSDN仓库
先赞后看,养成习惯!
任务一
给目标增加顶点(20-30个之间),创建一个更复杂的图形
- 1、在 vertics 中,增加点的坐标
vec4( x, y, z, 1.0 )
-
2、在colorCube函数中将四个点连成一个面
-
3、修改numPositions
任务二
计算重心,并可以绕重心和三个轴旋转
我的策略是,我的图形默认是质量分布均匀的,那么重心就是所有坐标的平均值,计算出来是 ( 0 , 0 , 3 28 ) (0, 0, \frac{3}{28}) (0,0,283),然后我把所有坐标减去这个平均值,就相当于把整个物体往下挪了 3 28 \frac{3}{28} 283,这样重心就和坐标原点重合了,就很容易实现绕重心和三个轴旋转
绕重心旋转我是加个一个用鼠标控制其任意旋转的代码
任务三
添加一个 viewer position,一个perspective projection,然后计算ModelView and Projection matrices,要求初始时物体要在viewing volume里面,并加按钮或滑块可以随意控制它和viewer position
主要就是ModelView matrix使用 l o o k A t ( e y e , a t u p ) lookAt(eye, at up) lookAt(eye,atup)函数实现,其中 e y e eye eye又由 radius,theta,phi控制
然后Projection matrices由 p e r s p e c t i v e ( f o v y , c a n v a s . w i d t h / c a n v a s . h e i g h t , n e a r , f a r ) perspective(fovy, canvas.width/canvas.height, near, far) perspective(fovy,canvas.width/canvas.height,near,far)控制
最后用控件控制这几个变量就可以了~
任务四
添加一个用三角形近似的圆柱体来模拟霓虹灯,放三个光源在里面,并加个开关
使用cylinder函数绘制出圆柱体,把其vertices,normals,TextureCoordinates和原来的图形concat起来。
然后加三个光源,将light position坐标放在圆柱的内部。。,关灯时直接设置 f C o l o r = v e c 4 ( 0 , 0 , 0 , 0 ) fColor=vec4(0, 0, 0, 0) fColor=vec4(0,0,0,0)黑色即可
任务五
分配材料属性
这个就简单的修改下 m a t e r i a l A m b i e n t , m a t e r i a l D i f f u s e , m a t e r i a l S p e c u l a r materialAmbient, materialDiffuse, materialSpecular materialAmbient,materialDiffuse,materialSpecular的颜色值就行
任务六
实现per-vertex和per-fragment shading model,并加个控件来回切换
per-vertex是一开始就实现了的,请看任务五的图片光照
per-fragment这个实现效果如下,他俩差不多的,不过per-fragment显得更真实些,具体请看代码
任务七
增加凹凸纹理,并设计个按钮来回切换
-
1、计算出normals,然后用configureTexture绘制纹理
-
2、在quad函数中给每个vertice添加texture coordinate array
-
3、传递texCoordsArray到html
-
4、vertex-shader和fragment-shader中计算 fColor
HTML 完整实现代码
<!DOCTYPE html>
<html>
<body>
<div style="text-align:center;">
<canvas id="gl-canvas" width="512" height="512"></canvas>
<hr>
<div>
<i>Task-2</i>
<br>
<button id="ButtonStart">Start</button>
<button id="ButtonStop">Stop</button>
<br>
<button id="ButtonX">Rotate X</button>
<button id="ButtonY">Rotate Y</button>
<button id="ButtonZ">Rotate Z</button>
<br>
<button id="ButtonRotation">Rotation Around Barycenter Using Mouse</button>
</div>
<hr>
<div>
<i>Task-3</i>
<h3 id="info3">Activate Perjection Viewer</h3>
<button id="SwitchV">Switch</button>
</div>
<br>
<div>
Radius 1<input id="radius" type="range" min="1" max="6" step="1" value="2" />6
</div>
<button id="Button0">Increase Theta</button>
<button id="Button1">Decrease Theta</button>
<br>
<button id="Button2">Increase Phi</button>
<button id="Button3">Decrease Phi</button>
<br>
<button id="Button4">Near</button>
<button id="Button5">Far</button>
<div>
Fovy 1<input id="fovy" type="range" min="1" max="120" step="1" value="100" />120
</div>
<hr>
<div>
<i>Task-4</i>
<h3 id="info4">Switch Light</h3>
NB: Please turn on the light before using other buttons
<br>
<button id="SwitchL">Switch</button>
</div>
<hr>
<div>
<i>Task-6</i>
<h3 id="info6">Per-Vertex</h3>
<button id="SwitchP">Switch</button>
</div>
<hr>
<div>
<i>Task-7</i>
<h3 id="info7">Activate Bump Texture</h3>
<button id="SwitchT">Switch</button>
</div>
</div>
<script id="vertex-shader" type="x-shader/x-vertex">
#version 300 es
in vec4 aPosition;
in vec3 aNormal;
out vec4 vColor;
uniform bool uRotationFlag;
uniform mat4 uRotationMatrix;
uniform vec4 uAmbientProduct, uDiffuseProduct, uSpecularProduct;
uniform vec4 umaterialEmission;
uniform mat4 uModelViewMatrix;
uniform mat4 uProjectionMatrix;
uniform vec4 uLightPosition;
uniform float uShininess;
in vec2 aTexCoord;
out vec2 vTexCoord;
out vec3 Lt;
uniform vec4 uNormal;
uniform bool uTextureFlag;
uniform vec3 uObjTangent;
uniform mat3 uNormalMatrix;
uniform bool uPerFlag;
out vec3 vN, vL, vE;
void main()
{
if(uPerFlag){
vec3 pos = -(uModelViewMatrix * aPosition).xyz;
//fixed light postion
vec3 light = uLightPosition.xyz;
vec3 L = normalize(light - pos);
vec3 E = normalize(-pos);
vec3 H = normalize(L + E);
vec4 NN = vec4(aNormal,0);
// Transform vertex normal into eye coordinates
vec3 N = normalize((uModelViewMatrix*NN).xyz);
// Compute terms in the illumination equation
vec4 ambient = uAmbientProduct;
float Kd = max(dot(L, N), 0.0);
vec4 diffuse = Kd*uDiffuseProduct;
float Ks = pow( max(dot(N, H), 0.0), uShininess );
vec4 specular = Ks * uSpecularProduct;
if( dot(L, N) < 0.0 ) {
specular = vec4(0.0, 0.0, 0.0, 1.0);
}
if(uRotationFlag){
gl_Position = uProjectionMatrix * uModelViewMatrix * uRotationMatrix * aPosition;
}
else{
gl_Position = uProjectionMatrix * uModelViewMatrix * aPosition;
}
vColor = ambient + diffuse +specular;// + umaterialEmission;
vColor.a = 1.0;
}
else{
vec3 pos = -(uModelViewMatrix * aPosition).xyz;
vec3 light = uLightPosition.xyz;
vL = normalize( light - pos );
vE = -pos;
vN = normalize( (uModelViewMatrix*vec4(aNormal,0)).xyz);
if(uRotationFlag){
gl_Position = uProjectionMatrix * uModelViewMatrix * uRotationMatrix * aPosition;
}
else{
gl_Position = uProjectionMatrix * uModelViewMatrix * aPosition;
}
}
//Task-7
if(uTextureFlag){
vec3 eyePosition = (uModelViewMatrix*aPosition).xyz;
vec3 eyeLightPos = (uModelViewMatrix*uLightPosition).xyz;
vec3 N = normalize(uNormalMatrix*uNormal.xyz);
vec3 T = normalize(uNormalMatrix*uObjTangent);
vec3 B = cross(N, T);
Lt.x = dot(T, eyeLightPos-eyePosition);
Lt.y = dot(B, eyeLightPos-eyePosition);
Lt.z = dot(N, eyeLightPos-eyePosition);
Lt = normalize(Lt);
vTexCoord = aTexCoord;
}
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
#version 300 es
precision mediump float;
in vec4 vColor;
out vec4 fColor;
uniform bool uLightFlag;
in vec3 Lt;
uniform bool uTextureFlag;
in vec2 vTexCoord;
uniform sampler2D uTexMap;
uniform vec4 uDiffuseProducttex;
uniform bool uPerFlag;
uniform vec4 uAmbientProduct6, uDiffuseProduct6, uSpecularProduct6;
uniform float uShininess6;
in vec3 vN, vL, vE;
void
main()
{
//Task-7
vec4 N = texture(uTexMap, vTexCoord);
vec3 NN = normalize(2.0*N.xyz-1.0);
vec3 LL = normalize(Lt);
float Kd7 = max(dot(NN, LL), 0.0);
if(uPerFlag){
if(uTextureFlag){
fColor = vColor * vec4(Kd7*uDiffuseProducttex.xyz, 1.0);}
else{fColor = vColor;}
}
else{
vec3 H = normalize( vL + vE );
vec4 ambient = uAmbientProduct6;
float Kd = max( dot(vL, vN), 0.0 );
vec4 diffuse = Kd * uDiffuseProduct6;
float Ks = pow( max(dot(vN, H), 0.0), uShininess6 );
vec4 specular = Ks * uSpecularProduct6;
if( dot(vL, vN) < 0.0 ) specular = vec4(0.0, 0.0, 0.0, 1.0);
if(uTextureFlag){
fColor = (ambient + diffuse +specular)*vec4(Kd7*uDiffuseProducttex.xyz, 1.0);}
else{fColor = ambient + diffuse +specular;}
fColor.a = 1.0;
}
if(uLightFlag){
fColor = vec4( 0.0, 0.0, 0.0, 1.0 );;
}
}
</script>
<script src="../Common/initShaders.js"></script>
<script src="../Common/MVnew.js"></script>
<script src="Homework1.js"></script>
</body>
</html>
JavaScript 完整实现代码
"use strict";
var shadedCube = function() {
var canvas;
var gl;
var positionsArray = [];
var normalsArray = [];
//-----------------------------------------------------------------------------------------------------------------------
//Task-4
var lightPosition = vec4(0.71, 0.77, 0.11, 1.0);
var lightAmbient = vec4(0.2, 0.2, 0.2, 1.0);
var lightDiffuse = vec4(1.0, 1.0, 1.0, 1.0);
var lightSpecular = vec4(1.0, 1.0, 1.0, 1.0);
var lightAmbient2 = vec4(0.2, 0.2, 0.2, 1.0);
var lightDiffuse2 = vec4(1.0, 1.0, 1.0, 1.0);
var lightSpecular2 = vec4(1.0, 1.0, 1.0, 1.0);
var lightAmbient3 = vec4(0.2, 0.2, 0.2, 1.0);
var lightDiffuse3 = vec4(1.0, 1.0, 1.0, 1.0);
var lightSpecular3 = vec4(1.0, 1.0, 1.0, 1.0);
//-----------------------------------------------------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
//Task-5
var materialAmbient = vec4(1.0, 0.3, 0.0, 1.0);
var materialDiffuse = vec4(1.0, 0.8, 0.1, 1.0);
var materialSpecular = vec4(1.0, 0.7, 0.0, 1.0);
var materialEmission = vec4(0.0, 0.3, 0.3, 1.0); //Task-4
var materialShininess = 80.0;
//-----------------------------------------------------------------------------------------------------------------------
var ctm;
var ambientColor, diffuseColor, specularColor;
var modelViewMatrix, projectionMatrix, nMatrix;
var viewerPos;
var program;
var xAxis = 0;
var yAxis = 1;
var zAxis = 2;
var axis = 0;
var theta = vec3(0, 0, 0);
var thetaLoc;
var flag = false;
//-------------------------------------------------------
// Task-1
var numPositions = 156;
var vertices = [
vec4( -0.5, -0.5, 0.5-4*0.75/28, 1.0 ), // 0
vec4( -0.5, 0.5, 0.5-4*0.75/28, 1.0 ), // 1
vec4( 0.5, 0.5, 0.5-4*0.75/28, 1.0 ), // 2
vec4( 0.5, -0.5, 0.5-4*0.75/28, 1.0 ), // 3
vec4( -0.5, -0.5, -0.5-4*0.75/28, 1.0 ), // 4
vec4( -0.5, 0.5, -0.5-4*0.75/28, 1.0 ), // 5
vec4( 0.5, 0.5, -0.5-4*0.75/28, 1.0 ), // 6
vec4( 0.5, -0.5, -0.5-4*0.75/28, 1.0 ), // 7
vec4(-0.25, -0.25, 0.75-4*0.75/28, 1.0), // 8
vec4(-0.25, 0.25, 0.75-4*0.75/28, 1.0), // 9
vec4(0.25, 0.25, 0.75-4*0.75/28, 1.0), // 10
vec4(0.25, -0.25, 0.75-4*0.75/28, 1.0), // 11
vec4(-0.25, 0.75, 0.25-4*0.75/28, 1.0), // 12
vec4(0.25, 0.75, 0.25-4*0.75/28, 1.0), // 13
vec4(-0.25, 0.75, -0.25-4*0.75/28, 1.0), // 14
vec4(0.25, 0.75, -0.25-4*0.75/28, 1.0), // 15
vec4(-0.25, -0.75, 0.25-4*0.75/28, 1.0), // 16
vec4(0.25, -0.75, 0.25-4*0.75/28, 1.0), // 17
vec4(-0.25, -0.75, -0.25-4*0.75/28, 1.0),// 18
vec4(0.25, -0.75, -0.25-4*0.75/28, 1.0), // 19
vec4(-0.75, 0.25, 0.25-4*0.75/28, 1.0), // 20
vec4(-0.75, -0.25, 0.25-4*0.75/28, 1.0), // 21
vec4(-0.75, 0.25, -0.25-4*0.75/28, 1.0), // 22
vec4(-0.75, -0.25, -0.25-4*0.75/28, 1.0),// 23
vec4(0.75, 0.25, 0.25-4*0.75/28, 1.0), // 24
vec4(0.75, -0.25, 0.25-4*0.75/28, 1.0), // 25
vec4(0.75, 0.25, -0.25-4*0.75/28, 1.0), // 26
vec4(0.75, -0.25, -0.25-4*0.75/28, 1.0), // 27
];
//-------------------------------------------------------
//-----------------------------------------------------------------------------------------------------------------------
//Task-2
var RotationFlag = false;
var rotationMatrix= mat4();
var rotationMatrixLoc;
var angle = 0.0;
var axis2 = vec3(0, 0, 1);
var trackingMouse = false;
var trackballMove = false;
var lastPos = [0, 0, 0];
var curx, cury;
var startX, startY;
function trackballView( x, y ) {
var d, a;
var v = [];
v[0] = x;
v[1] = y;
d = v[0]*v[0] + v[1]*v[1];
if (d < 1.0)
v[2] = Math.sqrt(1.0 - d);
else {
v[2] = 0.0;
a = 1.0 / Math.sqrt(d);
v[0] *= a;
v[1] *= a;
}
return v;
}
function mouseMotion( x, y)
{
var dx, dy, dz;
var curPos = trackballView(x, y);
if(trackingMouse) {
dx = curPos[0] - lastPos[0];
dy = curPos[1] - lastPos[1];
dz = curPos[2] - lastPos[2];
if (dx || dy || dz) {
angle = -0.1 * Math.sqrt(dx*dx + dy*dy + dz*dz);
axis2[0] = lastPos[1]*curPos[2] - lastPos[2]*curPos[1];
axis2[1] = lastPos[2]*curPos[0] - lastPos[0]*curPos[2];
axis2[2] = lastPos[0]*curPos[1] - lastPos[1]*curPos[0];
lastPos[0] = curPos[0];
lastPos[1] = curPos[1];
lastPos[2] = curPos[2];
}
}
render();
}
function startMotion( x, y)
{
trackingMouse = true;
startX = x;
startY = y;
curx = x;
cury = y;
lastPos = trackballView(x, y);
trackballMove=true;
}
function stopMotion( x, y)
{
trackingMouse = false;
if (startX != x || startY != y) {
}
else {
angle = 0.0;
trackballMove = false;
}
}
//-----------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------
//Task-3
var viewerFlag = true;
var fovy = 100.0;
var near = 0.3;
var far = 3.0;
var radius = 3.0;
var thetav = 0.0;
var phi = 0.0;
const at = vec3(0.0, 0.0, 0.0);
const up = vec3(0.0, 1.0, 0.0);
var dr = 5.0 * Math.PI/180.0;
//-------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------------
//Task-4
var ncylinder;
var lightFlag = false;
function cylinder(numSlices, numStacks, caps) {
var slices = 36;
if(numSlices) slices = numSlices;
var stacks = 1;
if(numStacks) stacks = numStacks;
var capsFlag = true;
if(caps==false) capsFlag = caps;
var data = {};
var top = 0.5;
var bottom = -0.5;
var radius = 0.5;
var topCenter = [0.0, top, 0.0];
var bottomCenter = [0.0, bottom, 0.0];
var sideColor = [1.0, 0.0, 0.0, 1.0];
var topColor = [0.0, 1.0, 0.0, 1.0];
var bottomColor = [0.0, 0.0, 1.0, 1.0];
var cylinderVertexCoordinates = [];
var cylinderNormals = [];
var cylinderVertexColors = [];
var cylinderTextureCoordinates = [];
// side
for(var j=0; j<stacks; j++) {
var stop = bottom + (j+1)*(top-bottom)/stacks;
var sbottom = bottom + j*(top-bottom)/stacks;
var topPoints = [];
var bottomPoints = [];
var topST = [];
var bottomST = [];
for(var i =0; i<slices; i++) {
var theta = 2.0*i*Math.PI/slices;
topPoints.push([radius*Math.sin(theta), stop, radius*Math.cos(theta), 1.0]);
bottomPoints.push([radius*Math.sin(theta), sbottom, radius*Math.cos(theta), 1.0]);
};
topPoints.push([0.0, stop, radius, 1.0]);
bottomPoints.push([0.0, sbottom, radius, 1.0]);
for(var i=0; i<slices; i++) {
var a = topPoints[i];
var d = topPoints[i+1];
var b = bottomPoints[i];
var c = bottomPoints[i+1];
var u = [b[0]-a[0], b[1]-a[1], b[2]-a[2]];
var v = [c[0]-b[0], c[1]-b[1], c[2]-b[2]];
var normal = [
u[1]*v[2] - u[2]*v[1],
u[2]*v[0] - u[0]*v[2],
u[0]*v[1] - u[1]*v[0]
];
var mag = Math.sqrt(normal[0]*normal[0] + normal[1]*normal[1] + normal[2]*normal[2])
normal = [normal[0]/mag, normal[1]/mag, normal[2]/mag];
cylinderVertexCoordinates.push([a[0], a[1], a[2], 1.0]);
cylinderVertexColors.push(sideColor);
cylinderNormals.push([normal[0], normal[1], normal[2]]);
cylinderTextureCoordinates.push([(i+1)/slices, j*(top-bottom)/stacks]);
cylinderVertexCoordinates.push([b[0], b[1], b[2], 1.0]);
cylinderVertexColors.push(sideColor);
cylinderNormals.push([normal[0], normal[1], normal[2]]);
cylinderTextureCoordinates.push([i/slices, (j-1)*(top-bottom)/stacks]);
cylinderVertexCoordinates.push([c[0], c[1], c[2], 1.0]);
cylinderVertexColors.push(sideColor);
cylinderNormals.push([normal[0], normal[1], normal[2]]);
cylinderTextureCoordinates.push([(i+1)/slices, (j-1)*(top-bottom)/stacks]);
cylinderVertexCoordinates.push([a[0], a[1], a[2], 1.0]);
cylinderVertexColors.push(sideColor);
cylinderNormals.push([normal[0], normal[1], normal[2]]);
cylinderTextureCoordinates.push([(i+1)/slices, j*(top-bottom)/stacks]);
cylinderVertexCoordinates.push([c[0], c[1], c[2], 1.0]);
cylinderVertexColors.push(sideColor);
cylinderNormals.push([normal[0], normal[1], normal[2]]);
cylinderTextureCoordinates.push([(i+1)/slices, (j-1)*(top-bottom)/stacks]);
cylinderVertexCoordinates.push([d[0], d[1], d[2], 1.0]);
cylinderVertexColors.push(sideColor);
cylinderNormals.push([normal[0], normal[1], normal[2]]);
cylinderTextureCoordinates.push([(i+1)/slices, j*(top-bottom)/stacks]);
};
};
var topPoints = [];
var bottomPoints = [];
for(var i =0; i<slices; i++) {
var theta = 2.0*i*Math.PI/slices;
topPoints.push([radius*Math.sin(theta), top, radius*Math.cos(theta), 1.0]);
bottomPoints.push([radius*Math.sin(theta), bottom, radius*Math.cos(theta), 1.0]);
};
topPoints.push([0.0, top, radius, 1.0]);
bottomPoints.push([0.0, bottom, radius, 1.0]);
if(capsFlag) {
//top
for(i=0; i<slices; i++) {
normal = [0.0, 1.0, 0.0];
var a = [0.0, top, 0.0, 1.0];
var b = topPoints[i];
var c = topPoints[i+1];
cylinderVertexCoordinates.push([a[0], a[1], a[2], 1.0]);
cylinderVertexColors.push(topColor);
cylinderNormals.push(normal);
cylinderTextureCoordinates.push([0, 1]);
cylinderVertexCoordinates.push([b[0], b[1], b[2], 1.0]);
cylinderVertexColors.push(topColor);
cylinderNormals.push(normal);
cylinderTextureCoordinates.push([0, 1]);
cylinderVertexCoordinates.push([c[0], c[1], c[2], 1.0]);
cylinderVertexColors.push(topColor);
cylinderNormals.push(normal);
cylinderTextureCoordinates.push([0, 1]);
};
//bottom
for(i=0; i<slices; i++) {
normal = [0.0, -1.0, 0.0];
var a = [0.0, bottom, 0.0, 1.0];
var b = bottomPoints[i];
var c = bottomPoints[i+1];
cylinderVertexCoordinates.push([a[0], a[1], a[2], 1.0]);
cylinderVertexColors.push(bottomColor);
cylinderNormals.push(normal);
cylinderTextureCoordinates.push([0, 1]);
cylinderVertexCoordinates.push([b[0], b[1], b[2], 1.0]);
cylinderVertexColors.push(bottomColor);
cylinderNormals.push(normal);
cylinderTextureCoordinates.push([0, 1]);
cylinderVertexCoordinates.push([c[0], c[1], c[2], 1.0]);
cylinderVertexColors.push(bottomColor);
cylinderNormals.push(normal);
cylinderTextureCoordinates.push([0, 1]);
};
};
function translate(x, y, z){
for(var i=0; i<cylinderVertexCoordinates.length; i++) {
cylinderVertexCoordinates[i][0] += x;
cylinderVertexCoordinates[i][1] += y;
cylinderVertexCoordinates[i][2] += z;
};
}
function scale(sx, sy, sz){
for(var i=0; i<cylinderVertexCoordinates.length; i++) {
cylinderVertexCoordinates[i][0] *= sx;
cylinderVertexCoordinates[i][1] *= sy;
cylinderVertexCoordinates[i][2] *= sz;
cylinderNormals[i][0] /= sx;
cylinderNormals[i][1] /= sy;
cylinderNormals[i][2] /= sz;
};
}
function radians( degrees ) {
return degrees * Math.PI / 180.0;
}
function rotate( angle, axis) {
var d = Math.sqrt(axis[0]*axis[0] + axis[1]*axis[1] + axis[2]*axis[2]);
var x = axis[0]/d;
var y = axis[1]/d;
var z = axis[2]/d;
var c = Math.cos( radians(angle) );
var omc = 1.0 - c;
var s = Math.sin( radians(angle) );
var mat = [
[ x*x*omc + c, x*y*omc - z*s, x*z*omc + y*s ],
[ x*y*omc + z*s, y*y*omc + c, y*z*omc - x*s ],
[ x*z*omc - y*s, y*z*omc + x*s, z*z*omc + c ]
];
for(var i=0; i<cylinderVertexCoordinates.length; i++) {
var u = [0, 0, 0];
var v = [0, 0, 0];
for( var j =0; j<3; j++)
for( var k =0 ; k<3; k++) {
u[j] += mat[j][k]*cylinderVertexCoordinates[i][k];
v[j] += mat[j][k]*cylinderNormals[i][k];
};
for( var j =0; j<3; j++) {
cylinderVertexCoordinates[i][j] = u[j];
cylinderNormals[i][j] = v[j];
};
};
}
data.TriangleVertices = cylinderVertexCoordinates;
data.TriangleNormals = cylinderNormals;
data.TriangleVertexColors = cylinderVertexColors;
data.TextureCoordinates = cylinderTextureCoordinates;
data.rotate = rotate;
data.translate = translate;
data.scale = scale;
return data;
}
//----------------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------
//Task-6
var perFlag = true;
//-------------------------------------------------------
//-------------------------------------------------------
//Task-7
var texSize = 256/2;
var texCoordsArray = [];
var data = new Array()
for (var i = 0; i<= texSize; i++) data[i] = new Array();
for (var i = 0; i<= texSize; i++) for (var j=0; j<=texSize; j++)
data[i][j] = 0.0;
for (var i = texSize/4; i<3*texSize/4; i++) for (var j = texSize/4; j<3*texSize/4; j++)
data[i][j] = 1.0;
var normalst = new Array()
for (var i=0; i<texSize; i++) normalst[i] = new Array();
for (var i=0; i<texSize; i++) for ( var j = 0; j < texSize; j++)
normalst[i][j] = new Array();
for (var i=0; i<texSize; i++) for ( var j = 0; j < texSize; j++) {
normalst[i][j][0] = data[i][j]-data[i+1][j];
normalst[i][j][1] = data[i][j]-data[i][j+1];
normalst[i][j][2] = 1;
}
for (var i=0; i<texSize; i++) for (var j=0; j<texSize; j++) {
var d = 0;
for(k=0;k<3;k++) d+=normalst[i][j][k]*normalst[i][j][k];
d = Math.sqrt(d);
for(k=0;k<3;k++) normalst[i][j][k]= 0.5*normalst[i][j][k]/d + 0.5;
}
var normals = new Uint8Array(3*texSize*texSize);
for ( var i = 0; i < texSize; i++ )
for ( var j = 0; j < texSize; j++ )
for(var k =0; k<3; k++)
normals[3*texSize*i+3*j+k] = 255*normalst[i][j][k];
var texCoord = [
vec2(0, 0),
vec2(0, 1),
vec2(1, 1),
vec2(1, 0)
];
function configureTexture( image ) {
var texture = gl.createTexture();
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, texSize, texSize, 0, gl.RGB, gl.UNSIGNED_BYTE, image);
gl.generateMipmap(gl.TEXTURE_2D);
}
var textureFlag = false; //Task-7
var normal = vec4(0.0, 1.0, 0.0, 0.0); //Task-7
var tangent = vec3(1.0, 0.0, 0.0); //Task-7
//-------------------------------------------------------
init();
function quad(a, b, c, d) {
var t1 = subtract(vertices[b], vertices[a]);
var t2 = subtract(vertices[c], vertices[b]);
var normal = cross(t1, t2);
normal = vec3(normal);
positionsArray.push(vertices[a]);
normalsArray.push(normal);
texCoordsArray.push(texCoord[0]);
positionsArray.push(vertices[b]);
normalsArray.push(normal);
texCoordsArray.push(texCoord[1]);
positionsArray.push(vertices[c]);
normalsArray.push(normal);
texCoordsArray.push(texCoord[2]);
positionsArray.push(vertices[a]);
normalsArray.push(normal);
texCoordsArray.push(texCoord[0]);
positionsArray.push(vertices[c]);
normalsArray.push(normal);
texCoordsArray.push(texCoord[2]);
positionsArray.push(vertices[d]);
normalsArray.push(normal);
texCoordsArray.push(texCoord[3]);
}
function colorCube()
{
//-------------------------------------------------------
// Task-1
quad( 8, 9, 10, 11 );
quad( 0, 1, 9, 8 );
quad( 9, 10, 2, 1 );
quad( 10, 11, 3, 2 );
quad( 11, 8, 0, 3);
quad( 14, 12, 13, 15 );
quad( 1, 12, 14, 5 );
quad( 1, 12, 13, 2 );
quad( 2, 13, 15, 6 );
quad( 5, 14, 15, 6 );
quad( 16, 17, 19, 18 );
quad( 0, 16, 18, 4 );
quad( 0, 16, 17, 3 );
quad( 3, 17, 19, 7 );
quad( 4, 18, 19, 7 );
quad( 20, 21, 23, 22 );
quad( 1, 20, 22, 5 );
quad( 1, 20, 21, 0 );
quad( 0, 21, 23, 4 );
quad( 5, 22, 23, 4 );
quad( 24, 25, 27, 26 );
quad( 2, 24, 25, 3 );
quad( 2, 24, 26, 6 );
quad( 3, 25, 27, 7 );
quad( 6, 26, 27, 7 );
quad( 4, 5, 6, 7 );
}
//-------------------------------------------------------
function init() {
canvas = document.getElementById("gl-canvas");
gl = canvas.getContext('webgl2');
if (!gl) alert( "WebGL 2.0 isn't available");
gl.viewport(0, 0, canvas.width, canvas.height);
gl.clearColor(1.0, 1.0, 1.0, 1.0);
gl.enable(gl.DEPTH_TEST);
//-------------------------------------------------------------------------------------
//Task-4
var myCylinder = cylinder(8, 1, true);
myCylinder.scale(0.2, 0.2, 0.2);
myCylinder.rotate(-45.0, [ 1, 1, 1]);
myCylinder.translate(0.8, 0.8, 0.0);
var points2 = myCylinder.TriangleVertices;
var normals2 = myCylinder.TriangleNormals;
var texCoord2 = myCylinder.TextureCoordinates;
ncylinder = myCylinder.TriangleVertices.length;
positionsArray = positionsArray.concat(points2);
normalsArray = normalsArray.concat(normals2);
texCoordsArray = texCoordsArray.concat(texCoord2);
//---------------------------------------------------------------------------------------
//
// Load shaders and initialize attribute buffers
//
program = initShaders(gl, "vertex-shader", "fragment-shader");
gl.useProgram(program);
colorCube();
var nBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, nBuffer);
gl.bufferData(gl.ARRAY_BUFFER, flatten(normalsArray), gl.STATIC_DRAW);
var normalLoc = gl.getAttribLocation(program, "aNormal");
gl.vertexAttribPointer(normalLoc, 3, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(normalLoc);
var vBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
gl.bufferData(gl.ARRAY_BUFFER, flatten(positionsArray), gl.STATIC_DRAW);
var positionLoc = gl.getAttribLocation(program, "aPosition");
gl.vertexAttribPointer(positionLoc, 4, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(positionLoc);
thetaLoc = gl.getUniformLocation(program, "theta");
//--------------------------------------------------------------------------------------
//Task-7
var tBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, tBuffer);
gl.bufferData(gl.ARRAY_BUFFER, flatten(texCoordsArray), gl.STATIC_DRAW);
var texCoordLoc = gl.getAttribLocation(program, "aTexCoord");
gl.vertexAttribPointer(texCoordLoc, 2, gl.FLOAT, false, 0, 0);
gl.enableVertexAttribArray(texCoordLoc);
configureTexture(normals);
//-----------------------------------------------------------------------------------------
var ambientProduct = mult(lightAmbient, materialAmbient);
var diffuseProduct = mult(lightDiffuse, materialDiffuse);
var specularProduct = mult(lightSpecular, materialSpecular);
//-----------------------------------------------------------------------------------------
var ambientProduct2 = mult(lightAmbient2, materialAmbient);
var diffuseProduct2 = mult(lightDiffuse2, materialDiffuse);
var specularProduct2 = mult(lightSpecular2, materialSpecular);
var ambientProduct3 = mult(lightAmbient3, materialAmbient);
var diffuseProduct3 = mult(lightDiffuse3, materialDiffuse);
var specularProduct3 = mult(lightSpecular3, materialSpecular);
//-----------------------------------------------------------------------------------------
document.getElementById("ButtonX").onclick = function(){axis = xAxis;};
document.getElementById("ButtonY").onclick = function(){axis = yAxis;};
document.getElementById("ButtonZ").onclick = function(){axis = zAxis;};
document.getElementById("ButtonRotation").onclick = function(){RotationFlag = !RotationFlag;}; //Task-2
document.getElementById("ButtonStart").onclick = function(){flag = true;}; //Task-2
document.getElementById("ButtonStop").onclick = function(){flag = false;}; //Task-2
document.getElementById("SwitchL").onclick = function(event){
lightFlag =! lightFlag;
if(lightFlag){
document.getElementById('info4').innerHTML = "Turn On";
}
else{
document.getElementById('info4').innerHTML = "Turn Off";
}
}; //Task-4
document.getElementById("SwitchP").onclick = function(event){
perFlag =! perFlag;
if(perFlag){
document.getElementById('info6').innerHTML = "Per-Vertex";
}
else{
document.getElementById('info6').innerHTML = "Per-Fragment";
}
}; //Task-6
document.getElementById("SwitchT").onclick = function(event){
textureFlag =! textureFlag;
if(textureFlag){
document.getElementById('info7').innerHTML = "Deactivate Bump Texture";
}
else{
document.getElementById('info7').innerHTML = "Activate Bump Texture";
}
}; //Task-7
//-----------------------------------------------------------------------------------------------------------------------
//Task-3
document.getElementById("SwitchV").onclick = function(event){
viewerFlag =! viewerFlag;
if(viewerFlag){
document.getElementById('info3').innerHTML = "Activate Perjection Viewer";
}
else{
document.getElementById('info3').innerHTML = "Deactivate Perjection Viewer";
}
};
document.getElementById("radius").onchange = function(event) {radius = event.target.value/2;};
document.getElementById("Button0").onclick = function(){thetav += dr;};
document.getElementById("Button1").onclick = function(){thetav -= dr;};
document.getElementById("Button2").onclick = function(){phi += dr;};
document.getElementById("Button3").onclick = function(){phi -= dr;};
document.getElementById("Button4").onclick = function(){near *= 1.1; far *= 1.1;};
document.getElementById("Button5").onclick = function(){near *= 0.9; far *= 0.9;};
document.getElementById("fovy").onchange = function(event) {fovy = event.target.value;};
//---------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------
//Task-4
var av = vec4(1/3, 1/3, 1/3, 1/3);
gl.uniform4fv(gl.getUniformLocation(program, "uAmbientProduct"), mult(add(add(ambientProduct,ambientProduct2),ambientProduct3), av));
gl.uniform4fv(gl.getUniformLocation(program, "uDiffuseProduct"), mult(add(add(diffuseProduct,diffuseProduct2),diffuseProduct3),av));
gl.uniform4fv(gl.getUniformLocation(program, "uSpecularProduct"),mult(add(add(specularProduct,specularProduct2),specularProduct3),av));
gl.uniform4fv(gl.getUniformLocation(program, "umaterialEmission"), materialEmission );//Task-4
//---------------------------------------------------------------------------------------------------------------------
gl.uniform4fv(gl.getUniformLocation(program, "uLightPosition"), lightPosition );
gl.uniform1f(gl.getUniformLocation(program, "uShininess"), materialShininess);
//------------------------------------------------------------------------------------------------------------------------
//Task-2
rotationMatrix = mat4();
rotationMatrixLoc = gl.getUniformLocation(program, "uRotationMatrix");
gl.uniformMatrix4fv(rotationMatrixLoc, false, flatten(rotationMatrix));
canvas.addEventListener("mousedown", function(event){
var x = 2*event.clientX/canvas.width-1;
var y = 2*(canvas.height-event.clientY)/canvas.height-1;
startMotion(x, y);
});
canvas.addEventListener("mouseup", function(event){
var x = 2*event.clientX/canvas.width-1;
var y = 2*(canvas.height-event.clientY)/canvas.height-1;
stopMotion(x, y);
});
canvas.addEventListener("mousemove", function(event){
var x = 2*event.clientX/canvas.width-1;
var y = 2*(canvas.height-event.clientY)/canvas.height-1;
mouseMotion(x, y);
} );
//------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------
//Task-6
gl.uniform4fv(gl.getUniformLocation(program, "uAmbientProduct6"), ambientProduct);
gl.uniform4fv(gl.getUniformLocation(program, "uDiffuseProduct6"), diffuseProduct );
gl.uniform4fv(gl.getUniformLocation(program, "uSpecularProduct6"), specularProduct );
gl.uniform1f(gl.getUniformLocation(program, "uShininess6"), materialShininess);
//------------------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------------------
//Task-7
gl.uniform4fv( gl.getUniformLocation(program, "uNormal"), normal);
gl.uniform3fv( gl.getUniformLocation(program, "uObjTangent"), tangent);
gl.uniform4fv(gl.getUniformLocation(program, "uDiffuseProducttex"), diffuseProduct );
//------------------------------------------------------------------------------------------------------------------------
render();
}
function render(){
gl.useProgram(program);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
if (viewerFlag){
if(flag) theta[axis] += 2.0;
modelViewMatrix = mat4();
modelViewMatrix = mult(modelViewMatrix, rotate(theta[xAxis], vec3(1, 0, 0)));
modelViewMatrix = mult(modelViewMatrix, rotate(theta[yAxis], vec3(0, 1, 0)));
modelViewMatrix = mult(modelViewMatrix, rotate(theta[zAxis], vec3(0, 0, 1)));
nMatrix = normalMatrix(modelViewMatrix, true); //Task-7
projectionMatrix = ortho(-1, 1, -1, 1, -100, 100);
}
//------------------------------------------------------------------------------------------------------------------------
//Task-3
else{
var eye = vec3(radius*Math.sin(thetav)*Math.cos(phi),
radius*Math.sin(thetav)*Math.sin(phi),
radius*Math.cos(thetav));
var modelViewMatrix = lookAt(eye, at, up);
projectionMatrix = perspective(fovy, canvas.width/canvas.height, near, far);
}
//------------------------------------------------------------------------------------------------------------------------
lightPosition[0] = lightPosition[0] + radius*Math.sin(thetav)*Math.cos(phi);
lightPosition[1] = lightPosition[1] + radius*Math.sin(thetav)*Math.sin(phi);
lightPosition[2] = lightPosition[2] + radius*Math.cos(thetav);
if(RotationFlag){
if(trackballMove) {
axis2 = normalize(axis2);
rotationMatrix = mult(rotationMatrix, rotate(angle, axis2));
gl.uniformMatrix4fv(rotationMatrixLoc, false, flatten(rotationMatrix));
}
gl.uniform1f(gl.getUniformLocation(program, "uRotationFlag"), RotationFlag);//Task-2
}
gl.uniformMatrix4fv(gl.getUniformLocation(program, "uModelViewMatrix"), false, flatten(modelViewMatrix));
gl.uniformMatrix4fv( gl.getUniformLocation(program, "uProjectionMatrix"), false, flatten(projectionMatrix)); //Task-3
gl.uniform1i( gl.getUniformLocation(program, "uLightFlag"), lightFlag); //Task-4
gl.uniform1i( gl.getUniformLocation(program, "uPerFlag"), perFlag); //Task-6
gl.uniformMatrix3fv( gl.getUniformLocation(program, "uNormalMatrix"), false, flatten(nMatrix)); //Task-7
gl.uniform1i( gl.getUniformLocation(program, "uTextureFlag"), textureFlag); //Task-7
//------------------------------------------------------------------------------------------------------------------------
//Task-4
gl.drawArrays(gl.TRIANGLES, 0, numPositions+ncylinder);
//------------------------------------------------------------------------------------------------------------------------
requestAnimationFrame(render);
}
}
shadedCube();
```