diff --git a/T09.js b/T09.js new file mode 100644 index 0000000000000000000000000000000000000000..3ce158d8e6c17301d091849ef794b0759647cd14 --- /dev/null +++ b/T09.js @@ -0,0 +1,361 @@ +var gl; +const {mat2, mat3, mat4, vec2, vec3, vec4} = glMatrix; // Now we can use function without glMatrix.~~~ + +function testGLError(functionLastCalled) { + /* gl.getError returns the last error that occurred using WebGL for debugging */ + var lastError = gl.getError(); + + if (lastError != gl.NO_ERROR) { + alert(functionLastCalled + " failed (" + lastError + ")"); + return false; + } + return true; +} + +function initialiseGL(canvas) { + try { + // Try to grab the standard context. If it fails, fallback to experimental + gl = canvas.getContext('webgl', + {stencil:true, alpha:true, depth:true, antialias:true, preserveDrawingBuffer:false}); + //gl = canvas.getContext('webgl', + // {stencil:true, alpha:true, depth:true, antialias:false, preserveDrawingBuffer:true}); + gl.viewport(0, 0, canvas.width, canvas.height); + } + catch (e) { + } + + if (!gl) { + alert("Unable to initialise WebGL. Your browser may not support it"); + return false; + } + return true; +} + +var shaderProgram; + +var vertexData = [ + // Backface (RED/WHITE) -> z = 0.5 + -0.5, -0.5, -0.5, 1.0, 0.0, 0.0, 1.0, + 0.5, 0.5, -0.5, 1.0, 0.0, 0.0, 1.0, + 0.5, -0.5, -0.5, 1.0, 0.0, 0.0, 1.0, + -0.5, -0.5, -0.5, 1.0, 0.0, 0.0, 1.0, + -0.5, 0.5, -0.5, 1.0, 0.0, 0.0, 1.0, + 0.5, 0.5, -0.5, 1.0, 1.0, 1.0, 1.0, + // Front (BLUE/WHITE) -> z = 0.5 + -0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0, + 0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0, + 0.5, 0.5, 0.5, 0.0, 0.0, 1.0, 1.0, + -0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0, + 0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0, + -0.5, 0.5, 0.5, 0.0, 0.0, 1.0, 1.0, + // LEFT (GREEN/WHITE) -> z = 0.5 + -0.5, -0.5, -0.5, 0.0, 1.0, 0.0, 1.0, + -0.5, 0.5, 0.5, 0.0, 1.0, 0.0, 1.0, + -0.5, 0.5, -0.5, 0.0, 1.0, 0.0, 1.0, + -0.5, -0.5, -0.5, 0.0, 1.0, 0.0, 1.0, + -0.5, -0.5, 0.5, 0.0, 1.0, 0.0, 1.0, + -0.5, 0.5, 0.5, 0.0, 1.0, 1.0, 1.0, + // RIGHT (YELLOW/WHITE) -> z = 0.5 + 0.5, -0.5, -0.5, 1.0, 1.0, 0.0, 1.0, + 0.5, 0.5, -0.5, 1.0, 1.0, 0.0, 1.0, + 0.5, 0.5, 0.5, 1.0, 1.0, 0.0, 1.0, + 0.5, -0.5, -0.5, 1.0, 1.0, 0.0, 1.0, + 0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0, + 0.5, -0.5, 0.5, 1.0, 1.0, 0.0, 1.0, + // BOTTON (MAGENTA/WHITE) -> z = 0.5 + -0.5, -0.5, -0.5, 1.0, 0.0, 1.0, 1.0, + 0.5, -0.5, -0.5, 1.0, 0.0, 1.0, 1.0, + 0.5, -0.5, 0.5, 1.0, 0.0, 1.0, 1.0, + -0.5, -0.5, -0.5, 1.0, 0.0, 1.0, 1.0, + 0.5, -0.5, 0.5, 1.0, 1.0, 1.0, 1.0, + -0.5, -0.5, 0.5, 1.0, 0.0, 1.0, 1.0, + // TOP (CYAN/WHITE) -> z = 0.5 + -0.5, 0.5, -0.5, 0.0, 1.0, 1.0, 1.0, + 0.5, 0.5, 0.5, 0.0, 1.0, 1.0, 1.0, + 0.5, 0.5, -0.5, 0.0, 1.0, 1.0, 1.0, + -0.5, 0.5, -0.5, 0.0, 1.0, 1.0, 1.0, + -0.5, 0.5, 0.5, 0.0, 1.0, 1.0, 1.0, + 0.5, 0.5, 0.5, 1.0, 1.0, 1.0, 1.0 +]; + +function initialiseBuffer() { + + gl.vertexBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, gl.vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertexData), gl.STATIC_DRAW); + + return testGLError("initialiseBuffers"); +} + +function initialiseShaders() { + + var fragmentShaderSource = ` + varying highp vec4 col; + void main(void) + { + gl_FragColor = col; + }`; + + gl.fragShader = gl.createShader(gl.FRAGMENT_SHADER); + gl.shaderSource(gl.fragShader, fragmentShaderSource); + gl.compileShader(gl.fragShader); + // Check if compilation succeeded + if (!gl.getShaderParameter(gl.fragShader, gl.COMPILE_STATUS)) { + alert("Failed to compile the fragment shader.\n" + gl.getShaderInfoLog(gl.fragShader)); + return false; + } + + // Vertex shader code + var vertexShaderSource = ` + attribute highp vec4 myVertex; + attribute highp vec4 myColor; + uniform mediump mat4 mMat; + uniform mediump mat4 vMat; + uniform mediump mat4 pMat; + varying highp vec4 col; + void main(void) + { + gl_Position = pMat * vMat * mMat * myVertex; + gl_PointSize = 8.0; + col = myColor; + }`; + + gl.vertexShader = gl.createShader(gl.VERTEX_SHADER); + gl.shaderSource(gl.vertexShader, vertexShaderSource); + gl.compileShader(gl.vertexShader); + // Check if compilation succeeded + if (!gl.getShaderParameter(gl.vertexShader, gl.COMPILE_STATUS)) { + alert("Failed to compile the vertex shader.\n" + gl.getShaderInfoLog(gl.vertexShader)); + return false; + } + + // Create the shader program + gl.programObject = gl.createProgram(); + // Attach the fragment and vertex shaders to it + gl.attachShader(gl.programObject, gl.fragShader); + gl.attachShader(gl.programObject, gl.vertexShader); + // Bind the custom vertex attribute "myVertex" to location 0 + gl.bindAttribLocation(gl.programObject, 0, "myVertex"); + gl.bindAttribLocation(gl.programObject, 1, "myColor"); + // Link the program + gl.linkProgram(gl.programObject); + // Check if linking succeeded in a similar way we checked for compilation errors + if (!gl.getProgramParameter(gl.programObject, gl.LINK_STATUS)) { + alert("Failed to link the program.\n" + gl.getProgramInfoLog(gl.programObject)); + return false; + } + + gl.useProgram(gl.programObject); + + return testGLError("initialiseShaders"); +} + +var xRot = 0.0; +var yRot = 0.0; +var zRot = 0.0; +var speedRot = 0.01; + +var flag_animation = 0; +var flag_draw_twice = 0; +var flag_draw_stencil = 0; +var xeye=0; +var yeye=0; +var zeye=2; + + +function fn_speed_scale(a) +{ + speedRot *= a; +} + +var draw_mode = 4; // 4 Triangles, 3 line_strip 0-Points + +function fn_draw_mode(a) +{ + draw_mode = a; +} + +var fov_degree = 90.0; +function fn_update_fov(val) +{ + document.getElementById('textFOV').value=val; + fov_degree = val; +} + +function fn_toggle(mode) +{ + if (gl.isEnabled(mode)) + gl.disable(mode); + else + gl.enable(mode); +} + +function fn_cull_mode(val) +{ + gl.cullFace(val); +} + +var ccolor=0; +function fn_clearcolor() +{ + var cc =document.getElementById('ccolor').value; + ccolor=cc; +} +var acolor=0; +function fn_clearcolor2() +{ + var aa =document.getElementById('acolor').value; + acolor=aa; +} +var bcolor=0; +function fn_clearcolor3() +{ + var bb =document.getElementById('bcolor').value; + bcolor=bb; +} + + +function fn_polygonOffset() +{ + gl.polygonOffset(document.getElementById('offset_f').value,document.getElementById('offset_u').value); +} + +function fn_depth_mode(val) +{ + gl.depthFunc(val); +} + +var mMat, vMat, pMat; +var depth_clear_value = 1.0; + +function fn_make_clear_stencil() +{ + gl.enable(gl.STENCIL_TEST); + gl.stencilMask(0xFF); + gl.clearStencil(0); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.clearStencil(1); + gl.enable(gl.SCISSOR_TEST); + gl.scissor(400, 300, 100, 100); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.scissor(300, 200, 100, 100); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.stencilFunc(gl.EQUAL, 1, 255); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + gl.disable(gl.SCISSOR_TEST); +} + +function renderScene() { + + // fn_make_clear_stencil(); + + gl.clearColor(ccolor, acolor, bcolor, 1.0); + gl.clearDepth(depth_clear_value); // Added for depth Test + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Added for depth Test + + var mMatLocation = gl.getUniformLocation(gl.programObject, "mMat"); + var vMatLocation = gl.getUniformLocation(gl.programObject, "vMat"); + var pMatLocation = gl.getUniformLocation(gl.programObject, "pMat"); + pMat = mat4.create(); + vMat = mat4.create(); + mMat = mat4.create(); + // mat4.ortho(pMat, -1, 1, -1, 1, -1, 1); + // mat4.frustum(pMat, -8.0/6.0, 8.0/6.0, -1, 1, 1, ); + mat4.perspective(pMat, fov_degree * 3.141592 / 180.0 , 8.0/6.0 , 0.5, 6); + mat4.lookAt(vMat, [xeye,yeye,zeye], [0.0 ,0.0, 0.0], [0,1,0]); + mat4.rotateX(mMat, mMat, xRot); + mat4.rotateY(mMat, mMat, yRot); + mat4.rotateZ(mMat, mMat, zRot); + + if (flag_animation == 1) + { + //xRot = xRot + speedRot; + yRot = yRot + speedRot; + zRot = zRot + 2 * speedRot; + } + + + + gl.uniformMatrix4fv(mMatLocation, gl.FALSE, mMat ); + gl.uniformMatrix4fv(vMatLocation, gl.FALSE, vMat ); + gl.uniformMatrix4fv(pMatLocation, gl.FALSE, pMat ); + + if (!testGLError("gl.uniformMatrix4fv")) { + return false; + } + + gl.bindBuffer(gl.ARRAY_BUFFER, gl.vertexBuffer); + gl.enableVertexAttribArray(0); + gl.vertexAttribPointer(0, 3, gl.FLOAT, gl.FALSE, 28, 0); + gl.enableVertexAttribArray(1); + gl.vertexAttribPointer(1, 4, gl.FLOAT, gl.FALSE, 28, 12); + + if (!testGLError("gl.vertexAttribPointer")) { + return false; + } + + if ( flag_draw_stencil ) { + gl.enable(gl.STENCIL_TEST); + gl.stencilMask(0xFF); + gl.clearStencil(0); + gl.clear(gl.STENCIL_BUFFER_BIT); + gl.stencilFunc(gl.ALWAYS, 1, 255); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE); + gl.colorMask(false, false, false, false); + gl.drawArrays(draw_mode, 0, 6); + gl.stencilFunc(gl.EQUAL, 1, 255); + gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); + gl.colorMask(true, true, true, true); + } + + + gl.drawArrays(draw_mode, 0, 36); + + if ( flag_draw_twice ) { + gl.enable(gl.POLYGON_OFFSET_FILL); + mat4.translate(mMat, mMat, [0.000, 0.00, 0.0]); + mat4.rotateY(mMat, mMat, 3.141592/2.0); + gl.uniformMatrix4fv(mMatLocation, gl.FALSE, mMat ); + gl.drawArrays(draw_mode, 0, 36); + gl.disable(gl.POLYGON_OFFSET_FILL); + } + + if (!testGLError("gl.drawArrays")) { + return false; + } + return true; +} + +function main() { + var canvas = document.getElementById("helloapicanvas"); + + if (!initialiseGL(canvas)) { + return; + } + + if (!initialiseBuffer()) { + return; + } + + if (!initialiseShaders()) { + return; + } + + //fn_capture_stencil(); + //renderScene(); + //fn_make_clear_stencil(); + + requestAnimFrame = (function () { + return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || + function (callback) { + window.setTimeout(callback, 1000, 60); + }; + })(); + + (function renderLoop() { + if (renderScene()) { + // Everything was successful, request that we redraw our scene again in the future + requestAnimFrame(renderLoop); + } + })(); +}