It's a Hollow Feeling II

BACK FRONT FRONT_AND_BACK none

Press x,y and z to rotate.

The HTML File

<html>
<head>

<script id="vertex-shader" type="x-shader/x-vertex" >
precision mediump float;

attribute vec4 vPosition;
attribute vec3 vBC;
attribute vec4 vColor;

//uniform float vFillType;

varying vec3 f_BC;
varying vec4 f_Color;
varying vec4 e_Color;

void main() {

    gl_Position = vPosition;
    f_BC = vBC;
    f_Color = vColor;
    e_Color = vec4(0.0, 0.0, 0.0, 1.0);
}
</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 vec4 e_Color;

uniform int vShader;

    // filled with edge shader
    void Shader0() {
       if (any(lessThan(f_BC, vec3(0.005)))) {
           // edge, draw it with the edge color
           gl_FragColor= e_Color;
       } else {
           if (gl_FrontFacing) {
	       // front face, draw it with the face color
               gl_FragColor = f_Color;
	   } else {
	       // back face, draw it grey
	       gl_FragColor = vec4(0.5, 0.5, 0.5, 1.0);
	   }
       }
    }

    // wireframe shader
    void Shader1() {
       if (gl_FrontFacing) {  
           // front face
           if (any(lessThan(f_BC, vec3(0.05)))) {
	       // wide border
               gl_FragColor= e_Color;
           } else {
	       // no interior
	       discard;
           }
       } else {
           // back facing
           if (any(lessThan(f_BC, vec3(0.005)))) {
	       // narrow border
               gl_FragColor= e_Color;
	   } else {
	      // partially obscuring
	      gl_FragColor = vec4(0.2, 0.2, 0.2, 0.3);
	   }
       }
    }

    void main(){
        if (vShader == 0) {
            Shader0(); 
	} else if (vShader == 1) {
	    Shader1();
	} else {
             gl_FragColor = f_Color;
        }
    }
</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="b2.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>It's a Hollow Feeling II</h1>
<script>
    var canvas = new Canvas(500, 500);
    canvas.Redisplay();
</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>
<p>
Press x,y and z to rotate.

</body>

The Javascript File

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;

    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;

    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,2,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);

    // a buffer for the colors
    this.cBuffer = gl.createBuffer();
    gl.bindBuffer(gl.ARRAY_BUFFER, this.cBuffer);

    var colorAttribute = gl.getAttribLocation(program, "vColor");
    gl.vertexAttribPointer(colorAttribute,3,gl.FLOAT, false,0,0);
    gl.enableVertexAttribArray(colorAttribute);

    this.shaderLoc = gl.getUniformLocation(program, "vShader");

    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.shaderChoice = false;
        this.gl.uniform1i(this.shaderLoc, 0);
 
        this.direction = this.gl.CCW;
        this.gl.frontFace(this.direction);

        this.gl.enable(this.gl.CULL_FACE);
	this.gl.cullFace(this.gl.BACK);

	this.MakeList();
    },

    FlipDir: function() {
        if (this.direction == this.gl.CCW) {
	    this.direction = this.gl.CW;
	} else {
	    this.direction = this.gl.CCW;
	}
        this.gl.frontFace(this.direction);
    },

    MakeList: function() {

        var p1 = vec2(-0.8, -0.8);
        var p2 = vec2(-0.1, -0.1);
        var p3 = vec2(-0.8, -0.1);
       
	this.verts= [p1, p2, p3] ;

        p1 = vec2(0.1, 0.1);
        p3 = vec2(0.8, 0.1);
	p2 = vec2(0.8, 0.8);

        this.verts.push(p1);
        this.verts.push(p2);
        this.verts.push(p3);

	var c1 = vec3(Math.random(), Math.random(),Math.random())
	var c2 = vec3(Math.random(), Math.random(),Math.random())
	var c3 = vec3(Math.random(), Math.random(),Math.random())

	this.colors = [c1, c2, c3];

	c1 = vec3(Math.random(), Math.random(),Math.random())
	c2 = vec3(Math.random(), Math.random(),Math.random())
	c3 = vec3(Math.random(), Math.random(),Math.random())

	this.colors.push(c1);
	this.colors.push(c2);
	this.colors.push(c3);

	this.bc = [[1,0,0],[0,1,0],[0,0,1],[1,0,0],[0,1,0],[0,0,1]];

        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);

        gl.bindBuffer(gl.ARRAY_BUFFER, this.cBuffer);
	gl.bufferData(gl.ARRAY_BUFFER,flatten(this.colors),gl.STATIC_DRAW);
    },

    ChangeShader: function() {
        if (this.shaderChoice == 0) {
            this.shaderChoice = 1
        } else {
	    this.shaderChoice = 0;
	}
        this.gl.uniform1i(this.shaderLoc, this.shaderChoice);
	console.log(this.shaderChoice);
	this.Redisplay();
    },

    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;
       }
    },

    Redisplay: function() {
        this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT );

	this.gl.drawArrays(this.gl.TRIANGLES, 0, this.verts.length);
        return;
    }
};