Color | Red | Green | Blue |
---|---|---|---|
Ambient | |||
Diffuse | |||
Specular |
Value of alpha:
Key | ActioN |
---|---|
S | Swap Shaders |
x | rotate Item about X axis |
y | rotate Item about Y axis |
z | rotate Item about Z axis |
s | Toggle Specular |
a | Toggle Ambient |
d | Toggle Diffuse |
<html> <head> <script id="vertex-shader" type="x-shader/x-vertex" > precision mediump float; attribute vec4 attributePosition; attribute float attributeBC; attribute vec3 surfaceNormal; attribute vec3 vertexNormal; uniform mat4 uniformTransform; uniform mat4 worldTransform; uniform mat4 uniformProject; uniform float shadingType; uniform float uAmbient; uniform float uSpecular; uniform float uDiffuse; uniform float uAlpha; uniform vec3 uSurfaceAmbient; uniform vec3 uSurfaceSpecular; uniform vec3 uSurfaceDiffuse; varying vec3 varyingBC; varying vec4 color; varying vec3 varNormal; varying vec3 lightVector; varying vec3 halfAngle; varying float fade; void main() { vec4 here = worldTransform * uniformTransform * attributePosition; gl_Position = uniformProject * here; vec4 tmp = worldTransform * uniformTransform * vec4(surfaceNormal,1); vec3 normal = normalize(tmp.xyz); varNormal = normal.xyz; here = -here; vec4 light = vec4(0.0 ,-1.0 ,4.0, 0.0); light = worldTransform * light; lightVector = normalize(light-here).xyz; halfAngle = normalize(vec4(0.0, 0.0, -4.0, 0.0)+ light).xyz; /* float a = 1.0; float b = 0.0; float c = 0.0; float dist = distance(light.xyz,here.xyz); fade = 1.0/(a+b*dist + c *dist*dist); */ fade = 1.0; if (attributeBC == 0.0) { varyingBC = vec3(1.0, 0.0, 0.0); } else if (attributeBC == 1.0) { varyingBC = vec3(0.0, 1.0, 0.0); } else { varyingBC = vec3(0.0, 0.0, 1.0); } if (shadingType < 0.5) { vec3 lightAmbient = vec3(1.0,1.0, 1.0); vec3 lightDiffuse = vec3(1.0, 1.0, 1.0); vec3 lightSpecular = vec3(1.0, 1.0, 1.0); vec3 zero = vec3(0.0, 0.0, 0.0); vec3 one = vec3(1.0, 1.0, 1.0); vec3 ambient = lightAmbient * uSurfaceAmbient; vec3 diffuse = max(dot(lightVector, normal),0.0) * lightDiffuse * uSurfaceDiffuse ; diffuse = clamp(diffuse, zero, one); vec3 specular = max(pow(dot(halfAngle,normal),uAlpha),0.0) * lightSpecular * uSurfaceSpecular; specular = clamp(specular,zero,one); if (uAmbient > .5) { ambient = zero; } if (uDiffuse > .5) { diffuse = zero; } if (uSpecular > .5) { specular = zero; } color = vec4(clamp(ambient + fade*(diffuse + specular), zero,one),1.0); } else { vec4 tmp = worldTransform * uniformTransform * vec4(vertexNormal,1); varNormal = normalize(tmp.xyz); } } </script> <script id="fragment-shader" type="x-shader/x-fragment"> precision mediump float; varying vec3 varyingBC; uniform vec4 uniformEdgeColor; uniform float shadingType; uniform float uAmbient; uniform float uSpecular; uniform float uDiffuse; uniform float uAlpha; uniform vec3 uSurfaceAmbient; uniform vec3 uSurfaceSpecular; uniform vec3 uSurfaceDiffuse; varying vec4 color; varying vec3 varNormal; varying vec3 lightVector; varying vec3 halfAngle; varying float fade; void main(){ if (shadingType < 0.5) { gl_FragColor= color; } else { vec3 lightAmbient = vec3(1.0,1.0, 1.0); vec3 lightDiffuse = vec3(1.0, 1.0, 1.0); vec3 lightSpecular = vec3(1.0, 1.0, 1.0); vec3 zero = vec3(0.0, 0.0, 0.0); vec3 one = vec3(1.0, 1.0, 1.0); // because they may have become denormailzed in interpolation vec3 L = normalize(lightVector); vec3 N = normalize (varNormal); vec3 H = normalize(halfAngle); vec3 ambient = lightAmbient * uSurfaceAmbient; vec3 diffuse = max(dot(L,N),0.0) * lightDiffuse * uSurfaceDiffuse ; diffuse = clamp(diffuse, zero, one); vec3 specular = max(pow(dot(H,N),uAlpha),0.0) * lightSpecular * uSurfaceSpecular; specular = clamp(specular,zero,one); if (uAmbient > .5) { ambient = zero; } if (uDiffuse > .5) { diffuse = zero; } if (uSpecular > .5) { specular = zero; } gl_FragColor = vec4(clamp(ambient + fade*(diffuse + specular), zero,one),1.0); } } </script> <script type="text/javascript" src="../Common/webgl-utils.js"></script> <script type="text/javascript" src="../Common/initShaders.js"></script> <script type="text/javascript" src="../Common/MV.js"></script> <script type="text/javascript" src="../Models/teapot.js"></script> <script type="text/javascript" src="../Models/bunny.js"> </script> <script type="text/javascript" src="../Models/cone.js"> </script> <script type="text/javascript" src="../Models/dragon.js"> </script> <script type="text/javascript" src="../Models/head.js"></script> <script type="text/javascript" src="../Models/stego.js"></script> <script type="text/javascript" src="../Models/xwing.js"></script> <script type="text/javascript" src="../Models/butterfly.js"></script> <script type="text/javascript" src="../Models/copter.js"></script> <script type="text/javascript" src="../Models/enterprise.js"></script> <script type="text/javascript" src="../Models/lizard.js"></script> <script type="text/javascript" src="../Models/tank.js"></script> <script type="text/javascript" src="../Models/cube.js"></script> <script type="text/javascript" src="../Models/epcot.js"></script> <script type="text/javascript" src="../Models/plane.js"></script> <script type="text/javascript" src="GLCanvas.js"></script> <script type="text/javascript" src="utils.js"></script> <script type="text/javascript" src="Widget.js"></script> <style> input { text-align: right; } </style> </head> <body> <h1>Lights</h1> <select onchange="MakeItem(this.value);Redisplay()"> <option value="teapot">Teapot</option> <option value="lizard">lizard</option> <option value="bunny">bunny</option> <option value="epcot">epcot</option> </select> <script> 'use strict' var canvas = new Canvas(400, 400, Keypress); var item; var camera, at, up, theta, phi; var orx=0, ory=0,orz=0; MakeItem("teapot") ResetCamera(); canvas.NewView(camera, at, up); Redisplay(); </script> <p> <table> <tr><th>Color</th><th> Red</th><th> Green</th><th> Blue</th></td> <tr><td> Ambient</td> <td> <input type="range" min="1" max="100" value="5" class="slider" id="ambientRed" onchange="FixColor()" list="ticks"> <output for="ambientRedInput" id="ambientRedInputValue"></output> </td> <td> <input type="range" min="1" max="100" value="5" class="slider" id="ambientGreen" onchange="FixColor()" list="ticks"> <output for="ambientGreenInput" id="ambientGreenInputValue"></output> </td> <td> <input type="range" min="1" max="100" value="5" class="slider" id="ambientBlue" onchange="FixColor()" list="ticks"> <output for="ambientBlueInput" id="ambientBlueInputValue"></output> </td></tr> <tr><td> Diffuse</td> <td> <input type="range" min="1" max="100" value="80" class="slider" id="diffuseRed" onchange="FixColor()" list="ticks"> <output for="diffuseRedInput" id="diffuseRedInputValue"></output> </td> <td> <input type="range" min="1" max="100" value="0" class="slider" id="diffuseGreen" onchange="FixColor()" list="ticks"> <output for="diffuseGreenInput" id="diffuseGreenInputValue"></output> </td> <td> <input type="range" min="1" max="100" value="0" class="slider" id="diffuseBlue" onchange="FixColor()" list="ticks"> <output for="diffuseBlueInput" id="diffuseBlueInputValue"></output> </td></tr> <tr><td> Specular</td> <td> <input type="range" min="1" max="100" value="70" class="slider" id="specularRed" onchange="FixColor()" list="ticks"> <output for="specularRedInput" id="specularRedInputValue"></output> </td> <td> <input type="range" min="1" max="100" value="10" class="slider" id="specularGreen" onchange="FixColor()" list="ticks"> <output for="specularGreenInput" id="specularGreenInputValue"></output> </td> <td> <input type="range" min="1" max="100" value="10" class="slider" id="specularBlue" onchange="FixColor()" list="ticks"> <output for="specularBlueInput" id="specularBlueInputValue"></output> </td></tr> </table> <p> Value of alpha: <input type="range" min="1" max="500" value="100" class="slider" id="alphaInput" onchange="FixAlpha()" list="ticks"> <output for="alphaInput" id="alphaInputValue"></output> <datalist id="ticks"> <option value="1"></option> <option value="120"></option> <option value="250"></option> <option value="360"></option> <option value="500"></option> </datalist> <p> <table> <tr><th> Key</td><td> ActioN</td></tr> <tr><td> S</td><td> Swap Shaders</td></tr> <tr><td> x</td><td> rotate Item about X axis</td></tr> <tr><td> y</td><td> rotate Item about Y axis</td></tr> <tr><td> z</td><td> rotate Item about Z axis</td></tr> <tr><td> s</td><td> Toggle Specular</td></tr> <tr><td> a</td><td> Toggle Ambient</td></tr> <tr><td> d</td><td> Toggle Diffuse</td></tr> </table> </body>
'use strict' class Canvas { constructor (width, height, Keypress) { this.height = height; this.width = width; this.MakeCanvas(); this.canvas.addEventListener("keypress", Keypress); this.SetupGL(); this.MakeShaders(); this.Init(); this.NewView([0,0,-1], [0,0,0],[0,1,0]); } NewView( camera, at, up) { var eye = lookAt(camera, at, up); var proj = this.Frustum(-1, 1, -1, 1,2 ,20); this.gl.uniformMatrix4fv(this.worldTrans, false,flatten(eye)); this.gl.uniformMatrix4fv(this.projLoc, false,flatten(proj)); } Frustum(l,r,b,t,n,f) { var m = mat4(1); m[0][0] = 2 * n / (r - l); m[0][1] = 0; m[0][2] = (r + l) / (r - l); m[0][3] = 0; m[1][0] = 0; m[1][1] = 2 * n / (t - b); m[1][2] = (t + b) / (t - b); m[1][3] = 0; m[2][0] = 0; m[2][1] = 0; m[2][2] = -(f + n) / (f - n); m[2][3] = -2 * f * n / (f - n); m[3][0] = 0; m[3][1] = 0; m[3][2] = -1; m[3][3] = 0; return m; } MakeCanvas() { if (this.width == undefined || this.width < 0) { this.width = 300; } if (this.height == undefined || this.height < 0) { this.height = 300; } this.canvas = document.createElement('canvas') this.canvas.tabIndex=0; this.canvas.height = this.height; this.canvas.width = this.width; this.canvas.style.border = '1px solid #000'; document.body.appendChild(this.canvas); } SetupGL() { this.gl = WebGLUtils.setupWebGL(this.canvas); if (!this.gl) { alert ("WebGL isn't available"); return; } this.gl.getExtension('OES_standard_derivatives'); } MakeShaders() { var gl = this.gl; this.program = initShaders(gl, "vertex-shader","fragment-shader"); gl.useProgram(this.program); this.projLoc = gl.getUniformLocation(this.program, "uniformProject"); this.worldTrans = gl.getUniformLocation(this.program, "worldTransform"); this.transLoc = gl.getUniformLocation(this.program, "uniformTransform"); this.edgeColorLoc = gl.getUniformLocation(this.program, "uniformEdgeColor"); this.surfaceColorLoc = gl.getUniformLocation(this.program, "uniformSurfaceColor"); this.shadingType = gl.getUniformLocation(this.program,"shadingType"); this.uAmbient = gl.getUniformLocation(this.program,"uAmbient"); this.uSpecular = gl.getUniformLocation(this.program,"uSpecular"); this.uDiffuse = gl.getUniformLocation(this.program,"uDiffuse"); this.uAlpha = gl.getUniformLocation(this.program,"uAlpha"); this.uSurfaceAmbient = gl.getUniformLocation(this.program,"uSurfaceAmbient"); this.uSurfaceSpecular = gl.getUniformLocation(this.program,"uSurfaceSpecular"); this.uSurfaceDiffuse = gl.getUniformLocation(this.program,"uSurfaceDiffuse"); } SurfaceAmbient(r,g,b) { this.gl.uniform3f(this.uSurfaceAmbient,r,g,b); } SurfaceSpecular(r,g,b) { this.gl.uniform3f(this.uSurfaceSpecular,r,g,b); } SurfaceDiffuse(r,g,b) { this.gl.uniform3f(this.uSurfaceDiffuse,r,g,b); } ToggleAmbient() { if (this.ambientV == 1) { this.ambientV = 0; } else { this.ambientV = 1; } this.gl.uniform1f(this.uAmbient,this.ambientV); } ToggleSpecular() { if (this.specularV == 1) { this.specularV = 0; } else { this.specularV = 1; } this.gl.uniform1f(this.uSpecular,this.specularV); } ToggleDiffuse() { if (this.diffuseV == 1) { this.diffuseV = 0; } else { this.diffuseV = 1; } this.gl.uniform1f(this.uDiffuse,this.diffuseV); } SwapShaders() { if (this.shadingTypeV == 1.0) { this.shadingTypeV = 0.0; } else { this.shadingTypeV = 1.0; } this.gl.uniform1f(this.shadingType,this.shadingTypeV); } SetAlpha(d) { if (d >0 && d <= 500) { this.gl.uniform1f(this.uAlpha,d); } } Init() { var gl = this.gl; gl.clearColor(1.0, 1.0, 1.0, 1.0); gl.viewport(0,0, this.width, this.height); gl.enable(gl.BLEND); gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA); gl.enable(gl.DEPTH_TEST); gl.frontFace(gl.CW); // set the default edge color for everything this.NewEdgeColor([0.0, 0.0, 0.0, 1.0]); this.NewSurfaceColor([1.0, 0.0, 0.0, 1.0]); this.shadingTypeV =1; this.SwapShaders(); this.ambientV = 1; this.ToggleAmbient(); this.specularV = 1; this.ToggleSpecular(); this.diffuseV = 1; this.ToggleDiffuse(); this.SetAlpha(100); this.SurfaceSpecular(0.7, 0.1, 0.1); this.SurfaceAmbient(0.05, 0.05, 0.05); this.SurfaceDiffuse(0.8, 0.0, 0.0); } NewSurfaceColor(c) { this.gl.uniform4fv(this.surfaceColorLoc, c); } NewEdgeColor(c) { this.gl.uniform4fv(this.edgeColorLoc, c); } Program() { return this.program; } GL() { return this.gl; } Translate() { return this.transLoc; } Clear() { this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); } };
'use strict' class Widget { constructor(gl, program, tris,cw) { this.size = tris.length; var bcs = [] for (var i=0;i<tris.length/3;i++) { bcs.push([0.0,1.0,2.0]); } this.SetupVBO(gl, program, tris, bcs); this.SurfaceNormals(gl,program,tris,cw); this.VertexNormals(gl,program,tris,cw); this.Reset(); this.Transform(); } SurfaceNormals(gl, program,tris,cw){ let i; let sn=[]; for(i=0;i<tris.length;i+=3) { let j=0; let normal; let a = subtract(vec3(tris[i]) , vec3(tris[i+1])); let b = subtract(vec3(tris[i]) , vec3(tris[i+2])); if (equal(a, vec3(0,0,0))) { a = vec3(1,0,0); } a = normalize(a); if (equal(b, vec3(0,0,0))) { b = vec3(1,0,0); } b = normalize(b) if (cw) { normal = normalize(cross(a,b)); } else { normal = normalize(cross(b,a)); } for(j=0;j<3;j++ ) { sn.push(normal); } } this.vSN = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.vSN); this.aSN = gl.getAttribLocation(program, "surfaceNormal"); if (this.aSN ==-1) { console.log("failed to get attribute for surfaceNormal") } else { gl.vertexAttribPointer(this.aSN,3,gl.FLOAT, false,0,0); gl.enableVertexAttribArray(this.aSN); gl.bufferData(gl.ARRAY_BUFFER,flatten(sn),gl.STATIC_DRAW); } } VertexNormals(gl,program,tris,cw) { var verts = new Map(); let i; let sn=[]; for(i=0;i<tris.length;i+=3) { let j=0; let normal; let a = subtract(vec3(tris[i]) , vec3(tris[i+1])); let b = subtract(vec3(tris[i]) , vec3(tris[i+2])); if (equal(a, vec3(0,0,0))) { a = vec3(1,0,0); } a = normalize(a); if (equal(b, vec3(0,0,0))) { b = vec3(1,0,0); } b = normalize(b) if (cw) { normal = normalize(cross(a,b)); } else { normal = normalize(cross(b,a)); } for (let j=0;j<3;j++) { if (verts.has(tris[i+j])) { verts[tris[i+j]] = add(verts[tris[i+j]],normal); } else { verts[tris[i+j]] = normal; } } } for (let k of verts.keys()) { verts[k] = normalize(verts[k]); } for(i=0;i<tris.length;i+=3) { for (let j=0;j<3;j++) { sn.push(verts[tris[i+j]]); } } this.vVN = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.vVN); this.aVN = gl.getAttribLocation(program, "vertexNormal"); if (this.aVN ==-1) { console.log("failed to get attribute for vertexNormal") } else { gl.vertexAttribPointer(this.aVN,3,gl.FLOAT, false,0,0); gl.enableVertexAttribArray(this.aVN); gl.bufferData(gl.ARRAY_BUFFER,flatten(sn),gl.STATIC_DRAW); } } // things we might want to have to totally reset the item. Reset() { this.visible = true; this.rx = 0; this.ry = 0; this.rz = 0; this.sx = 1; this.sy = 1; this.sz = 1; this.tx = 0; this.ty = 0; this.tz = 0; } SetupVBO(gl, program, tris, bcs) { this.vPos = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.vPos); this.aPos = gl.getAttribLocation(program, "attributePosition"); if (this.aPos == -1) { console.log("Faild to get attributePosition") ; } else { gl.vertexAttribPointer(this.aPos, 3, gl.FLOAT, false, 0, 0); gl.enableVertexAttribArray(this.aPos); gl.bufferData(gl.ARRAY_BUFFER,flatten(tris),gl.STATIC_DRAW); } this.vBC = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.vBC); this.aBC = gl.getAttribLocation(program, "attributeBC"); if (this.aBC == -1) { console.log("Faild to get attributeBC") ; } else { gl.vertexAttribPointer(this.aBC,1,gl.FLOAT, false,0,0); gl.enableVertexAttribArray(this.aBC); gl.bufferData(gl.ARRAY_BUFFER,flatten(bcs),gl.STATIC_DRAW); } } Show() { this.visible = true; } Hide() { this.visible = false; } Visible() { return this.visible; } Transform() { var tmp = translate(this.tx, this.ty, this.tz); tmp = mult(tmp, scalem(this.sx, this.sy, this.sz)); tmp = mult(tmp, rotate(this.rz, [0,0,1])); tmp = mult(tmp, rotate(this.ry, [0,1,0])); tmp = mult(tmp, rotate(this.rx, [1,0,0])); this.transform = tmp; } Display(gl, transform, transLoc) { if (this.visible) { // make sure that the transform matrix is up to date. this.Transform(); // multiply it by any incoming transformation matrix let tx = mult(transform, this.transform); // use it gl.uniformMatrix4fv(transLoc, false, flatten(tx)); gl.bindBuffer(gl.ARRAY_BUFFER, this.vPos); gl.vertexAttribPointer(this.aPos, 3, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, this.vBC); gl.vertexAttribPointer(this.aBC, 1, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, this.vSN); gl.vertexAttribPointer(this.aSN, 3, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, this.vVN); gl.vertexAttribPointer(this.aVN, 3, gl.FLOAT, false, 0, 0); gl.drawArrays(gl.TRIANGLES, 0, this.size); } } }
'use strict' const FA = [-10, -1, -10]; const FB = [ 10, -1.5, -10]; const FC = [0, -1.5, 0]; const FD = [ 10, -1.5, 10]; const FE = [-10, -1.5, 10]; const CA = [-10, 3, -10]; const CB = [ 10, 3, -10]; const CC = [ 0, 3, 0]; const CD = [ 10, 3, 10]; const CE = [-10, 3, 10]; const Floor= [FA, FB, FC, FB, FD, FC, FD, FE, FC, FE, FA, FC]; const Roof = [CB, CA, CC, CD, CB, CC, CE, CD, CC, CA, CE, CC]; function MakeTeapot() { let teapot =new Widget(canvas.GL(), canvas.Program(), Teapot_Triangles,false); teapot.tz = .5 teapot.rx = -90 orx = -90; teapot.sx = 2; teapot.sy = 2; teapot.sz = 2; return teapot; } function MakeLizard() { let lizard =new Widget(canvas.GL(), canvas.Program(), Lizard_Triangles,false); lizard.tz = .5 lizard.ty = -1.3 lizard.rx = -90 orx = -90; lizard.sx = 3.4; lizard.sy = 3.4; lizard.sz = 3.4; return lizard; } function MakeBunny() { let bunny =new Widget(canvas.GL(), canvas.Program(), Bunny_Triangles,false); bunny.tz = 1.0 bunny.ty = 0 bunny.ry = 90 orx = 90; bunny.sx = 3.4; bunny.sy = 3.4; bunny.sz = 3.4; return bunny; } function MakeEpcot() { let epcot =new Widget(canvas.GL(), canvas.Program(), Epcot_Triangles,false); epcot.tz = 1.0 epcot.ty = 0 epcot.sx = 3.4; epcot.sy = 3.4; epcot.sz = 3.4; return epcot; } function MakeItem(key) { if (key == "teapot") { item = MakeTeapot(); } else if (key == "lizard") { item = MakeLizard(); } else if (key == "bunny") { item = MakeBunny(); } else if (key == "epcot") { item = MakeEpcot(); } } function ResetCamera() { up = [0,1,0]; theta = 0; phi = 90; camera = [0,0,-3.0]; MoveAt(0.5); } function Fix(angle) { while (angle < 0) { angle += 360; } angle %= 360; return angle; } function Offset(delta) { let x,y,z; theta = Fix(theta); phi = Fix(phi); let rphi = phi * Math.PI/180; let rtheta = theta * Math.PI/180; z = delta * Math.sin(rphi) * Math.cos(rtheta); y = delta * Math.cos(rphi) x = delta * Math.sin(rphi) * Math.sin(rtheta); return ([x,y,z]); } function MoveAt(delta) { let offset = Offset(delta); at = add(camera, offset); } function MoveAll(delta) { let offset = Offset(delta); camera = add(camera , offset); at = add(camera, offset); } function Keypress(evnt) { switch(evnt.key) { case 'S': canvas.SwapShaders(); break; case 'R': item.rx = orx; item.ry = ory; item.rz = orz; break; case 'x': item.rx ++; break; case 'y': item.ry ++; break; case 'z': item.rz ++; break; case 'a': canvas.ToggleAmbient(); break; case 's': canvas.ToggleSpecular(); break; case 'd': canvas.ToggleDiffuse(); break; } Redisplay(); } function FixAlpha() { let alpha = document.getElementById('alphaInput').value canvas.SetAlpha(alpha); Redisplay(); } function FixColor() { let aR = document.getElementById('ambientRed').value let aG = document.getElementById('ambientGreen').value let aB = document.getElementById('ambientBlue').value canvas.SurfaceAmbient(aR/100,aG/100,aB/100); let dR = document.getElementById('diffuseRed').value let dG = document.getElementById('diffuseGreen').value let dB = document.getElementById('diffuseBlue').value canvas.SurfaceDiffuse(dR/100,dG/100,dB/100); let sR = document.getElementById('specularRed').value let sG = document.getElementById('specularGreen').value let sB = document.getElementById('specularBlue').value canvas.SurfaceSpecular(sR/100,sG/100,sB/100); Redisplay(); } function Redisplay() { canvas.Clear(); canvas.NewEdgeColor([0.0, 0.0, 0.0, 1.0]); canvas.NewSurfaceColor([1.0, 0.0, 0.0, 1.0]); canvas.GL().frontFace(canvas.GL().CW); item.Display(canvas.GL(), mat4(), canvas.Translate()); }