<html> <head> <script id="vertex-shader" type="x-shader/x-vertex" > precision mediump float; attribute vec4 vPosition; attribute vec3 vBC; attribute vec4 vColor; 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"> 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 = vec4(1.0, 1.0, 1.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="GLCanvas.js"></script> <script type="text/javascript" src="triangle.js"></script> <style> input { text-align: right; } </style> </head> <body> <h1>Barycentric Coordinates</h1> <script> var canvas = new Canvas(500, 500); var triangle = new Triangle(canvas.GL(), canvas.Program()); function Redisplay() { canvas.Clear(); triangle.Display(canvas.GL()); } Redisplay(); </script> <p> <button type="button" onclick="canvas.FlipDir(),Redisplay()"> Triangle Dir </button> <button type="button" onclick="canvas.ChangeShader(),Redisplay()"> Change Shader </button> <form > <input type="radio" name="face" value="0" checked onchange="canvas.ChangeFace(this.value), Redisplay()"> BACK </input> <input type="radio" name="face" value="1" onchange="canvas.ChangeFace(this.value), Redisplay()"> FRONT </input> <input type="radio" name="face" value="2" onchange="canvas.ChangeFace(this.value), Redisplay()"> FRONT_AND_BACK </input> <input type="radio" name="face" value="3" onchange="canvas.ChangeFace(this.value), Redisplay()"> none </input> </form> </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(); } 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; 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() { this.program = initShaders(this.gl, "vertex-shader","fragment-shader"); this.gl.useProgram(this.program); this.shaderLoc = this.gl.getUniformLocation(this.program, "vShader"); } Init() { this.gl.clearColor(1.0, 1.0, 1.0, 1.0); this.gl.viewport(0,0, this.width, this.height); 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.ChangeShader(); this.FlipDir(); this.ChangeFace(0); } FlipDir() { if (this.direction == this.gl.CCW) { this.direction = this.gl.CW; } else { this.direction = this.gl.CCW; } this.gl.frontFace(this.direction); } ChangeShader() { if (this.shaderChoice === 0 || this.shaderChoice === undefined ) { this.shaderChoice = 1 } else { this.shaderChoice = 0; } this.gl.uniform1i(this.shaderLoc, this.shaderChoice); } ChangeFace(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; } } Program() { return this.program; } GL() { return this.gl; } Clear() { this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT); } };
'use strict' class Triangle { constructor(gl, program) { this.SetupBuffers(gl, program) this.MakeList(gl) } SetupBuffers(gl, 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); } MakeList(gl) { 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(gl); } UpdateBuffers(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); } Display(gl) { gl.drawArrays(gl.TRIANGLES, 0, this.verts.length); } }