在 WebGL 中转换立方体
Translation of a cube in a WebGL
我想在 WebGL 中执行立方体的平移,但我得到的是立方体的变形而不是平移
这是我的代码:
HTML 文件
<!DOCTYPE html>
<html>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 vPosition;
attribute vec4 vColor;
varying vec4 fColor;
uniform vec3 theta;
uniform vec3 tr;
void main()
{
// Compute the sines and cosines of theta for each of
// the three axes in one computation.
vec3 angles = radians( theta );
vec3 c = cos( angles );
vec3 s = sin( angles );
// Remeber: thse matrices are column-major
mat4 rx = mat4( 1.0, 0.0, 0.0, 0.0,
0.0, c.x, s.x, 0.0,
0.0, -s.x, c.x, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 ry = mat4( c.y, 0.0, -s.y, 0.0,
0.0, 1.0, 0.0, 0.0,
s.y, 0.0, c.y, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 rz = mat4( c.z, s.z, 0.0, 0.0,
-s.z, c.z, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 t= mat4( 1.0, 0.0, 0.0, tr.x,
0.0, 1.0, 0.0, tr.y,
0.0, 0.0, 1.0, tr.z,
0.0, 0.0, 0.0, 1.0 );
fColor = vColor;
gl_Position = rz * ry * rx * t * vPosition;
gl_Position.z = -gl_Position.z;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
varying vec4 fColor;
void
main()
{
gl_FragColor = fColor;
}
</script>
<script type="text/javascript" src="../Common/webgl-utils.js"></script>
<script type="text/javascript" src="../Common/initShaders.js"></script>
<script type="text/javascript" src="../Common/MV.js"></script>
<script type="text/javascript" src="Lab20170314_1.js"></script>
<body>
<canvas id="gl-canvas" width="512"" height="512">
Oops ... your browser doesn't support the HTML5 canvas element
</canvas>
<br/>
<button id= "xButton">Rotate X</button>
<button id= "yButton">Rotate Y</button>
<button id= "zButton">Rotate Z</button>
<button id= "stopAnimation"> Start/Stop Animation</button>
<div>
rotation angle 0 <input id="slide" type="range"
min="0" max="10" step="1" value="5" />
10 </div>
<div>
translation on x -1 <input id="slide1" type="range"
min="-1" max="1" step="0.1" value="0" />
1 </div>
<div>
translation on y -1 <input id="slide2" type="range"
min="-1" max="1" step="0.1" value="0" />
1 </div>
<div>
translation on z -1 <input id="slide3" type="range"
min="-1" max="1" step="0.1" value="0" />
1 </div>
</body>
</html>
JavaScript代码
"use strict";
var canvas;
var gl;
var NumVertices = 36;
var points = [];
var colors = [];
var xAxis = 0;
var yAxis = 1;
var zAxis = 2;
var axis = 0;
var axisTr = 0;
var theta = [ 0, 0, 0 ];
var tr=[ 0, 0, 0 ];
var thetaLoc;
var trLoc;
var stop = false;
var trInput = 0;
var degrees=5;
window.onload = function init()
{
canvas = document.getElementById( "gl-canvas" );
gl = WebGLUtils.setupWebGL( canvas );
if ( !gl ) { alert( "WebGL isn't available" ); }
colorCube();
gl.viewport( 0, 0, canvas.width, canvas.height );
gl.clearColor( 1.0, 1.0, 1.0, 1.0 );
gl.enable(gl.DEPTH_TEST);
//
// Load shaders and initialize attribute buffers
//
var program = initShaders( gl, "vertex-shader", "fragment-shader" );
gl.useProgram( program );
var cBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, cBuffer );
gl.bufferData( gl.ARRAY_BUFFER, flatten(colors), gl.STATIC_DRAW );
var vColor = gl.getAttribLocation( program, "vColor" );
gl.vertexAttribPointer( vColor, 4, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vColor );
var vBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, vBuffer );
gl.bufferData( gl.ARRAY_BUFFER, flatten(points), gl.STATIC_DRAW );
var vPosition = gl.getAttribLocation( program, "vPosition" );
gl.vertexAttribPointer( vPosition, 4, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vPosition );
thetaLoc = gl.getUniformLocation(program, "theta");
trLoc = gl.getUniformLocation(program, "tr")
//event listeners for buttons
document.getElementById( "xButton" ).onclick = function () {
axis = xAxis;
};
document.getElementById( "yButton" ).onclick = function () {
axis = yAxis;
};
document.getElementById( "zButton" ).onclick = function () {
axis = zAxis;
};
document.getElementById( "stopAnimation" ).onclick= function() {
stop =! stop;
};
document.getElementById( "slide" ).onchange= function(){
degrees = parseInt(event.target.value,10);
};
document.getElementById( "slide1" ).onchange= function(){
axisTr = xAxis;
trInput = parseFloat(event.target.value,10);
};
document.getElementById( "slide2" ).onchange= function(){
axisTr = yAxis;
trInput = parseFloat(event.target.value,10);
};
document.getElementById( "slide3" ).onchange= function(){
axisTr = zAxis;
trInput = parseFloat(event.target.value,10);
};
render();
}
function colorCube()
{
quad( 1, 0, 3, 2 );
quad( 2, 3, 7, 6 );
quad( 3, 0, 4, 7 );
quad( 6, 5, 1, 2 );
quad( 4, 5, 6, 7 );
quad( 5, 4, 0, 1 );
}
function quad(a, b, c, d)
{
var vertices = [
vec4( -0.5, -0.5, 0.5, 1.0 ),
vec4( -0.5, 0.5, 0.5, 1.0 ),
vec4( 0.5, 0.5, 0.5, 1.0 ),
vec4( 0.5, -0.5, 0.5, 1.0 ),
vec4( -0.5, -0.5, -0.5, 1.0 ),
vec4( -0.5, 0.5, -0.5, 1.0 ),
vec4( 0.5, 0.5, -0.5, 1.0 ),
vec4( 0.5, -0.5, -0.5, 1.0 )
];
var vertexColors = [
[ 0.0, 0.0, 0.0, 1.0 ], // black
[ 1.0, 0.0, 0.0, 1.0 ], // red
[ 1.0, 1.0, 0.0, 1.0 ], // yellow
[ 0.0, 1.0, 0.0, 1.0 ], // green
[ 0.0, 0.0, 1.0, 1.0 ], // blue
[ 1.0, 0.0, 1.0, 1.0 ], // magenta
[ 0.0, 1.0, 1.0, 1.0 ], // cyan
[ 1.0, 1.0, 1.0, 1.0 ] // white
];
// We need to parition the quad into two triangles in order for
// WebGL to be able to render it. In this case, we create two
// triangles from the quad indices
//vertex color assigned by the index of the vertex
var indices = [ a, b, c, a, c, d ];
for ( var i = 0; i < indices.length; ++i ) {
points.push( vertices[indices[i]] );
//colors.push( vertexColors[indices[i]] );
// for solid colored faces use
colors.push(vertexColors[a]);
}
}
function render()
{
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
if(stop)
{
}
else
{
theta[axis] += degrees;
}
tr[axisTr] = trInput;
gl.uniform3fv(thetaLoc, theta);
gl.uniform3fv(trLoc, tr);
gl.drawArrays( gl.TRIANGLES, 0, NumVertices );
requestAnimFrame( render );
}
我使用平移矩阵根据齐次坐标系进行平移。此外,我有三个滑块来设置翻译参数。我哪里错了?
提前致谢。
如果你有 post 工作代码会更好。 Link 在来自 CDN 的公共库中,其余部分使用片段。
您的代码可以正常工作并修复了吗?
- 首先我使用 twgl 提供一些东西来编译着色器。
- 您的 canvas 标签中有额外的
"
,这使得文件的所有其余部分都被忽略了
- 没有理由再为
requestAnimationFrame
使用助手了。所有支持 WebGL 的浏览器都支持 requestAnimationFrame
.
- 几乎没有理由使用任何特殊函数来获取 webgl 上下文。只要做
someCanvas.getContext("webgl")
- 您没有提供
flatten
函数。看起来您正在使用的 flatten 函数生成了一个 Float32Array
,这对于习惯于 JavaScript 并期望它生成一个实际的 JavaScript 数组的人来说会非常混乱。
- 您没有提供
vec4
函数。不确定为什么你有那个功能,但很容易猜到
- 没有理由使用
window.onload
。只需将您的脚本放在 HTML 的底部,然后直接调用 init
。
- 使用
oninput
而不是 onchange
进行实时更新(因为您会在幻灯片滑动时被调用,而不是仅在用户松开滑块时被调用)。虽然我们正在讨论它,但可以说使用 elem.addEventListener('input', listener)
比 elem.oninput
更好。第一个更灵活。它允许多个听众。
终于到了你的实际问题。从编程的角度来看,WebGL 的存储顺序是行优先的,但它的乘法函数将这些行解释为列。
因此,您可以交换乘法顺序,也可以更改矩阵。我建议更改矩阵,否则您将与几乎所有其他 webgl 应用程序不同。
我还建议在着色器中创建矩阵既不灵活也不常见。有时候这是正确的做法,但这可以说不是其中之一,您可能想要 try these webgl tutorials
"use strict";
var canvas;
var gl;
var NumVertices = 36;
var points = [];
var colors = [];
var xAxis = 0;
var yAxis = 1;
var zAxis = 2;
var axis = 0;
var axisTr = 0;
var theta = [ 0, 0, 0 ];
var tr=[ 0, 0, 0 ];
var thetaLoc;
var trLoc;
var stop = false;
var trInput = 0;
var degrees=5;
function init()
{
canvas = document.getElementById( "gl-canvas" );
gl = canvas.getContext("webgl");
if ( !gl ) { alert( "WebGL isn't available" ); return; }
colorCube();
gl.viewport( 0, 0, canvas.width, canvas.height );
gl.clearColor( 1.0, 1.0, 1.0, 1.0 );
gl.enable(gl.DEPTH_TEST);
//
// Load shaders and initialize attribute buffers
//
var program = initShaders( gl, "vertex-shader", "fragment-shader" );
gl.useProgram( program );
var cBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, cBuffer );
gl.bufferData( gl.ARRAY_BUFFER, flatten(colors), gl.STATIC_DRAW );
var vColor = gl.getAttribLocation( program, "vColor" );
gl.vertexAttribPointer( vColor, 4, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vColor );
var vBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, vBuffer );
gl.bufferData( gl.ARRAY_BUFFER, flatten(points), gl.STATIC_DRAW );
var vPosition = gl.getAttribLocation( program, "vPosition" );
gl.vertexAttribPointer( vPosition, 4, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vPosition );
thetaLoc = gl.getUniformLocation(program, "theta");
trLoc = gl.getUniformLocation(program, "tr")
//event listeners for buttons
document.getElementById( "xButton" ).onclick = function () {
axis = xAxis;
};
document.getElementById( "yButton" ).onclick = function () {
axis = yAxis;
};
document.getElementById( "zButton" ).onclick = function () {
axis = zAxis;
};
document.getElementById( "stopAnimation" ).onclick= function() {
stop =! stop;
};
document.getElementById( "slide" ).oninput = function(){
degrees = parseInt(event.target.value,10);
};
document.getElementById( "slide1" ).oninput = function(){
axisTr = xAxis;
trInput = parseFloat(event.target.value,10);
};
document.getElementById( "slide2" ).oninput = function(){
axisTr = yAxis;
trInput = parseFloat(event.target.value,10);
};
document.getElementById( "slide3" ).oninput= function(){
axisTr = zAxis;
trInput = parseFloat(event.target.value,10);
};
render();
}
function colorCube()
{
quad( 1, 0, 3, 2 );
quad( 2, 3, 7, 6 );
quad( 3, 0, 4, 7 );
quad( 6, 5, 1, 2 );
quad( 4, 5, 6, 7 );
quad( 5, 4, 0, 1 );
}
function quad(a, b, c, d)
{
var vertices = [
vec4( -0.5, -0.5, 0.5, 1.0 ),
vec4( -0.5, 0.5, 0.5, 1.0 ),
vec4( 0.5, 0.5, 0.5, 1.0 ),
vec4( 0.5, -0.5, 0.5, 1.0 ),
vec4( -0.5, -0.5, -0.5, 1.0 ),
vec4( -0.5, 0.5, -0.5, 1.0 ),
vec4( 0.5, 0.5, -0.5, 1.0 ),
vec4( 0.5, -0.5, -0.5, 1.0 )
];
var vertexColors = [
[ 0.0, 0.0, 0.0, 1.0 ], // black
[ 1.0, 0.0, 0.0, 1.0 ], // red
[ 1.0, 1.0, 0.0, 1.0 ], // yellow
[ 0.0, 1.0, 0.0, 1.0 ], // green
[ 0.0, 0.0, 1.0, 1.0 ], // blue
[ 1.0, 0.0, 1.0, 1.0 ], // magenta
[ 0.0, 1.0, 1.0, 1.0 ], // cyan
[ 1.0, 1.0, 1.0, 1.0 ] // white
];
// We need to parition the quad into two triangles in order for
// WebGL to be able to render it. In this case, we create two
// triangles from the quad indices
//vertex color assigned by the index of the vertex
var indices = [ a, b, c, a, c, d ];
for ( var i = 0; i < indices.length; ++i ) {
points.push( vertices[indices[i]] );
//colors.push( vertexColors[indices[i]] );
// for solid colored faces use
colors.push(vertexColors[a]);
}
}
function render()
{
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
if(stop)
{
}
else
{
theta[axis] += degrees;
}
tr[axisTr] = trInput;
gl.uniform3fv(thetaLoc, theta);
gl.uniform3fv(trLoc, tr);
gl.drawArrays( gl.TRIANGLES, 0, NumVertices );
requestAnimationFrame( render );
}
function initShaders(gl, vsId, fsId) {
return twgl.createProgramFromScripts(gl, [vsId, fsId]);
}
function vec4(x, y, z, w) {
return [x, y, z, w];
}
function flatten(arrays) {
return new Float32Array([].concat.apply([], arrays));
}
init();
<script src="https://twgljs.org/dist/3.x/twgl.min.js"></script>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 vPosition;
attribute vec4 vColor;
varying vec4 fColor;
uniform vec3 theta;
uniform vec3 tr;
void main()
{
// Compute the sines and cosines of theta for each of
// the three axes in one computation.
vec3 angles = radians( theta );
vec3 c = cos( angles );
vec3 s = sin( angles );
// Remeber: thse matrices are column-major
mat4 rx = mat4( 1.0, 0.0, 0.0, 0.0,
0.0, c.x, -s.x, 0.0,
0.0, s.x, c.x, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 ry = mat4( c.y, 0.0, s.y, 0.0,
0.0, 1.0, 0.0, 0.0,
-s.y, 0.0, c.y, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 rz = mat4( c.z, -s.z, 0.0, 0.0,
s.z, c.z, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 t= mat4( 1.0, 0.0, 0.0, 0,
0.0, 1.0, 0.0, 0,
0.0, 0.0, 1.0, 0,
tr.xyz, 1.0 );
fColor = vColor;
gl_Position = rz * ry * rx * t * vPosition;
gl_Position.z = -gl_Position.z;
// this would too but would be different than most WebGL programs
//gl_Position = vPosition * t * rx * ry * rz;
//gl_Position.z = -gl_Position.z;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
varying vec4 fColor;
void
main()
{
gl_FragColor = fColor;
}
</script>
<canvas id="gl-canvas" width="512" height="512">
Oops ... your browser doesn't support the HTML5 canvas element
</canvas>
<br/>
<button id= "xButton">Rotate X</button>
<button id= "yButton">Rotate Y</button>
<button id= "zButton">Rotate Z</button>
<button id= "stopAnimation"> Start/Stop Animation</button>
<div>
rotation angle 0 <input id="slide" type="range"
min="0" max="10" step="1" value="5" />
10 </div>
<div>
translation on x -1 <input id="slide1" type="range"
min="-1" max="1" step="0.1" value="0" />
1 </div>
<div>
translation on y -1 <input id="slide2" type="range"
min="-1" max="1" step="0.1" value="0" />
1 </div>
<div>
translation on z -1 <input id="slide3" type="range"
min="-1" max="1" step="0.1" value="0" />
1 </div>
我想在 WebGL 中执行立方体的平移,但我得到的是立方体的变形而不是平移 这是我的代码:
HTML 文件
<!DOCTYPE html>
<html>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 vPosition;
attribute vec4 vColor;
varying vec4 fColor;
uniform vec3 theta;
uniform vec3 tr;
void main()
{
// Compute the sines and cosines of theta for each of
// the three axes in one computation.
vec3 angles = radians( theta );
vec3 c = cos( angles );
vec3 s = sin( angles );
// Remeber: thse matrices are column-major
mat4 rx = mat4( 1.0, 0.0, 0.0, 0.0,
0.0, c.x, s.x, 0.0,
0.0, -s.x, c.x, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 ry = mat4( c.y, 0.0, -s.y, 0.0,
0.0, 1.0, 0.0, 0.0,
s.y, 0.0, c.y, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 rz = mat4( c.z, s.z, 0.0, 0.0,
-s.z, c.z, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 t= mat4( 1.0, 0.0, 0.0, tr.x,
0.0, 1.0, 0.0, tr.y,
0.0, 0.0, 1.0, tr.z,
0.0, 0.0, 0.0, 1.0 );
fColor = vColor;
gl_Position = rz * ry * rx * t * vPosition;
gl_Position.z = -gl_Position.z;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
varying vec4 fColor;
void
main()
{
gl_FragColor = fColor;
}
</script>
<script type="text/javascript" src="../Common/webgl-utils.js"></script>
<script type="text/javascript" src="../Common/initShaders.js"></script>
<script type="text/javascript" src="../Common/MV.js"></script>
<script type="text/javascript" src="Lab20170314_1.js"></script>
<body>
<canvas id="gl-canvas" width="512"" height="512">
Oops ... your browser doesn't support the HTML5 canvas element
</canvas>
<br/>
<button id= "xButton">Rotate X</button>
<button id= "yButton">Rotate Y</button>
<button id= "zButton">Rotate Z</button>
<button id= "stopAnimation"> Start/Stop Animation</button>
<div>
rotation angle 0 <input id="slide" type="range"
min="0" max="10" step="1" value="5" />
10 </div>
<div>
translation on x -1 <input id="slide1" type="range"
min="-1" max="1" step="0.1" value="0" />
1 </div>
<div>
translation on y -1 <input id="slide2" type="range"
min="-1" max="1" step="0.1" value="0" />
1 </div>
<div>
translation on z -1 <input id="slide3" type="range"
min="-1" max="1" step="0.1" value="0" />
1 </div>
</body>
</html>
JavaScript代码
"use strict";
var canvas;
var gl;
var NumVertices = 36;
var points = [];
var colors = [];
var xAxis = 0;
var yAxis = 1;
var zAxis = 2;
var axis = 0;
var axisTr = 0;
var theta = [ 0, 0, 0 ];
var tr=[ 0, 0, 0 ];
var thetaLoc;
var trLoc;
var stop = false;
var trInput = 0;
var degrees=5;
window.onload = function init()
{
canvas = document.getElementById( "gl-canvas" );
gl = WebGLUtils.setupWebGL( canvas );
if ( !gl ) { alert( "WebGL isn't available" ); }
colorCube();
gl.viewport( 0, 0, canvas.width, canvas.height );
gl.clearColor( 1.0, 1.0, 1.0, 1.0 );
gl.enable(gl.DEPTH_TEST);
//
// Load shaders and initialize attribute buffers
//
var program = initShaders( gl, "vertex-shader", "fragment-shader" );
gl.useProgram( program );
var cBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, cBuffer );
gl.bufferData( gl.ARRAY_BUFFER, flatten(colors), gl.STATIC_DRAW );
var vColor = gl.getAttribLocation( program, "vColor" );
gl.vertexAttribPointer( vColor, 4, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vColor );
var vBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, vBuffer );
gl.bufferData( gl.ARRAY_BUFFER, flatten(points), gl.STATIC_DRAW );
var vPosition = gl.getAttribLocation( program, "vPosition" );
gl.vertexAttribPointer( vPosition, 4, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vPosition );
thetaLoc = gl.getUniformLocation(program, "theta");
trLoc = gl.getUniformLocation(program, "tr")
//event listeners for buttons
document.getElementById( "xButton" ).onclick = function () {
axis = xAxis;
};
document.getElementById( "yButton" ).onclick = function () {
axis = yAxis;
};
document.getElementById( "zButton" ).onclick = function () {
axis = zAxis;
};
document.getElementById( "stopAnimation" ).onclick= function() {
stop =! stop;
};
document.getElementById( "slide" ).onchange= function(){
degrees = parseInt(event.target.value,10);
};
document.getElementById( "slide1" ).onchange= function(){
axisTr = xAxis;
trInput = parseFloat(event.target.value,10);
};
document.getElementById( "slide2" ).onchange= function(){
axisTr = yAxis;
trInput = parseFloat(event.target.value,10);
};
document.getElementById( "slide3" ).onchange= function(){
axisTr = zAxis;
trInput = parseFloat(event.target.value,10);
};
render();
}
function colorCube()
{
quad( 1, 0, 3, 2 );
quad( 2, 3, 7, 6 );
quad( 3, 0, 4, 7 );
quad( 6, 5, 1, 2 );
quad( 4, 5, 6, 7 );
quad( 5, 4, 0, 1 );
}
function quad(a, b, c, d)
{
var vertices = [
vec4( -0.5, -0.5, 0.5, 1.0 ),
vec4( -0.5, 0.5, 0.5, 1.0 ),
vec4( 0.5, 0.5, 0.5, 1.0 ),
vec4( 0.5, -0.5, 0.5, 1.0 ),
vec4( -0.5, -0.5, -0.5, 1.0 ),
vec4( -0.5, 0.5, -0.5, 1.0 ),
vec4( 0.5, 0.5, -0.5, 1.0 ),
vec4( 0.5, -0.5, -0.5, 1.0 )
];
var vertexColors = [
[ 0.0, 0.0, 0.0, 1.0 ], // black
[ 1.0, 0.0, 0.0, 1.0 ], // red
[ 1.0, 1.0, 0.0, 1.0 ], // yellow
[ 0.0, 1.0, 0.0, 1.0 ], // green
[ 0.0, 0.0, 1.0, 1.0 ], // blue
[ 1.0, 0.0, 1.0, 1.0 ], // magenta
[ 0.0, 1.0, 1.0, 1.0 ], // cyan
[ 1.0, 1.0, 1.0, 1.0 ] // white
];
// We need to parition the quad into two triangles in order for
// WebGL to be able to render it. In this case, we create two
// triangles from the quad indices
//vertex color assigned by the index of the vertex
var indices = [ a, b, c, a, c, d ];
for ( var i = 0; i < indices.length; ++i ) {
points.push( vertices[indices[i]] );
//colors.push( vertexColors[indices[i]] );
// for solid colored faces use
colors.push(vertexColors[a]);
}
}
function render()
{
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
if(stop)
{
}
else
{
theta[axis] += degrees;
}
tr[axisTr] = trInput;
gl.uniform3fv(thetaLoc, theta);
gl.uniform3fv(trLoc, tr);
gl.drawArrays( gl.TRIANGLES, 0, NumVertices );
requestAnimFrame( render );
}
我使用平移矩阵根据齐次坐标系进行平移。此外,我有三个滑块来设置翻译参数。我哪里错了?
提前致谢。
如果你有 post 工作代码会更好。 Link 在来自 CDN 的公共库中,其余部分使用片段。
您的代码可以正常工作并修复了吗?
- 首先我使用 twgl 提供一些东西来编译着色器。
- 您的 canvas 标签中有额外的
"
,这使得文件的所有其余部分都被忽略了 - 没有理由再为
requestAnimationFrame
使用助手了。所有支持 WebGL 的浏览器都支持requestAnimationFrame
. - 几乎没有理由使用任何特殊函数来获取 webgl 上下文。只要做
someCanvas.getContext("webgl")
- 您没有提供
flatten
函数。看起来您正在使用的 flatten 函数生成了一个Float32Array
,这对于习惯于 JavaScript 并期望它生成一个实际的 JavaScript 数组的人来说会非常混乱。 - 您没有提供
vec4
函数。不确定为什么你有那个功能,但很容易猜到 - 没有理由使用
window.onload
。只需将您的脚本放在 HTML 的底部,然后直接调用init
。 - 使用
oninput
而不是onchange
进行实时更新(因为您会在幻灯片滑动时被调用,而不是仅在用户松开滑块时被调用)。虽然我们正在讨论它,但可以说使用elem.addEventListener('input', listener)
比elem.oninput
更好。第一个更灵活。它允许多个听众。
终于到了你的实际问题。从编程的角度来看,WebGL 的存储顺序是行优先的,但它的乘法函数将这些行解释为列。
因此,您可以交换乘法顺序,也可以更改矩阵。我建议更改矩阵,否则您将与几乎所有其他 webgl 应用程序不同。
我还建议在着色器中创建矩阵既不灵活也不常见。有时候这是正确的做法,但这可以说不是其中之一,您可能想要 try these webgl tutorials
"use strict";
var canvas;
var gl;
var NumVertices = 36;
var points = [];
var colors = [];
var xAxis = 0;
var yAxis = 1;
var zAxis = 2;
var axis = 0;
var axisTr = 0;
var theta = [ 0, 0, 0 ];
var tr=[ 0, 0, 0 ];
var thetaLoc;
var trLoc;
var stop = false;
var trInput = 0;
var degrees=5;
function init()
{
canvas = document.getElementById( "gl-canvas" );
gl = canvas.getContext("webgl");
if ( !gl ) { alert( "WebGL isn't available" ); return; }
colorCube();
gl.viewport( 0, 0, canvas.width, canvas.height );
gl.clearColor( 1.0, 1.0, 1.0, 1.0 );
gl.enable(gl.DEPTH_TEST);
//
// Load shaders and initialize attribute buffers
//
var program = initShaders( gl, "vertex-shader", "fragment-shader" );
gl.useProgram( program );
var cBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, cBuffer );
gl.bufferData( gl.ARRAY_BUFFER, flatten(colors), gl.STATIC_DRAW );
var vColor = gl.getAttribLocation( program, "vColor" );
gl.vertexAttribPointer( vColor, 4, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vColor );
var vBuffer = gl.createBuffer();
gl.bindBuffer( gl.ARRAY_BUFFER, vBuffer );
gl.bufferData( gl.ARRAY_BUFFER, flatten(points), gl.STATIC_DRAW );
var vPosition = gl.getAttribLocation( program, "vPosition" );
gl.vertexAttribPointer( vPosition, 4, gl.FLOAT, false, 0, 0 );
gl.enableVertexAttribArray( vPosition );
thetaLoc = gl.getUniformLocation(program, "theta");
trLoc = gl.getUniformLocation(program, "tr")
//event listeners for buttons
document.getElementById( "xButton" ).onclick = function () {
axis = xAxis;
};
document.getElementById( "yButton" ).onclick = function () {
axis = yAxis;
};
document.getElementById( "zButton" ).onclick = function () {
axis = zAxis;
};
document.getElementById( "stopAnimation" ).onclick= function() {
stop =! stop;
};
document.getElementById( "slide" ).oninput = function(){
degrees = parseInt(event.target.value,10);
};
document.getElementById( "slide1" ).oninput = function(){
axisTr = xAxis;
trInput = parseFloat(event.target.value,10);
};
document.getElementById( "slide2" ).oninput = function(){
axisTr = yAxis;
trInput = parseFloat(event.target.value,10);
};
document.getElementById( "slide3" ).oninput= function(){
axisTr = zAxis;
trInput = parseFloat(event.target.value,10);
};
render();
}
function colorCube()
{
quad( 1, 0, 3, 2 );
quad( 2, 3, 7, 6 );
quad( 3, 0, 4, 7 );
quad( 6, 5, 1, 2 );
quad( 4, 5, 6, 7 );
quad( 5, 4, 0, 1 );
}
function quad(a, b, c, d)
{
var vertices = [
vec4( -0.5, -0.5, 0.5, 1.0 ),
vec4( -0.5, 0.5, 0.5, 1.0 ),
vec4( 0.5, 0.5, 0.5, 1.0 ),
vec4( 0.5, -0.5, 0.5, 1.0 ),
vec4( -0.5, -0.5, -0.5, 1.0 ),
vec4( -0.5, 0.5, -0.5, 1.0 ),
vec4( 0.5, 0.5, -0.5, 1.0 ),
vec4( 0.5, -0.5, -0.5, 1.0 )
];
var vertexColors = [
[ 0.0, 0.0, 0.0, 1.0 ], // black
[ 1.0, 0.0, 0.0, 1.0 ], // red
[ 1.0, 1.0, 0.0, 1.0 ], // yellow
[ 0.0, 1.0, 0.0, 1.0 ], // green
[ 0.0, 0.0, 1.0, 1.0 ], // blue
[ 1.0, 0.0, 1.0, 1.0 ], // magenta
[ 0.0, 1.0, 1.0, 1.0 ], // cyan
[ 1.0, 1.0, 1.0, 1.0 ] // white
];
// We need to parition the quad into two triangles in order for
// WebGL to be able to render it. In this case, we create two
// triangles from the quad indices
//vertex color assigned by the index of the vertex
var indices = [ a, b, c, a, c, d ];
for ( var i = 0; i < indices.length; ++i ) {
points.push( vertices[indices[i]] );
//colors.push( vertexColors[indices[i]] );
// for solid colored faces use
colors.push(vertexColors[a]);
}
}
function render()
{
gl.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
if(stop)
{
}
else
{
theta[axis] += degrees;
}
tr[axisTr] = trInput;
gl.uniform3fv(thetaLoc, theta);
gl.uniform3fv(trLoc, tr);
gl.drawArrays( gl.TRIANGLES, 0, NumVertices );
requestAnimationFrame( render );
}
function initShaders(gl, vsId, fsId) {
return twgl.createProgramFromScripts(gl, [vsId, fsId]);
}
function vec4(x, y, z, w) {
return [x, y, z, w];
}
function flatten(arrays) {
return new Float32Array([].concat.apply([], arrays));
}
init();
<script src="https://twgljs.org/dist/3.x/twgl.min.js"></script>
<script id="vertex-shader" type="x-shader/x-vertex">
attribute vec4 vPosition;
attribute vec4 vColor;
varying vec4 fColor;
uniform vec3 theta;
uniform vec3 tr;
void main()
{
// Compute the sines and cosines of theta for each of
// the three axes in one computation.
vec3 angles = radians( theta );
vec3 c = cos( angles );
vec3 s = sin( angles );
// Remeber: thse matrices are column-major
mat4 rx = mat4( 1.0, 0.0, 0.0, 0.0,
0.0, c.x, -s.x, 0.0,
0.0, s.x, c.x, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 ry = mat4( c.y, 0.0, s.y, 0.0,
0.0, 1.0, 0.0, 0.0,
-s.y, 0.0, c.y, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 rz = mat4( c.z, -s.z, 0.0, 0.0,
s.z, c.z, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 );
mat4 t= mat4( 1.0, 0.0, 0.0, 0,
0.0, 1.0, 0.0, 0,
0.0, 0.0, 1.0, 0,
tr.xyz, 1.0 );
fColor = vColor;
gl_Position = rz * ry * rx * t * vPosition;
gl_Position.z = -gl_Position.z;
// this would too but would be different than most WebGL programs
//gl_Position = vPosition * t * rx * ry * rz;
//gl_Position.z = -gl_Position.z;
}
</script>
<script id="fragment-shader" type="x-shader/x-fragment">
precision mediump float;
varying vec4 fColor;
void
main()
{
gl_FragColor = fColor;
}
</script>
<canvas id="gl-canvas" width="512" height="512">
Oops ... your browser doesn't support the HTML5 canvas element
</canvas>
<br/>
<button id= "xButton">Rotate X</button>
<button id= "yButton">Rotate Y</button>
<button id= "zButton">Rotate Z</button>
<button id= "stopAnimation"> Start/Stop Animation</button>
<div>
rotation angle 0 <input id="slide" type="range"
min="0" max="10" step="1" value="5" />
10 </div>
<div>
translation on x -1 <input id="slide1" type="range"
min="-1" max="1" step="0.1" value="0" />
1 </div>
<div>
translation on y -1 <input id="slide2" type="range"
min="-1" max="1" step="0.1" value="0" />
1 </div>
<div>
translation on z -1 <input id="slide3" type="range"
min="-1" max="1" step="0.1" value="0" />
1 </div>