简体   繁体   中英

Create a new model matrix Webgl

I am new to webgl and I've been trying to create two cubes that rotate around their own axis, but right now, they rotate only according to one axis. I would like to know what I am doing wrong, (I think it's because I need to create a new model matrix for the rotation but I am not sure how to do that). Thank you!

 // Application info. var app = app || {}; function initGL() { var gl = app.gl; gl.enable(gl.DEPTH_TEST); gl.depthFunc(gl.LEQUAL); gl.viewport(0,0,app.can.width, app.can.height); gl.clearColor(0.,0.,0., 1.0); gl.clear(app.gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); var vs = createShaderFromElement(app.gl, "vs"); var fs = createShaderFromElement(app.gl, "fs"); app.progObject = buildProgram(app.gl, vs, fs); gl.useProgram(app.progObject); } function initScene() { var gl = app.gl; // Creer le buffer de geometrie (vertex) // var positions = [ // Front face -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, // Back face -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, // Top face -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, // Bottom face -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, // Right face 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, // Left face -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0 ]; app.nPoints = positions.length / 3; var colors = [ 1,1,1, 1,1,1, 1,1,1, 1,1,1, 1,1,1, 1,1,1, 1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, 1,0,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1 ]; var loc, buffer; // Create and copy position buffer. loc = gl.getAttribLocation(app.progObject, "pos"); buffer = gl.createBuffer(); gl.enableVertexAttribArray(loc); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.vertexAttribPointer(loc, 3, gl.FLOAT, false /*no normalization*/, 0 /*stride*/, 0 /*offset*/); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); // Create and copy color buffer. loc = gl.getAttribLocation(app.progObject, "color"); buffer = gl.createBuffer(); gl.enableVertexAttribArray(loc); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.vertexAttribPointer(loc, 3, gl.FLOAT, false /*no normalization*/, 0 /*stride*/, 0 /*offset*/); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW); // Look for uniforms. app.pmLocation = gl.getUniformLocation(app.progObject, "projMatrix"); app.mmLocation = gl.getUniformLocation(app.progObject, "modelMatrix"); app.vmLocation = gl.getUniformLocation(app.progObject, "viewMatrix"); var mat4 = glMatrix.mat4; app.projMatrix = mat4.create(); app.modelMatrix = mat4.create(); app.viewMatrix = mat4.create(); mat4.perspective(app.projMatrix, Math.PI / 4.0 /*45 degrees*/, 1, 0.1, 100); mat4.lookAt(app.viewMatrix, [0, 0, -10], [0, 0, 0], [0, 1, 0]); } function animate(time) { var gl = app.gl; var mat4 = glMatrix.mat4; // converts to seconds. var seconds = time * 1E-3; var dtime = time - app.oldTime; var angle = dtime * 0.001; mat4.rotateY(app.modelMatrix, app.modelMatrix, angle); var mm1 = mat4.create(); mat4.translate(mm1, app.modelMatrix, [2, 0, 0]); app.oldTime = time; gl.clear(app.gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.uniformMatrix4fv(app.pmLocation, false, app.projMatrix ); gl.uniformMatrix4fv(app.mmLocation, false, mm1 ); gl.uniformMatrix4fv(app.vmLocation, false, app.viewMatrix ); gl.drawArrays(gl.TRIANGLES, 0, app.nPoints); // Pour dessiner autre cube, calculer autre model matrix // et redessiner ... gl.drawArrays(gl.TRIANGLES, 0, app.nPoints); mat4.rotateY( app.modelMatrix, app.modelMatrix, angle) var mm2 = mat4.create(); mat4.translate(mm2, app.modelMatrix, [-2, 0, 0]); gl.uniformMatrix4fv(app.pmLocation, false, app.projMatrix); gl.uniformMatrix4fv(app.mmLocation, false, mm2); gl.uniformMatrix4fv(app.vmLocation, false, app.viewMatrix); gl.drawArrays(gl.TRIANGLES, 0, app.nPoints); window.requestAnimationFrame(animate); } function fovChanged(id, value) { console.log("FOV Angle: ", value); var label = document.getElementById( 'output-fov' ); label.innerHTML = value; } function farChanged(id, value) { console.log("Far Plane: ", value); var label = document.getElementById( 'output-far' ); label.innerHTML = value; } function init() { [app.can, app.gl] = getContextGL('can'); if (app.can == null || app.gl == null) { alert("Can't init canvas or context"); return; } app.can.width = app.can.height * (app.can.clientWidth / app.can.clientHeight); var rect = app.can.getBoundingClientRect(); app.scaleX = app.can.width / rect.width; app.scaleY = app.can.height / rect.height; initGL(); initScene(); app.oldTime = 0; animate(0); }
 div { } #main-div { display:inline-block; } #viewport, #manager { float: left; margin: auto; } .color { width:100px; height:50px; } .blue{ background:#0f0; } #viewport { width: 600px; height:700px; } #can { width: 600px; height: 500px; border:1px solid orange; } #manager { width: 200px; height:300px; padding: 0 0 0 5px; } #obj-list { width: 200px; }
 <!DOCTYPE html> <html> <head> <title>Cube Transform</title> <link rel="stylesheet" type="text/css" href="style.css"> <script src="transforms.js"></script> <script src="utils.js"></script> <script src="gl-matrix-min.js"></script> <script id="vs" type="x-shader/x-vertex"> precision mediump float; uniform mat4 projMatrix; uniform mat4 viewMatrix; uniform mat4 modelMatrix; attribute vec3 pos; attribute vec3 color; varying vec3 fColor; void main() { fColor = color; vec4 pt = vec4(pos, 1.0); gl_Position = projMatrix * viewMatrix * modelMatrix * pt; } </script> <script id="fs" type="x-shader/x-fragment"> precision mediump float; varying vec3 fColor; void main() { gl_FragColor = vec4(fColor,1); } </script> </head> <body onload="init();"> <div id="main-div"> <div id="viewport"> <canvas id="can" >Your browser doesn't seem to support canvas!</canvas> <div class="slider"> <span class="slider-label">FOV cam</span> <input id="fov" class="slider-input" type="range" min="20" max="90" step="1" value="0" onClick="fovChanged(this.id, this.value)" /> <span id="output-fov" class="slider-value">20</span> </div> <div class="slider"> <span class="slider-label">Far Plane</span> <input id="far" class="slider-input" type="range" min="5" max="30" step="0.1" value="0" onClick="farChanged(this.id, this.value)" /> <span id="output-far" class="slider-value">5</span> </div> </div> </div> </body> </html>

I'm not exactly sure what your code is trying to do.

In any case, in general to rotate in place to translate then rotate

mat = idenity
mat = mat * translation
mat = mat * rotation

or depending on the library

mat = identity
translate(mat, ...)
rotate(mat, ...)

or

mat = translation(...);
rotate(mat, ...);

etc.

 // Application info. var app = app || {}; function initGL() { var gl = app.gl; gl.enable(gl.DEPTH_TEST); gl.depthFunc(gl.LEQUAL); gl.viewport(0, 0, app.can.width, app.can.height); gl.clearColor(0., 0., 0., 1.0); gl.clear(app.gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); var vs = createShaderFromElement(app.gl, "vs"); var fs = createShaderFromElement(app.gl, "fs"); app.progObject = buildProgram(app.gl, vs, fs); gl.useProgram(app.progObject); } function initScene() { var gl = app.gl; // Creer le buffer de geometrie (vertex) // var positions = [ // Front face -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, // Back face -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0, -1.0, // Top face -1.0, 1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, -1.0, 1.0, -1.0, // Bottom face -1.0, -1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, 1.0, -1.0, -1.0, -1.0, // Right face 1.0, -1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, -1.0, // Left face -1.0, -1.0, -1.0, -1.0, -1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, 1.0, -1.0, 1.0, -1.0, -1.0, -1.0, -1.0 ]; app.nPoints = positions.length / 3; var colors = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1 ]; var loc, buffer; // Create and copy position buffer. loc = gl.getAttribLocation(app.progObject, "pos"); buffer = gl.createBuffer(); gl.enableVertexAttribArray(loc); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.vertexAttribPointer(loc, 3, gl.FLOAT, false /*no normalization*/ , 0 /*stride*/ , 0 /*offset*/ ); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW); // Create and copy color buffer. loc = gl.getAttribLocation(app.progObject, "color"); buffer = gl.createBuffer(); gl.enableVertexAttribArray(loc); gl.bindBuffer(gl.ARRAY_BUFFER, buffer); gl.vertexAttribPointer(loc, 3, gl.FLOAT, false /*no normalization*/ , 0 /*stride*/ , 0 /*offset*/ ); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW); // Look for uniforms. app.pmLocation = gl.getUniformLocation(app.progObject, "projMatrix"); app.mmLocation = gl.getUniformLocation(app.progObject, "modelMatrix"); app.vmLocation = gl.getUniformLocation(app.progObject, "viewMatrix"); var mat4 = glMatrix.mat4; app.projMatrix = mat4.create(); app.modelMatrix = mat4.create(); app.viewMatrix = mat4.create(); mat4.perspective(app.projMatrix, Math.PI / 4.0 /*45 degrees*/ , 1, 0.1, 100); mat4.lookAt(app.viewMatrix, [0, 0, -10], [0, 0, 0], [0, 1, 0]); } function animate(time) { var gl = app.gl; var mat4 = glMatrix.mat4; // converts to seconds. var seconds = time * 1E-3; var dtime = time - app.oldTime; var mm1 = mat4.create(); mat4.translate(mm1, app.modelMatrix, [2, 0, 0]); var angle = time * 0.001; mat4.rotateY(mm1, mm1, angle); app.oldTime = time; gl.clear(app.gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.uniformMatrix4fv(app.pmLocation, false, app.projMatrix); gl.uniformMatrix4fv(app.mmLocation, false, mm1); gl.uniformMatrix4fv(app.vmLocation, false, app.viewMatrix); gl.drawArrays(gl.TRIANGLES, 0, app.nPoints); // Pour dessiner autre cube, calculer autre model matrix // et redessiner ... gl.drawArrays(gl.TRIANGLES, 0, app.nPoints); var mm2 = mat4.create(); mat4.translate(mm2, app.modelMatrix, [-2, 0, 0]); mat4.rotateY(mm2, mm2, angle) gl.uniformMatrix4fv(app.pmLocation, false, app.projMatrix); gl.uniformMatrix4fv(app.mmLocation, false, mm2); gl.uniformMatrix4fv(app.vmLocation, false, app.viewMatrix); gl.drawArrays(gl.TRIANGLES, 0, app.nPoints); window.requestAnimationFrame(animate); } function fovChanged(id, value) { console.log("FOV Angle: ", value); var label = document.getElementById('output-fov'); label.innerHTML = value; } function farChanged(id, value) { console.log("Far Plane: ", value); var label = document.getElementById('output-far'); label.innerHTML = value; } function init() { [app.can, app.gl] = getContextGL('can'); if (app.can == null || app.gl == null) { alert("Can't init canvas or context"); return; } app.can.width = app.can.height * (app.can.clientWidth / app.can.clientHeight); var rect = app.can.getBoundingClientRect(); app.scaleX = app.can.width / rect.width; app.scaleY = app.can.height / rect.height; initGL(); initScene(); app.oldTime = 0; animate(0); } init(); // ----- function getContextGL(id) { const can = document.getElementById(id); const gl = can.getContext('webgl'); return [can, gl]; } function createShaderFromElement(gl, id) { const e = document.getElementById(id); const s = gl.createShader(e.type.indexOf('vertex') >= 0 ? gl.VERTEX_SHADER : gl.FRAGMENT_SHADER); gl.shaderSource(s, e.text); gl.compileShader(s); return s; } function buildProgram(gl, vs, fs) { const p = gl.createProgram(); gl.attachShader(p, vs); gl.attachShader(p, fs); gl.linkProgram(p); return p; }
 div {} #main-div { display: inline-block; } #viewport, #manager { float: left; margin: auto; } .color { width: 100px; height: 50px; } .blue { background: #0f0; } #viewport { width: 600px; height: 700px; } #can { width: 600px; height: 500px; border: 1px solid orange; } #manager { width: 200px; height: 300px; padding: 0 0 0 5px; } #obj-list { width: 200px; }
 <script src="https://cdn.jsdelivr.net/npm/gl-matrix@3.3.0/gl-matrix-min.js"></script> <script id="vs" type="x-shader/x-vertex"> precision mediump float; uniform mat4 projMatrix; uniform mat4 viewMatrix; uniform mat4 modelMatrix; attribute vec3 pos; attribute vec3 color; varying vec3 fColor; void main() { fColor = color; vec4 pt = vec4(pos, 1.0); gl_Position = projMatrix * viewMatrix * modelMatrix * pt; } </script> <script id="fs" type="x-shader/x-fragment"> precision mediump float; varying vec3 fColor; void main() { gl_FragColor = vec4(fColor,1); } </script> </head> <div id="main-div"> <div id="viewport"> <canvas id="can" >Your browser doesn't seem to support canvas!</canvas> <div class="slider"> <span class="slider-label">FOV cam</span> <input id="fov" class="slider-input" type="range" min="20" max="90" step="1" value="0" onClick="fovChanged(this.id, this.value)" /> <span id="output-fov" class="slider-value">20</span> </div> <div class="slider"> <span class="slider-label">Far Plane</span> <input id="far" class="slider-input" type="range" min="5" max="30" step="0.1" value="0" onClick="farChanged(this.id, this.value)" /> <span id="output-far" class="slider-value">5</span> </div> </div> </div>

I'd suggest these articles on matrices in WebGL

Also, please take a look at how to make your snippet runnable as a runnable snippet is far more useful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM