在WebGL中翻译多维数据集

时间:2017-03-23 21:42:04

标签: javascript html webgl

我想在WebGL中执行多维数据集的转换,但是我得到了多维数据集的变形而不是翻译 这是我的代码:

HTML文件

private static readonly IReadOnlyCollection<string> LOWER_TRUE_VALUES = new string[] { "true", "t", "1", "yes", "y" };
public static bool IsTrue(string value) => value != null ? LOWER_TRUE_VALUES.Contains(value.Trim().ToLower()) : false;

JavaScript代码

<!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>

我使用翻译矩阵根据齐次坐标系统执行翻译。此外,我有三个滑块来设置转换参数。我哪里错了?

提前谢谢。

1 个答案:

答案 0 :(得分:0)

如果您发布工作代码会更好。来自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>