Press x,y,z to rotate.
<html>
<head>
<script id="vertex-shader" type="x-shader/x-vertex" >
attribute vec4 vPosition;
attribute vec3 vBC;
attribute vec4 vColor;
uniform mat4 Transform;
uniform float vFillType;
varying vec3 f_BC;
varying vec4 f_Color;
varying float f_FillType;
void main() {
gl_Position = Transform * vPosition;
f_BC = vBC;
f_Color = vec4(1.0, 0.0, 0.0, 1.0);
f_FillType = vFillType;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
#extension GL_OES_standard_derivatives : enable
precision mediump float;
varying vec4 f_Color;
varying vec3 f_BC;
varying float f_FillType;
float edgeFactor(){
vec3 d = fwidth(f_BC);
vec3 a3 = smoothstep(vec3(0.0), d*1.5, f_BC);
return min(min(a3.x, a3.y), a3.z);
}
void main(){
if (f_FillType >= 1.0) {
// alpha by edge
if(gl_FrontFacing){
gl_FragColor = vec4(0,0.0,0.0, (1.0-edgeFactor())*0.95);
} else {
gl_FragColor = vec4(0.0, 0.0, 0.0, (1.0-edgeFactor())*0.7);
}
} else {
if (gl_FrontFacing) {
gl_FragColor = f_Color;
} else {
gl_FragColor = vec4(0.0, 0.0, 0.0, 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="../offs/oldTeapot.js"></script>
<!-- <script type="text/javascript" src="../offs/oldLizard.js"></script> --!>
<!-- <script type="text/javascript" src="../offs/oldTank.js"></script> --!>
<!-- <script type="text/javascript" src="../offs/oldDragon.js"></script> --!>
<script type="text/javascript" src="offTeapot.js"></script>
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
<style>
input {
text-align: right;
}
</style>
</head>
<body>
<h1>Care for Tea?</h1>
<script>
var canvas = new Canvas(500, 500);
</script>
<p>
<button type="button" onclick="canvas.FlipDir(),canvas.Redisplay()">
Triangle Dir
</button>
<button type="button" onclick="canvas.ChangeShader(),canvas.Redisplay()">
Change Shader
</button>
<form >
<input type="radio" name="face" value="0" checked
onchange="canvas.ChangeFace(this.value), canvas.Redisplay()">
BACK
</input>
<input type="radio" name="face" value="1"
onchange="canvas.ChangeFace(this.value), canvas.Redisplay()">
FRONT
</input>
<input type="radio" name="face" value="2"
onchange="canvas.ChangeFace(this.value), canvas.Redisplay()">
FRONT_AND_BACK
</input>
<input type="radio" name="face" value="3"
onchange="canvas.ChangeFace(this.value), canvas.Redisplay()">
none
</input>
</form>
Press x,y,z to rotate.
</body>
function MakeCanvas(width, height, locID) {
if (width == undefined || width < 0) {
width = 300;
}
if (height == undefined || height < 0) {
height = 300;
}
var canvas = document.createElement('canvas')
canvas.tabIndex = 0;
canvas.height = height;
canvas.width = width;
canvas.style.border = "1px solid #0000FF";
if(locID == undefined) {
document.body.appendChild(canvas);
} else {
div = document.getElementById(locID);
if (null == div) {
document.body.appendChild(canvas);
} else {
div.appendChild(canvas);
}
}
document.body.appendChild(canvas);
return canvas;
}
function InitGL(canvas) {
var gl = WebGLUtils.setupWebGL(canvas,'OES_standard_derivatives');
if (!gl) {
alert ("WebGL isn't available");
}
// required to turn on fwidth and such.
gl.getExtension('OES_standard_derivatives');
return gl;
}
function Canvas(width, height, locID) {
var canvas = MakeCanvas(width, height, locID);
var gl = InitGL(canvas);
this.gl = gl;
var tmpCanvas = this;
this.x = canvas.offsetLeft;
this.y = canvas.offsetTop;
canvas.addEventListener("keypress",
function(evnt) {
tmpCanvas.KeyFunc(tmpCanvas, evnt);
}
);
gl.viewport(0,0, width, height);
var program = initShaders(gl, "vertex-shader","fragment-shader");
gl.useProgram(program);
this.vPos = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.vPos);
var vPos = gl.getAttribLocation(program, "vPosition");
gl.vertexAttribPointer(vPos,3,gl.FLOAT, false,0,0);
gl.enableVertexAttribArray(vPos);
this.vBC = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, this.vBC);
var vBC = gl.getAttribLocation(program, "vBC");
gl.vertexAttribPointer(vBC,3,gl.FLOAT, false,0,0);
gl.enableVertexAttribArray(vBC);
this.shaderLoc = gl.getUniformLocation(program, "vFillType");
gl.uniform1f(this.shaderLoc, 0.0);
this.transformLoc = gl.getUniformLocation(program, "Transform");
this.Init();
return this;
}
Canvas.prototype = {
Init: function() {
this.gl.clearColor(1.0, 1.0, 1.0, 1.0);
this.gl.enable(this.gl.BLEND);
this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
this.gl.enable(this.gl.DEPTH_TEST);
this.gl.depthFunc(this.gl.LESS);
this.gl.depthMask(this.gl.TRUE);
this.RestartList();
this.shaderChoice = false;
this.gl.uniform1f(this.shaderLoc, 0.0);
this.Reset();
this.Redisplay();
},
Reset: function() {
this.xr = 0;
this.yr = 0;
this.zr = 0;
// make these switchable
this.gl.enable(this.gl.CULL_FACE);
this.direction = this.gl.CCW;
this.gl.frontFace(this.direction);
this.gl.cullFace(this.gl.BACK);
},
FlipDir: function() {
if (this.direction == this.gl.CCW) {
this.direction = this.gl.CW;
} else {
this.direction = this.gl.CCW;
}
this.gl.frontFace(this.direction);
},
RestartList: function() {
this.verts= teapotTriangles ;
this.bc = teapotBC
this.UpdateBuffers();
},
UpdateBuffers: function() {
var gl = this.gl;
// change the vertex data
gl.bindBuffer(gl.ARRAY_BUFFER, this.vBC);
gl.bufferData(gl.ARRAY_BUFFER,flatten(this.bc),gl.STATIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER, this.vPos);
gl.bufferData(gl.ARRAY_BUFFER,flatten(this.verts),gl.STATIC_DRAW);
},
ChangeShader: function() {
this.shaderChoice = ! this.shaderChoice;
var shader = 0.0;
if (this.shaderChoice) {
shader = 1.0
}
this.gl.uniform1f(this.shaderLoc, shader);
},
ChangeFace: function(value) {
switch(value) {
default:
case '0':
this.gl.enable(this.gl.CULL_FACE);
this.gl.cullFace(this.gl.BACK);
break;
case '1':
this.gl.enable(this.gl.CULL_FACE);
this.gl.cullFace(this.gl.FRONT);
break;
case '2':
this.gl.enable(this.gl.CULL_FACE);
this.gl.cullFace(this.gl.FRONT_AND_BACK);
break;
case '3':
this.gl.disable(this.gl.CULL_FACE);
break;
}
},
KeyFunc: function(me, evnt) {
switch(evnt.key) {
case 'X': me.xr += -5; break;
case 'Y': me.yr += -5; break;
case 'Z': me.zr += -5; break;
case 'x': me.xr += 5; break;
case 'y': me.yr += 5; break;
case 'z': me.zr += 5; break;
case 'r': me.Reset(); break;
}
me.Redisplay();
},
Redisplay: function() {
var transform = mat4(1);
// this probably doesn't belong here
transform = mult(transform, rotate(this.xr, [1,0,0]));
transform = mult(transform, rotate(this.yr, [0,1,0]));
transform = mult(transform, rotate(this.zr, [0,0,1]));
this.gl.uniformMatrix4fv(this.transformLoc,false, flatten(transform ));
this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);
this.gl.drawArrays(this.gl.TRIANGLES, 0, this.verts.length);
return;
}
};