// Mapping function function map(smin, smax, val, omin, omax) { const percent = (val - smin) / (smax - smin); return (omax - omin) * percent + omin; } /*======= Creating a canvas =========*/ var canvas = document.getElementById('my_Canvas'); var gl = canvas.getContext('webgl'); /*======= Filling values =========*/ var nc = 3; // Number of curves var courbe = [ [5, 0.1, 0.4, 0.7, 0.9, 1.0], // Example data [5, 0.2, 0.3, 0.6, 0.8, 0.95], [5, 0.05, 0.15, 0.5, 0.75, 0.85], ]; var valmin = [0.1, 0.2, 0.05]; var valmax = [1.0, 0.95, 0.85]; // Drawing modes const HORIZONTAL = 0; const VERTICAL = 1; const SUPERPOSER = 2; // Drawing types const LIGNE = 0; const LIGNE_AXES = 1; const HISTOGRAMME = 2; let mode_affichage = HORIZONTAL; let type_dessin = LIGNE_AXES; function toVertices(index) { const size = courbe[index][0]; var vertices = new Array(size*3).fill(0); let j = 0; for (let i = 1; i <= size; i++) { vertices[j] = map(1, size, i, -1, 1); if(mode_affichage == SUPERPOSER) { vertices[j+1] = map(valmin[index], valmax[index], courbe[index][i], -1, 1); }else { var start = map(0, nc, index, -1, 1); var end = map(0, nc, index+1, -1, 1); vertices[j+1] = map(valmin[index], valmax[index], courbe[index][i], start, end); if(mode_affichage == VERTICAL) { [vertices[j], vertices[j+1]] = [vertices[j+1], vertices[j]]; } } vertices[j+2] = 0; j += 3; } return vertices; } function getCurveVertices(index) { const size = courbe[index][0]; var vertices = toVertices(index); // Create an empty buffer object var vertex_buffer = gl.createBuffer(); // Bind appropriate array buffer to it gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); // Pass the vertex data to the buffer gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); // Unbind the buffer gl.bindBuffer(gl.ARRAY_BUFFER, null); //console.log(vertices); return vertex_buffer; } /*=================== Shaders ====================*/ function setShader(red) { // Vertex shader source code var vertCode = 'attribute vec3 coordinates;' + 'void main(void) {' + ' gl_Position = vec4(coordinates, 1.0);' + '}'; // Create a vertex shader object var vertShader = gl.createShader(gl.VERTEX_SHADER); // Attach vertex shader source code gl.shaderSource(vertShader, vertCode); // Compile the vertex shader gl.compileShader(vertShader); // Fragment shader source code var fragCode = ""; if(red == false) { var fragCode = 'void main(void) {' + 'gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);' + '}'; }else{ var fragCode = 'void main(void) {' + 'gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);' + '}'; } // Create fragment shader object var fragShader = gl.createShader(gl.FRAGMENT_SHADER); // Attach fragment shader source code gl.shaderSource(fragShader, fragCode); // Compile the fragmentt shader gl.compileShader(fragShader); // Create a shader program object to store // the combined shader program var shaderProgram = gl.createProgram(); // Attach a vertex shader gl.attachShader(shaderProgram, vertShader); // Attach a fragment shader gl.attachShader(shaderProgram, fragShader); // Link both the programs gl.linkProgram(shaderProgram); // Use the combined shader program object gl.useProgram(shaderProgram); return shaderProgram; } var shaderProgramRed = setShader(true); var shaderProgram = setShader(false); function draw(index) { var vertex_buffer = getCurveVertices(index); // Bind vertex buffer object gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); // Get the attribute location var coord = gl.getAttribLocation(shaderProgram, "coordinates"); // Point an attribute to the currently bound VBO gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0); // Enable the attribute gl.enableVertexAttribArray(coord); // Set the view port gl.viewport(0,0,canvas.width,canvas.height); // Draw the triangle gl.drawArrays(gl.LINE_STRIP, 0, courbe[index][0]); } function axe(index, ax) { const size = courbe[index][0]; x_start = -1.0; x_end = map(1, size, ax+1, -1, 1); y_start = -1; y_end = map(valmin[index], valmax[index], courbe[index][ax+1], -1, 1); if(mode_affichage != SUPERPOSER) { y_start = map(0, nc, index, -1, 1); var end = map(0, nc, index+1, -1, 1); y_end = map(valmin[index], valmax[index], courbe[index][ax+1], y_start, end); } if(mode_affichage == VERTICAL) { [x_start, y_start] = [y_start, x_start]; [x_end, y_end] = [y_end, x_end]; } var vertices = [ x_start, y_end, 0.0, x_end, y_end, 0.0, x_end, y_end, 0.0, x_end, y_start, 0.0, ] return vertices; } function drawAxes(index) { const size = courbe[index][0]; var vertices = []; for(let i = 1; i < size; i++) { let v = axe(index, i); vertices.push(...v); } //console.log(vertices); // Create an empty buffer object var vertex_buffer = gl.createBuffer(); // Bind appropriate array buffer to it gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); // Pass the vertex data to the buffer gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); // Get the attribute location var coord = gl.getAttribLocation(shaderProgram, "coordinates"); // Point an attribute to the currently bound VBO gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0); // Enable the attribute gl.enableVertexAttribArray(coord); // Set the view port gl.viewport(0,0,canvas.width,canvas.height); gl.useProgram(shaderProgramRed); // Draw the triangle gl.drawArrays(gl.LINES, 0, (courbe[index][0]-1) * 4); gl.useProgram(shaderProgram); } function square(index, squ) { const size = courbe[index][0]; x_start = map(1, size, squ, -1, 1); x_end = map(1, size, squ+1, -1, 1); y_start = -1; y_end = map(valmin[index], valmax[index], courbe[index][squ], -1, 1); if(mode_affichage != SUPERPOSER) { y_start = map(0, nc, index, -1, 1); var end = map(0, nc, index+1, -1, 1); y_end = map(valmin[index], valmax[index], courbe[index][squ], y_start, end); } if(mode_affichage == VERTICAL) { [x_start, y_start] = [y_start, x_start]; [x_end, y_end] = [y_end, x_end]; } var vertices = [ x_start, y_start, 0, x_end, y_start, 0, x_end, y_end, 0, x_start, y_end, 0 ] return vertices; } function drawHisto(index) { const size = courbe[index][0]; for(let i = 1; i < size; i++) { var vertices = square(index, i); //console.log(i); //console.log(vertices); indices = [0, 2, 1, 0, 3, 2]; // Create an empty buffer object to store vertex buffer var vertex_buffer = gl.createBuffer(); // Bind appropriate array buffer to it gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); // Pass the vertex data to the buffer gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW); // Unbind the buffer gl.bindBuffer(gl.ARRAY_BUFFER, null); // Create an empty buffer object to store Index buffer var Index_Buffer = gl.createBuffer(); // Bind appropriate array buffer to it gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer); // Pass the vertex data to the buffer gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STATIC_DRAW); // Unbind the buffer gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null); // Bind vertex buffer object gl.bindBuffer(gl.ARRAY_BUFFER, vertex_buffer); // Bind index buffer object gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, Index_Buffer); // Get the attribute location var coord = gl.getAttribLocation(shaderProgram, "coordinates"); // Point an attribute to the currently bound VBO gl.vertexAttribPointer(coord, 3, gl.FLOAT, false, 0, 0); // Enable the attribute gl.enableVertexAttribArray(coord); // Set the view port gl.viewport(0,0,canvas.width,canvas.height); // Draw the triangle gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT,0); } } gl.clearColor(0, 0, 0, 0.5); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); for(var i = 0; i < nc; i++) { if(type_dessin == HISTOGRAMME) { drawHisto(i); }else{ draw(i); if(type_dessin == LIGNE_AXES) { drawAxes(i); } } }