From f7b8365847893d9675a2e2c83713366b270db006 Mon Sep 17 00:00:00 2001 From: "jorge.josegonc" <jorge.jose-goncalves@etu.hesge.ch> Date: Wed, 16 Dec 2020 10:22:10 +0100 Subject: [PATCH] rotation and shadow with ponct light good but have not directionnal and ambient and a good method for select hourglass --- lab4/src/lab4.js | 696 +++++++++++++++++++++++------------------------ 1 file changed, 348 insertions(+), 348 deletions(-) diff --git a/lab4/src/lab4.js b/lab4/src/lab4.js index 14aadf2..cdd4abf 100644 --- a/lab4/src/lab4.js +++ b/lab4/src/lab4.js @@ -2,167 +2,145 @@ Author : Jorge José Goncalves */ -// variable for camera and light -var eyeX = 2; -var eyeY = 4; -var eyeZ = 6; -const STEP = 0.1; -var lightDirectionnalX = 0.5; -var lightDirectionnalY = 3.0; -var lightDirectionnalZ = 4.0; -var lightPositionX = 0.0; -var lightPositionY = 5.0; -var lightPositionZ = 0.0; -var OFFSCREEN_WIDTH = 2048; -var OFFSCREEN_HEIGHT = 2048; -var clicked_canvas = false; -var x_clicked = 0; -var y_clicked = 0; -var VSHADER_SOURCE_DIRECTIONNAL_LIGHT = +// Vertex shader program for generating a shadow map +var SHADOW_VSHADER_SOURCE = 'attribute vec4 a_Position;\n' + - 'attribute vec4 a_Color;\n' + - 'attribute vec4 a_Normal;\n' + - 'uniform mat4 mMVP;\n' + - 'uniform mat4 mNormal;\n' + - 'uniform vec3 vLightDirection;\n' + - 'varying vec4 v_Color;\n' + + 'uniform mat4 u_MvpMatrix;\n' + 'void main() {\n' + - ' gl_Position = mMVP * a_Position;\n' + - ' vec4 normal = mNormal * a_Normal;\n' + - ' float nDotL = max(dot(normalize(normal.xyz), vLightDirection), 0.0);\n' + - ' v_Color = vec4(a_Color.xyz * nDotL, a_Color.a);\n' + + ' gl_Position = u_MvpMatrix * a_Position;\n' + '}\n'; -var FSHADER_SOURCE_DIRECTIONNAL_LIGHT = +// Fragment shader program for generating a shadow map +var SHADOW_FSHADER_SOURCE = '#ifdef GL_ES\n' + 'precision mediump float;\n' + '#endif\n' + - 'varying vec4 v_Color;\n' + 'void main() {\n' + - ' gl_FragColor = v_Color;\n' + + ' gl_FragColor = vec4(gl_FragCoord.z, 0.0, 0.0, 0.0);\n' + // Write the z-value in R '}\n'; - var VSHADER_SOURCE_PONCTUAL_LIGHT = +// Vertex shader program for regular drawing +var VSHADER_SOURCE = 'attribute vec4 a_Position;\n' + 'attribute vec4 a_Color;\n' + 'attribute vec4 a_Normal;\n' + - 'uniform mat4 mMVP;\n' + - 'uniform mat4 mModel;\n' + - 'uniform mat4 mNormal;\n' + - 'varying vec4 v_Color;\n' + - 'varying vec3 normal;\n' + - 'varying vec4 vertexPosition;\n' + - 'uniform bool u_Clicked;\n' + - 'uniform bool u_is_hourglass;\n' + + 'uniform mat4 u_MvpMatrix;\n' + 'uniform mat4 u_MvpMatrixFromLight;\n' + 'varying vec4 v_PositionFromLight;\n' + + 'varying vec4 v_Color;\n' + + 'varying vec3 v_normal;\n' + + 'uniform mat4 u_NormalMatrix;\n' + + 'uniform bool u_Clicked;\n' + + 'varying vec4 v_VertexPosition;\n' + + 'uniform mat4 u_ModelMatrix;\n' + 'void main() {\n' + - ' gl_Position = mMVP * a_Position;\n' + - ' normal = normalize(vec3(mNormal * a_Normal));\n' + - ' vertexPosition = mModel * a_Position;\n' + - ' if(u_Clicked && u_is_hourglass) {\n' + + ' gl_Position = u_MvpMatrix * a_Position;\n' + + ' v_normal = normalize(vec3(u_NormalMatrix * a_Normal));\n' + + ' v_VertexPosition = u_ModelMatrix * a_Position;\n' + + ' v_PositionFromLight = u_MvpMatrixFromLight * a_Position;\n' + + ' if(u_Clicked && a_Color != vec4(1.0, 1.0, 1.0, 1.0)) {\n' + ' v_Color = vec4(0.0, 1.0, 0.0, 1.0);\n' + ' } else {\n' + ' v_Color = a_Color;\n' + ' }\n' + '}\n'; -var FSHADER_SOURCE_PONCTUAL_LIGHT = +// Fragment shader program for regular drawing +var FSHADER_SOURCE = '#ifdef GL_ES\n' + 'precision mediump float;\n' + '#endif\n' + - 'varying vec4 v_Color;\n' + - 'uniform vec3 vLightColor;\n' + - 'uniform vec3 vLightPosition;\n' + - 'varying vec3 normal;\n' + - 'varying vec4 vertexPosition;\n' + + 'uniform sampler2D u_ShadowMap;\n' + 'varying vec4 v_PositionFromLight;\n' + + 'varying vec4 v_Color;\n' + + 'varying vec3 v_normal;\n' + + 'varying vec4 v_VertexPosition;\n' + + 'uniform vec3 u_LightPosition;\n' + + 'uniform vec3 u_LightColor;\n' + 'void main() {\n' + - ' vec3 vLightDirection = normalize(vLightPosition - vec3(vertexPosition));\n' + - ' float nDotL = max(dot(normal, vLightDirection), 0.0);\n' + - ' vec3 diffuse = vLightColor * v_Color.rgb * nDotL;\n' + - ' gl_FragColor = vec4(diffuse, v_Color.a);\n' + + ' vec3 lightDirection = normalize(u_LightPosition - vec3(v_VertexPosition));\n' + + ' float nDotL = max(dot(v_normal, lightDirection), 0.0);\n' + + ' vec3 diffuse = u_LightColor * v_Color.rgb * nDotL;\n' + + ' vec3 shadowCoord = (v_PositionFromLight.xyz/v_PositionFromLight.w)/2.0 + 0.5;\n' + + ' vec4 rgbaDepth = texture2D(u_ShadowMap, shadowCoord.xy);\n' + + ' float depth = rgbaDepth.r;\n' + // Retrieve the z-value from R + ' float visibility = (shadowCoord.z > depth + 0.005) ? 0.0 : 1.0;\n' + + ' gl_FragColor = vec4(diffuse * visibility, v_Color.a);\n' + '}\n'; -var SHADOW_VSHADER_SOURCE = - 'attribute vec4 a_Position;\n' + - 'uniform mat4 u_MvpMatrix;\n' + - 'void main() {\n' + - ' gl_Position = u_MvpMatrix * a_Position;\n' + - '}\n'; +const PERSPECTIVE_WIDTH_FROM_LIGHT = 2048 +const PERSPECTIVE_HEIGHT_FROM_LIGHT = 2048 -var SHADOW_FSHADER_SOURCE = -'#ifdef GL_ES\n' + -'precision mediump float;\n' + -'#endif\n' + -'void main() {\n' + -' gl_FragColor = vec4(gl_FragCoord.z, 0.0, 0.0, 0.0);\n' + // Write the z-value in R -'}\n'; +// Step when change with keys +const STEP = 0.1; -function main() { - //directionnal_light(); - ponctual_light(); - // Control camera or lights - document.addEventListener("keydown", (event) => { - switch (event.key) { - case 'a': - eyeX -= STEP; - break; - case 'd': - eyeX += STEP; - break; - case 's': - eyeY -= STEP; - break; - case 'w': - eyeY += STEP; - break; - case 'r': - eyeZ -= STEP; - break; - case 'f': - eyeZ += STEP; - break; - case 'ArrowRight': - lightDirectionnalX += STEP; - lightPositionX += STEP; - break; - case 'ArrowLeft': - lightDirectionnalX -= STEP; - lightPositionX -= STEP; - break; - case 'ArrowDown': - lightDirectionnalY -= STEP; - lightPositionY -= STEP; - break; - case 'ArrowUp': - lightDirectionnalY += STEP; - lightPositionY += STEP; - break; - case 'z': - lightDirectionnalZ += STEP; - lightPositionZ += STEP; - break; - case 'h': - lightDirectionnalZ -= STEP; - lightPositionZ -= STEP; - break; - default: - break; - } +// For light position +var light_x = 0 +var light_y = 1 +var light_z = 2; + +// For camera position +var eye_x = 2; +var eye_y = 4; +var eye_z = 6; + +// Coordinate transformation matrix +var tmp_modelMatrix = new Matrix4(); +var tmp_mvpMatrix = new Matrix4(); +var tmp_normalMatrix = new Matrix4(); +var rotationSecFrustrumMatrix = new Matrix4(); +var translateFrustrumMatrix = new Matrix4(); + +// Event of key down, move camera or light positions +document.addEventListener("keydown", (event) => { + switch (event.key) { + case 'a': + eye_x -= STEP; + break; + case 'd': + eye_x += STEP; + break; + case 's': + eye_y -= STEP; + break; + case 'w': + eye_y += STEP; + break; + case 'r': + eye_z -= STEP; + break; + case 'f': + eye_z += STEP; + break; + case 'ArrowRight': + light_x += STEP; + break; + case 'ArrowLeft': + light_x -= STEP; + break; + case 'ArrowDown': + light_y -= STEP; + break; + case 'ArrowUp': + light_y += STEP; + break; + case 'z': + light_z += STEP; + break; + case 'h': + light_z -= STEP; + break; + default: + break; + } - // update html - document.getElementById("light_x_dir").textContent = "Light X directionnal : " + lightDirectionnalX - document.getElementById("light_y_dir").textContent = "Light Y directionnal : " + lightDirectionnalY - document.getElementById("light_z_dir").textContent = "Light Z directionnal : : " + lightDirectionnalZ - - document.getElementById("light_x_point").textContent = "Light X point : " + lightPositionX - document.getElementById("light_y_point").textContent = "Light Y point : " + lightPositionY - document.getElementById("light_z_point").textContent = "Light Z point : " + lightPositionZ - }); -} + document.getElementById("light_x_point").textContent = "Light X point : " + light_x + document.getElementById("light_y_point").textContent = "Light Y point : " + light_y + document.getElementById("light_z_point").textContent = "Light Z point : " + light_z +}); -function directionnal_light() { +function main() { + // Retrieve <canvas> element var canvas = document.getElementById('my-canvas'); // Get the rendering context for WebGL @@ -172,67 +150,40 @@ function directionnal_light() { return; } - // Initialize shaders for light directionnal - if (!initShaders(gl, VSHADER_SOURCE_DIRECTIONNAL_LIGHT, FSHADER_SOURCE_DIRECTIONNAL_LIGHT)) { - console.log('Failed to intialize shaders.'); - return; - } - - // Set the clear color and enable the depth test - gl.clearColor(0, 0, 0, 1); - gl.enable(gl.DEPTH_TEST); - - // Get the storage locations - var mMVP = gl.getUniformLocation(gl.program, 'mMVP'); - var mNormal = gl.getUniformLocation(gl.program, 'mNormal'); - var vLightDirection = gl.getUniformLocation(gl.program, 'vLightDirection'); - if (!mMVP || !mNormal || !vLightDirection) { - console.log('Failed to get the storage location'); - return; - } - - var vpMatrix = new Matrix4(); // View projection matrix - - var tick = function () { - // Set perspective and camera - vpMatrix.setPerspective(50, canvas.width / canvas.height, 1, 100); - vpMatrix.lookAt(eyeX, eyeY, eyeZ, 0, 0, 0, 0, 1, 0); - - // Set the light direction - var lightDirection = new Vector3([lightDirectionnalX, lightDirectionnalY, lightDirectionnalZ]); - lightDirection.normalize(); // Normalize - gl.uniform3fv(vLightDirection, lightDirection.elements); - - // Clear color and depth buffer - gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); - - // Draw - drawHourGlass(gl, vpMatrix, mMVP, mNormal, null, false); - drawPlaneBase(gl, vpMatrix, mMVP, mNormal, null, false); - - requestAnimationFrame(tick, canvas); - }; - tick(); -} - -function ponctual_light() { - var canvas = document.getElementById('my-canvas2'); - // Get the rendering context for WebGL - var gl = getWebGLContext(canvas); - if (!gl) { - console.log('Failed to get the rendering context for WebGL'); + // Create a program for generating a shadow map + var shadowProgram = createProgram(gl, SHADOW_VSHADER_SOURCE, SHADOW_FSHADER_SOURCE); + shadowProgram.a_Position = gl.getAttribLocation(shadowProgram, 'a_Position'); + shadowProgram.u_MvpMatrix = gl.getUniformLocation(shadowProgram, 'u_MvpMatrix'); + if (shadowProgram.a_Position < 0 || !shadowProgram.u_MvpMatrix) { + console.log('Failed to get the storage location of attribute or uniform variable from shadowProgram'); return; } - // Initialize shaders shadow - if (!initShaders(gl, SHADOW_VSHADER_SOURCE, SHADOW_FSHADER_SOURCE)) { - console.log('Failed to intialize shaders.'); + // Create the normal program + var normalProgram = createProgram(gl, VSHADER_SOURCE, FSHADER_SOURCE); + normalProgram.a_Position = gl.getAttribLocation(normalProgram, 'a_Position'); + normalProgram.a_Color = gl.getAttribLocation(normalProgram, 'a_Color'); + normalProgram.a_Normal = gl.getAttribLocation(normalProgram, 'a_Normal'); + normalProgram.u_MvpMatrix = gl.getUniformLocation(normalProgram, 'u_MvpMatrix'); + normalProgram.u_MvpMatrixFromLight = gl.getUniformLocation(normalProgram, 'u_MvpMatrixFromLight'); + normalProgram.u_ShadowMap = gl.getUniformLocation(normalProgram, 'u_ShadowMap'); + normalProgram.u_Clicked = gl.getUniformLocation(normalProgram, 'u_Clicked'); + normalProgram.u_NormalMatrix = gl.getUniformLocation(normalProgram, 'u_NormalMatrix'); + normalProgram.u_ModelMatrix = gl.getUniformLocation(normalProgram, 'u_ModelMatrix'); + normalProgram.u_LightPosition = gl.getUniformLocation(normalProgram, 'u_LightPosition'); + normalProgram.u_LightColor = gl.getUniformLocation(normalProgram, 'u_LightColor'); + if (normalProgram.a_Position < 0 || normalProgram.a_Color < 0 || normalProgram.a_Normal < 0 || !normalProgram.u_MvpMatrix || + !normalProgram.u_MvpMatrixFromLight || !normalProgram.u_ShadowMap || !normalProgram.u_Clicked || !normalProgram.u_NormalMatrix || + !normalProgram.u_ModelMatrix || !normalProgram.u_LightPosition || !normalProgram.u_LightColor) { + console.log('Failed to get the storage location of attribute or uniform variable from normalProgram'); return; } - // Initialize shaders - if (!initShaders(gl, VSHADER_SOURCE_PONCTUAL_LIGHT, FSHADER_SOURCE_PONCTUAL_LIGHT)) { - console.log('Failed to intialize shaders.'); + // Set the vertex information of objects for the draw + var frustrum = initVertexBuffersForFrustrum(gl); + var plane = initVertexBuffersForPlane(gl); + if (!frustrum || !plane) { + console.log('Failed to set the vertex information'); return; } @@ -242,27 +193,42 @@ function ponctual_light() { console.log('Failed to initialize frame buffer object'); return; } - gl.activeTexture(gl.TEXTURE0); // Set a texture object to the texture unit + + // Set a texture object to the texture unit + gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, fbo.texture); // Set the clear color and enable the depth test gl.clearColor(0, 0, 0, 1); gl.enable(gl.DEPTH_TEST); - // Get the storage locations - var mModel = gl.getUniformLocation(gl.program, 'mModel'); - var mMVP = gl.getUniformLocation(gl.program, 'mMVP'); - var mNormal = gl.getUniformLocation(gl.program, 'mNormal'); - var vLightColor = gl.getUniformLocation(gl.program, 'vLightColor'); - var vLightPosition = gl.getUniformLocation(gl.program, 'vLightPosition'); - var u_Clicked = gl.getUniformLocation(gl.program, 'u_Clicked'); - var u_is_hourglass = gl.getUniformLocation(gl.program, 'u_is_hourglass'); - if (!mMVP || !mNormal || !vLightColor || !vLightPosition || !mModel || !u_Clicked) { - console.log('Failed to get the storage location'); - return; - } - - canvas.onmousedown = function(ev) { // Mouse is pressed + // View project for shadow map + var viewProjMatrixFromLight = new Matrix4(); + viewProjMatrixFromLight.setPerspective(200.0, PERSPECTIVE_WIDTH_FROM_LIGHT/PERSPECTIVE_HEIGHT_FROM_LIGHT, 1.0, 100.0); + viewProjMatrixFromLight.lookAt(light_x, light_y, light_z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + + // View project for normal program + var viewProjMatrix = new Matrix4(); + viewProjMatrix.setPerspective(45, canvas.width/canvas.height, 1.0, 100.0); + viewProjMatrix.lookAt(eye_x, eye_y, eye_z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + + // For the animation of hourglass + var animateHourGlass = false; + var currentAngle = 0.0; + var oldAngle = 0.0; + + // A mvp for the 3 objects (2 frustrum and 1 plane) + var mvpMatrixFromLight_f = new Matrix4(); + var mvpMatrixFromLight_f2 = new Matrix4(); + var mvpMatrixFromLight_p = new Matrix4(); + + // Save data when event mouse clicked is active + var clicked_canvas = false; + var x_clicked = 0; + var y_clicked = 0; + + // Event when mouse is clicked + canvas.onmousedown = function(ev) { var x = ev.clientX, y = ev.clientY; var rect = ev.target.getBoundingClientRect(); if (rect.left <= x && x < rect.right && rect.top <= y && y < rect.bottom) { @@ -272,162 +238,184 @@ function ponctual_light() { } } - var vpMatrix = new Matrix4(); // View projection matrix + // Tick for create a shadow map and drawing + var tick = function() { + + // View project for light + viewProjMatrixFromLight.setPerspective(200.0, PERSPECTIVE_WIDTH_FROM_LIGHT/PERSPECTIVE_HEIGHT_FROM_LIGHT, 1.0, 100.0); + viewProjMatrixFromLight.lookAt(light_x, light_y, light_z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + + // View project for camera + viewProjMatrix.setPerspective(45, canvas.width/canvas.height, 1.0, 100.0); + viewProjMatrix.lookAt(eye_x, eye_y, eye_z, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0); + + // Animate 180 degrees and change color of hourglass + if(animateHourGlass){ + oldAngle = currentAngle + currentAngle += 1.0; + if(oldAngle >= 359 && gl.getUniform(normalProgram, normalProgram.u_Clicked) == 0){ + animateHourGlass = false; + currentAngle = 0; + } else if(oldAngle >= 179 && gl.getUniform(normalProgram, normalProgram.u_Clicked) == 1){ + animateHourGlass = false; + currentAngle = 180; + } + } + + // Use of framebuffer object for shadow map + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + gl.viewport(0, 0, PERSPECTIVE_WIDTH_FROM_LIGHT, PERSPECTIVE_HEIGHT_FROM_LIGHT); + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); - var tick = function () { - // Set perspective and camera - vpMatrix.setPerspective(50, canvas.width / canvas.height, 1, 100); - vpMatrix.lookAt(eyeX, eyeY, eyeZ, 0, 0, 0, 0, 1, 0); + // Use the programm shadow for generating a shadow map + gl.useProgram(shadowProgram); - // Set the light color (white) - gl.uniform3f(vLightColor, 1.0, 1.0, 1.0); - // Set the light position - gl.uniform3f(vLightPosition, lightPositionX, lightPositionY, lightPositionZ); + // Draw the two frustrum and plane for the shadow map + drawFrustrum(gl, shadowProgram, frustrum, currentAngle, viewProjMatrixFromLight, false); + mvpMatrixFromLight_f.set(tmp_mvpMatrix); + drawFrustrum(gl, shadowProgram, frustrum, currentAngle, viewProjMatrixFromLight, true); + mvpMatrixFromLight_f2.set(tmp_mvpMatrix); + drawPlane(gl, shadowProgram, plane, viewProjMatrixFromLight); + mvpMatrixFromLight_p.set(tmp_mvpMatrix); - // Clear color and depth buffer + // Use the normal program and the default framebuffer + gl.bindFramebuffer(gl.FRAMEBUFFER, null); + gl.viewport(0, 0, canvas.width, canvas.height); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); - drawHourGlass(gl, vpMatrix, mMVP, mNormal, mModel, true, u_Clicked, u_is_hourglass); - drawPlaneBase(gl, vpMatrix, mMVP, mNormal, mModel, true, u_is_hourglass); + gl.useProgram(normalProgram); + gl.uniform3f(normalProgram.u_LightColor, 1.0, 1.0, 1.0); // The light is white + gl.uniform3f(normalProgram.u_LightPosition, light_x, light_y, light_z); + gl.uniform1i(normalProgram.u_ShadowMap, 0); // Pass 0 because gl.TEXTURE0 is enabled + + // Draw the two frustrum and plane for the normal program + gl.uniformMatrix4fv(normalProgram.u_MvpMatrixFromLight, false, mvpMatrixFromLight_f.elements); + drawFrustrum(gl, normalProgram, frustrum, currentAngle, viewProjMatrix, false); + gl.uniformMatrix4fv(normalProgram.u_MvpMatrixFromLight, false, mvpMatrixFromLight_f2.elements); + drawFrustrum(gl, normalProgram, frustrum, currentAngle, viewProjMatrix, true); + gl.uniformMatrix4fv(normalProgram.u_MvpMatrixFromLight, false, mvpMatrixFromLight_p.elements); + drawPlane(gl, normalProgram, plane, viewProjMatrix); + + // Change color and animate when clicked + if(clicked_canvas && animateHourGlass == false){ + var pixels = new Uint8Array(4); + gl.readPixels(x_clicked, y_clicked, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + if(pixels[0] > 0 && pixels[1] == 0 && pixels[2] == 0){ + gl.uniform1i(normalProgram.u_Clicked, 1); + animateHourGlass = true; + } + else if(pixels[0] == 0 && pixels[1] > 0 && pixels[2] == 0){ + gl.uniform1i(normalProgram.u_Clicked, 0); + animateHourGlass = true; + } + clicked_canvas = false; + } - requestAnimationFrame(tick, canvas); + window.requestAnimationFrame(tick, canvas); }; - tick(); + tick(); } -function drawPlaneBase(gl, vpMatrix, mMVP, mNormal, mModel, isPonct, u_is_hourglass) { - gl.uniform1i(u_is_hourglass, 0); - var n = initVertexBuffersPlaneBase(gl); - if (n < 0) { - console.log('Failed to set the vertex information'); - return; +function drawFrustrum(gl, program, frustrum, angle, viewProjMatrix, is_second) { + // Rotate for the animation + tmp_modelMatrix.setRotate(angle, 1, 0, 0); + + // Rotate the second frustrum + if(is_second){ + rotationSecFrustrumMatrix.setRotate(180, 1, 0, 0) + tmp_modelMatrix.multiply(rotationSecFrustrumMatrix); } - var modelMatrixTranslate = new Matrix4(); - var mvpMatrix = new Matrix4(); - var normalMatrix = new Matrix4(); - - modelMatrixTranslate.setTranslate(0, -0.001, 0); - if (isPonct) { - gl.uniformMatrix4fv(mModel, false, modelMatrixTranslate.elements); - } - mvpMatrix.set(vpMatrix).multiply(modelMatrixTranslate); - gl.uniformMatrix4fv(mMVP, false, mvpMatrix.elements); - normalMatrix.setInverseOf(modelMatrixTranslate); - normalMatrix.transpose(); - gl.uniformMatrix4fv(mNormal, false, normalMatrix.elements); + // Change translate to have a good rotate animation + translateFrustrumMatrix.setTranslate(0, -1, 0); + tmp_modelMatrix.multiply(translateFrustrumMatrix); + draw(gl, program, frustrum, viewProjMatrix); +} - gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0); +function drawPlane(gl, program, plane, viewProjMatrix) { + // translate the plane to be good with the hourglass + tmp_modelMatrix.setTranslate(0, -1, 0); + draw(gl, program, plane, viewProjMatrix); } -var angle = 0; -var trans = 0; -function drawHourGlass(gl, vpMatrix, mMVP, mNormal, mModel, isPonct, u_Clicked, u_is_hourglass) { - //angle += 1; - gl.uniform1i(u_is_hourglass, 1); - var n = initVertexBuffersHourglass(gl); - if (n < 0) { - console.log('Failed to set the vertex information'); - return; +function draw(gl, program, o, viewProjMatrix) { + initAttributeVariable(gl, program.a_Position, o.vertexBuffer); + + // If programm shadow, he can't have the color buffer or normal buffer + if (program.a_Color != undefined){ + initAttributeVariable(gl, program.a_Color, o.colorBuffer); } - var modelMatrixRotate = new Matrix4(); // Model matrix - var modelMatrixTranslate = new Matrix4(); - var modelMatrixScale = new Matrix4(); - var mvpMatrix = new Matrix4(); // Model view projection matrix - var normalMatrix = new Matrix4(); // Transformation matrix for normals - - // First frustrum - modelMatrixRotate.setRotate(0 + angle, 1, 0, 0); // Rotate around the y-axis - modelMatrixTranslate.setTranslate(0, 0.0 - trans, 0); - var finalModelMatrix = modelMatrixRotate.multiply(modelMatrixTranslate).multiply(modelMatrixScale); - if (isPonct) { - gl.uniformMatrix4fv(mModel, false, finalModelMatrix.elements); + if (program.a_Normal != undefined){ + initAttributeVariable(gl, program.a_Normal, o.normalsBuffer); } + + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, o.indexBuffer); - mvpMatrix.set(vpMatrix).multiply(modelMatrixRotate); - gl.uniformMatrix4fv(mMVP, false, mvpMatrix.elements); - normalMatrix.setInverseOf(modelMatrixRotate); - normalMatrix.transpose(); - gl.uniformMatrix4fv(mNormal, false, normalMatrix.elements); + // Calculate the mvp matrix and pass it to u_MvpMatrix + tmp_mvpMatrix.set(viewProjMatrix); + tmp_mvpMatrix.multiply(tmp_modelMatrix); + gl.uniformMatrix4fv(program.u_MvpMatrix, false, tmp_mvpMatrix.elements); - - gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0); - - // Second frustrum - modelMatrixRotate.setRotate(180 + angle, 1, 0, 0); - modelMatrixTranslate.setTranslate(0, -2.0 + trans, 0); - modelMatrixScale.setScale(-1, 1, -1); - var finalModelMatrix = modelMatrixRotate.multiply(modelMatrixTranslate).multiply(modelMatrixScale); - if (isPonct) { - gl.uniformMatrix4fv(mModel, false, finalModelMatrix.elements); - } - mvpMatrix.set(vpMatrix).multiply(finalModelMatrix) - gl.uniformMatrix4fv(mMVP, false, mvpMatrix.elements); - normalMatrix.setInverseOf(finalModelMatrix); - normalMatrix.transpose(); - gl.uniformMatrix4fv(mNormal, false, normalMatrix.elements); - gl.drawElements(gl.TRIANGLES, n, gl.UNSIGNED_BYTE, 0); - - if(clicked_canvas){ - var pixels = new Uint8Array(4); // Array for storing the pixel value - gl.readPixels(x_clicked, y_clicked, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels); - console.log(pixels); - if(pixels[0] > 0){ - console.log("Rouge"); - if(isPonct){ - gl.getUniform(gl.program, u_Clicked); - } - gl.uniform1i(u_Clicked, 1); - } - else if(pixels[1] > 0){ - console.log("Vert"); - gl.uniform1i(u_Clicked, 0); - } - clicked_canvas = false; - } + // Calculate normals + tmp_normalMatrix.setInverseOf(tmp_modelMatrix); + tmp_normalMatrix.transpose(); + gl.uniformMatrix4fv(program.u_NormalMatrix, false, tmp_normalMatrix.elements); + + // Stock the model matrix + gl.uniformMatrix4fv(program.u_ModelMatrix, false, tmp_modelMatrix.elements); + + gl.drawElements(gl.TRIANGLES, o.numIndices, gl.UNSIGNED_BYTE, 0); } -function initVertexBuffersPlaneBase(gl) { - var vertices_position = new Float32Array([ - -2.0, -0.5, -2.0, 2.0, -0.5, 2.0, -2.0, -0.5, 2.0, 2.0, -0.5, -2.0 +// Assign the buffer objects and enable the assignment +function initAttributeVariable(gl, a_attribute, buffer) { + gl.bindBuffer(gl.ARRAY_BUFFER, buffer); + gl.vertexAttribPointer(a_attribute, buffer.num, buffer.type, false, 0, 0); + gl.enableVertexAttribArray(a_attribute); +} + +function initVertexBuffersForPlane(gl) { + + // Vertex coordinates + var vertices = new Float32Array([ + -5.0, -0.5, -5.0, 5.0, -0.5, 5.0, -5.0, -0.5, 5.0, 5.0, -0.5, -5.0 ]); - // Colors only white for this tp + // Colors var colors = new Float32Array([ - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 ]); + // Normals var normals = new Float32Array([ 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0 ]); - var indices = new Uint8Array([ - 0, 1, 2, 0, 1, 3 - ]); + // Indices of the vertices + var indices = new Uint8Array([0, 1, 2, 0, 1, 3]); + + var o = new Object(); // Utilize Object object to return multiple buffer objects together - // Write the vertex property to buffers (positions, colors and normals) - if (!initArrayBuffer(gl, 'a_Position', vertices_position, 3, gl.FLOAT)) return -1; - if (!initArrayBuffer(gl, 'a_Color', colors, 3, gl.FLOAT)) return -1; - if (!initArrayBuffer(gl, 'a_Normal', normals, 3, gl.FLOAT)) return -1; + // Write vertex information to buffer object + o.vertexBuffer = initArrayBufferForLaterUse(gl, vertices, 3, gl.FLOAT); + o.colorBuffer = initArrayBufferForLaterUse(gl, colors, 3, gl.FLOAT); + o.normalsBuffer = initArrayBufferForLaterUse(gl, normals, 3, gl.FLOAT); + o.indexBuffer = initElementArrayBufferForLaterUse(gl, indices, gl.UNSIGNED_BYTE); + if (!o.vertexBuffer || !o.colorBuffer || !o.indexBuffer || !o.normalsBuffer) return null; + + o.numIndices = indices.length; // Unbind the buffer object gl.bindBuffer(gl.ARRAY_BUFFER, null); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); - // Write the indices to the buffer object - var indexBuffer = gl.createBuffer(); - if (!indexBuffer) { - console.log('Failed to create the buffer object'); - return false; - } - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); - - return indices.length; + return o; } -function initVertexBuffersHourglass(gl) { - var vertices_position = new Float32Array([ +function initVertexBuffersForFrustrum(gl) { + // Vertex coordinates + var vertices = new Float32Array([ -0.25, 1.0, 0.25, 0.5, -0.5, 0.5, -0.5, -0.5, 0.5, 0.25, 1.0, 0.25, // front face 0.25, 1.0, 0.25, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, 0.25, 1.0, -0.25,// right face -0.25, 1.0, -0.25, 0.25, 1.0, 0.25, -0.25, 1.0, 0.25, 0.25, 1.0, -0.25, // Up face @@ -436,7 +424,7 @@ function initVertexBuffersHourglass(gl) { 0.25, 1.0, -0.25, -0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.25, 1.0, -0.25 // back face ]); - // Colors only red for this tp + // Colors var colors = new Float32Array([ 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, @@ -445,17 +433,18 @@ function initVertexBuffersHourglass(gl) { 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0 ]); - + var normals = new Float32Array([ 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, // front face 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, // right face 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, // up face -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, -1.0, 1.0, 0.0, // left face 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, 0.0, -1.0, 0.0, // down face - 0.0, 1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, -1.0, // back face + 0.0, 1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, -1.0, 0.0, 1.0, -1.0 // back face ]); - var indices = new Uint8Array([ + // Indices of the vertices + var indices = new Uint8Array([ 0, 1, 2, 0, 1, 3, // front Face 4, 5, 6, 4, 5, 7, // right face 8, 9, 10, 8, 9, 11, // up face @@ -464,49 +453,59 @@ function initVertexBuffersHourglass(gl) { 20, 21, 22, 20, 21, 23 // back face ]); - // Write the vertex property to buffers (positions, colors and normals) - if (!initArrayBuffer(gl, 'a_Position', vertices_position, 3, gl.FLOAT)) return -1; - if (!initArrayBuffer(gl, 'a_Color', colors, 3, gl.FLOAT)) return -1; - if (!initArrayBuffer(gl, 'a_Normal', normals, 3, gl.FLOAT)) return -1; + var o = new Object(); // Utilize Object object to return multiple buffer objects together + + // Write vertex information to buffer object + o.vertexBuffer = initArrayBufferForLaterUse(gl, vertices, 3, gl.FLOAT); + o.colorBuffer = initArrayBufferForLaterUse(gl, colors, 3, gl.FLOAT); + o.normalsBuffer = initArrayBufferForLaterUse(gl, normals, 3, gl.FLOAT); + o.indexBuffer = initElementArrayBufferForLaterUse(gl, indices, gl.UNSIGNED_BYTE); + if (!o.vertexBuffer || !o.colorBuffer || !o.indexBuffer || !o.normalsBuffer) return null; + + o.numIndices = indices.length; // Unbind the buffer object gl.bindBuffer(gl.ARRAY_BUFFER, null); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); - // Write the indices to the buffer object - var indexBuffer = gl.createBuffer(); - if (!indexBuffer) { - console.log('Failed to create the buffer object'); - return false; - } - gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); - gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indices, gl.STATIC_DRAW); - - return indices.length; + return o; } -function initArrayBuffer(gl, attribute, data, num, type) { +function initArrayBufferForLaterUse(gl, data, num, type) { // Create a buffer object var buffer = gl.createBuffer(); if (!buffer) { console.log('Failed to create the buffer object'); - return false; + return null; } // Write date into the buffer object gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW); - // Assign the buffer object to the attribute variable - var a_attribute = gl.getAttribLocation(gl.program, attribute); - if (a_attribute < 0) { - console.log('Failed to get the storage location of ' + attribute); - return false; + + // Store the necessary information to assign the object to the attribute variable later + buffer.num = num; + buffer.type = type; + + return buffer; +} + +function initElementArrayBufferForLaterUse(gl, data, type) { + // Create a buffer object + var buffer = gl.createBuffer(); + if (!buffer) { + console.log('Failed to create the buffer object'); + return null; } - gl.vertexAttribPointer(a_attribute, num, type, false, 0, 0); - // Enable the assignment of the buffer object to the attribute variable - gl.enableVertexAttribArray(a_attribute); + // Write date into the buffer object + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, buffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, data, gl.STATIC_DRAW); + + buffer.type = type; - return true; + return buffer; } +// Create the framebuffer fbo for shadow map function initFramebufferObject(gl) { var framebuffer, texture, depthBuffer; @@ -531,8 +530,9 @@ function initFramebufferObject(gl) { console.log('Failed to create texture object'); return error(); } + gl.bindTexture(gl.TEXTURE_2D, texture); - gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); + gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, PERSPECTIVE_WIDTH_FROM_LIGHT, PERSPECTIVE_HEIGHT_FROM_LIGHT, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); // Create a renderbuffer object and Set its size and parameters @@ -542,7 +542,7 @@ function initFramebufferObject(gl) { return error(); } gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); - gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, OFFSCREEN_WIDTH, OFFSCREEN_HEIGHT); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, PERSPECTIVE_WIDTH_FROM_LIGHT, PERSPECTIVE_HEIGHT_FROM_LIGHT); // Attach the texture and the renderbuffer object to the FBO gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); -- GitLab