繁体   English   中英

在x轴上平移3D立方体

[英]Translate 3D cube on x-axis

我试图将两个3D立方体彼此转换。 我试过使用clipspace以及转换矩阵,但没有任何效果。 寻找的解决方案是最好在x轴上并排放置立方体。

这是我的代码:

 var gl,program,canvas; var vBuffer, vPosition; var idxBuffer; var vertices = [ -0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, -0.5, 1, -0.5, -0.5, 1, -0.5, 0.5, 0, 0.5, 0.5, 0, 0.5, -0.5, 0, -0.5, -0.5, 0 ]; var dVecIdx = new Uint16Array([ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ]); var projection = [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1 ]; var a = Math.sqrt(0.5); var rotation = [ a, 0, a, 0, 0, 1, 0, 0, -a, 0, a, 0, 0, 0, 0, 1 ]; window.onload = function init() { canvas = document.getElementById("gl-canvas"); gl = WebGLUtils.setupWebGL(canvas); if (!gl) { alert("WebGL isn't available"); } gl.viewport(0, 0, canvas.width, canvas.height); gl.clearColor(1.0, 1.0, 1.0, 1.0); gl.enable(gl.DEPTH_TEST); program = initShaders(gl, "vertex-shader", "fragment-shader"); vBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer); gl.bufferData(gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW); vPosition = gl.getAttribLocation(program, "vPosition"); gl.enableVertexAttribArray(vPosition); gl.vertexAttribPointer(vPosition, 3, gl.FLOAT, false, 0, 0); idxBuffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, idxBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, dVecIdx, gl.STATIC_DRAW); render(); } function render() { gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); gl.useProgram(program); gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer); projLoc = gl.getUniformLocation(program, "projectionMatrix"); loc = gl.getUniformLocation(program, "rotate"); gl.uniformMatrix4fv(projLoc, false, projection); gl.uniformMatrix4fv(loc, false, projection); gl.drawElements(gl.LINES, dVecIdx.length, gl.UNSIGNED_SHORT, 0); gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer); projLoc = gl.getUniformLocation(program, "projectionMatrix"); loc = gl.getUniformLocation(program, "rotate"); gl.uniformMatrix4fv(projLoc, false, projection); gl.uniformMatrix4fv(loc, false, rotation); gl.drawElements(gl.LINES, dVecIdx.length, gl.UNSIGNED_SHORT, 0); requestAnimFrame(render); } 
 <html> <head> <script src="https://www.cs.unm.edu/~angel/WebGL/7E/Common/initShaders.js"></script> <script src="https://www.cs.unm.edu/~angel/WebGL/7E/Common/MV.js"></script> <script src="https://www.cs.unm.edu/~angel/WebGL/7E/Common/webgl-utils.js"></script> <script id="vertex-shader" type="x-shader/x-vertex"> attribute vec3 vPosition; attribute vec4 vColor; varying vec4 fColor; uniform mat4 projectionMatrix; uniform mat4 rotate; void main() { gl_Position = projectionMatrix * rotate * vec4(vPosition, 1); fColor = vColor; } </script> <script id="fragment-shader" type="x-shader/x-fragment"> precision mediump float; varying vec4 fColor; void main() { gl_FragColor = fColor; } </script> </head> <body> <div style="border: 1px dotted black;"> <div style="text-align:center"> <canvas id="gl-canvas" width="500" height="500"></canvas> </div> </div> </body> </html> 

任何帮助表示赞赏!

如果您尝试在设置上进行太多改进,我建议您使用诸如Three.js之类的WebGL库来抽象一些数学运算,或者建议您花点时间浏览并了解对象和相机转换矩阵。

回答:

话虽如此,简单的答案是仅添加另一个平移矩阵,并将其插入到着色器的投影矩阵和旋转矩阵之间:

attribute vec3 vPosition;
attribute vec4 vColor;
varying vec4 fColor;
uniform mat4 projectionMatrix;
uniform mat4 rotate;
uniform mat4 translate;

void main() {
    gl_Position = projectionMatrix * translate * rotate * vec4(vPosition, 1);
    fColor = vColor;
}

转换矩阵如下所示:

var translation = [
    1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    x, y, z, 1
];

其中xyz分别是沿X轴,Y轴和Z轴的平移距离。 然后将其以与旋转矩阵相同的方式添加到render方法:

transLoc = gl.getUniformLocation(program, "translate");
gl.uniformMatrix4fv(transLoc, false, translation);

优化:

现在还说 ,您还可以进行其他一些优化/更正:

1)由于WebGL一直保持其“状态”直到被更改(保持绑定/设置/启用/保持等),因此您可以在render()方法中删除很多重复的代码:

function render() {
    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);

    // set state
    gl.useProgram(program);
    gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer);
    projLoc = gl.getUniformLocation(program, "projectionMatrix");
    loc = gl.getUniformLocation(program, "rotate");
    gl.uniformMatrix4fv(projLoc, false, projection);

    // draw shape 1
    gl.uniformMatrix4fv(loc, false, projection);
    gl.drawElements(gl.LINES, dVecIdx.length, gl.UNSIGNED_SHORT, 0);

    // draw shape 2
    gl.uniformMatrix4fv(loc, false, rotation);
    gl.drawElements(gl.LINES, dVecIdx.length, gl.UNSIGNED_SHORT, 0);

    requestAnimFrame(render);
}

2)如果不想在渲染过程中使用特定的矩阵,则应将其设置为单位矩阵,该矩阵在相乘时不会改变其他矩阵/向量:

var identity = [
    1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1
];

这是第一个形状上的旋转矩阵而不是透视图矩阵应使用的方法:

// draw shape 1
gl.uniformMatrix4fv(loc, false, identity);
gl.drawElements(gl.LINES, dVecIdx.length, gl.UNSIGNED_SHORT, 0);

3)您可以将progLoc,rotLoc和transLoc声明为全局变量,并在程序初始化后立即设置它们的值。 这些对于单个程序不会更改,也不需要在渲染循环中重置。

program = initShaders(gl, "vertex-shader", "fragment-shader");
projLoc = gl.getUniformLocation(program, "projectionMatrix");
rotLoc = gl.getUniformLocation(program, "rotate");
transLoc = gl.getUniformLocation(program, "translate");

编写最终代码:

 var gl,program,canvas; var vBuffer, vPosition; var idxBuffer; var projLoc, rotLoc, transLoc; var vertices = [ -0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, -0.5, 1, -0.5, -0.5, 1, -0.5, 0.5, 0, 0.5, 0.5, 0, 0.5, -0.5, 0, -0.5, -0.5, 0 ]; var dVecIdx = new Uint16Array([ 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 2, 6, 3, 7 ]); var identity = [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ]; var projection = [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1 ]; var a = Math.sqrt(0.5); var rotation = [ a, 0, a, 0, 0, 1, 0, 0, -a, 0, a, 0, 0, 0, 0, 1 ]; // actual translations are set in the render() function var translation = [ 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 ]; window.onload = function init() { canvas = document.getElementById("gl-canvas"); gl = WebGLUtils.setupWebGL(canvas); if (!gl) { alert("WebGL isn't available"); } gl.viewport(0, 0, canvas.width, canvas.height); gl.clearColor(1.0, 1.0, 1.0, 1.0); gl.enable(gl.DEPTH_TEST); program = initShaders(gl, "vertex-shader", "fragment-shader"); projLoc = gl.getUniformLocation(program, "projectionMatrix"); rotLoc = gl.getUniformLocation(program, "rotate"); transLoc = gl.getUniformLocation(program, "translate"); vBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer); gl.bufferData(gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW); vPosition = gl.getAttribLocation(program, "vPosition"); gl.enableVertexAttribArray(vPosition); gl.vertexAttribPointer(vPosition, 3, gl.FLOAT, false, 0, 0); idxBuffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, idxBuffer); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, dVecIdx, gl.STATIC_DRAW); render(); } function render() { gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // set non-changing states gl.useProgram(program); gl.bindBuffer(gl.ARRAY_BUFFER, vBuffer); gl.uniformMatrix4fv(projLoc, false, projection); // draw shape 1 translation[12] = 1; // x-axis translation (y and z are 0) gl.uniformMatrix4fv(transLoc, false, translation); gl.uniformMatrix4fv(rotLoc, false, identity); gl.drawElements(gl.LINES, dVecIdx.length, gl.UNSIGNED_SHORT, 0); // draw shape 2 translation[12] = -1; // set x-axis translation gl.uniformMatrix4fv(transLoc, false, translation); gl.uniformMatrix4fv(rotLoc, false, rotation); gl.drawElements(gl.LINES, dVecIdx.length, gl.UNSIGNED_SHORT, 0); requestAnimFrame(render); } 
 <html> <head> <script src="https://www.cs.unm.edu/~angel/WebGL/7E/Common/initShaders.js"></script> <script src="https://www.cs.unm.edu/~angel/WebGL/7E/Common/MV.js"></script> <script src="https://www.cs.unm.edu/~angel/WebGL/7E/Common/webgl-utils.js"></script> <script id="vertex-shader" type="x-shader/x-vertex"> attribute vec3 vPosition; attribute vec4 vColor; varying vec4 fColor; uniform mat4 projectionMatrix; uniform mat4 rotate; uniform mat4 translate; void main() { gl_Position = projectionMatrix * translate * rotate * vec4(vPosition, 1); fColor = vColor; } </script> <script id="fragment-shader" type="x-shader/x-fragment"> precision mediump float; varying vec4 fColor; void main() { gl_FragColor = fColor; } </script> </head> <body> <div style="border: 1px dotted black;"> <div style="text-align:center"> <canvas id="gl-canvas" width="500" height="500"></canvas> </div> </div> </body> </html> 

4)如果要使用MV.js脚本,还可以将矩阵声明为mat4()对象,并在将数据传输到GPU之前使用mult()将CPU上的矩阵相乘(每个形状一个乘法,而不是每个形状一个乘法)顶点)。 您还可以使用它来创建更通用,更准确的相机矩阵:

var persp = perspective(30.0, 1, 0.1, 100); // fovy, aspect, near, far
var view = lookAt([0, 0, 5], [0, 0, 0], [0, 1, 0]); // eye, look, up
var projection2D = mult(persp, view);

var projection = []; // convert to 1D array
for(var i = 0; i < projection2D.length; i++) {
    projection = projection.concat(projection2D[i]);
}

希望这会有所帮助! 干杯!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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