如何在 Webgl 的缓冲区中仅使用 4 个顶点绘制 2 个嵌套矩形?

How to draw 2 nested rectangles using ONLY 4 vertices in the buffer in Webgl?

我知道如何使用统一变量来移动矩形,但我不知道如何使它变小或变大以适应另一个。任何帮助表示赞赏。谢谢!

var vertices = 
    [
  vec2(0.0, 0.0 ),  
  vec2(0.4, 0),
  vec2(0, 0.4),
  vec2(0.4, 0.4)  
];

gl.viewport( 0, 0, canvas.width, canvas.height );
gl.clearColor( 0.9, 0.9, 0.9, 1.0 );

var program = initShaders( gl, "vertex-shader", "fragment-shader" );
gl.useProgram( program );

// Create a buffer for the vertex shader in the GPU.
var bufferId = gl.createBuffer();

// Tell the GPU to expect data for this buffer
gl.bindBuffer( gl.ARRAY_BUFFER, bufferId );

    // Send data into the buffer.   
gl.bufferData( gl.ARRAY_BUFFER, flatten(vertices), gl.STATIC_DRAW );   

// Set up the buffer for use
var vPosition = gl.getAttribLocation( program, "myvPosition" );

// myvPosition (identified using vPosition) will correspond to 2 floats per vertex,
gl.vertexAttribPointer( vPosition, 2, gl.FLOAT, false, 0, 0 );

// Enable use of the vertex buffer with myvPosition
gl.enableVertexAttribArray( vPosition );

// Get an index to each uniform variable in the GPU's shader      
var xIndex   = gl.getUniformLocation( program, "xAdjust" );
var yIndex   = gl.getUniformLocation( program, "yAdjust" );
var rIndex   = gl.getUniformLocation(  program, "red" );
var gIndex   = gl.getUniformLocation(  program, "green" );
var bIndex   = gl.getUniformLocation(  program, "blue" );

gl.uniform1f( xIndex, -0.25 );    // move to the left

gl.uniform1f( gIndex,  1.0 );


gl.clear( gl.COLOR_BUFFER_BIT );  // note new place to put clear

render();

gl.uniform1f( xIndex, +0.25 );    // move to the right

gl.uniform1f( rIndex,  1.0 );

render();   
};

function render()  
{   
   gl.drawArrays( gl.TRIANGLE_STRIP, 0, 4 );
 }

例如:我可以更改 gl.uniform1f(xIndex, ) 中的值以沿 x 轴移动矩形

是时候学习变换矩阵了。有很多数学,但我会尽量解释得尽可能简单。

让我们选择新方块 1x1:

var vertices = 
    [
  vec2(0, 0),  
  vec2(1, 0),
  vec2(0, 1),
  vec2(1, 1)  
];

现在,如果您想将它向左移动 1(就像您所做的那样),您需要将所有顶点的 [x] 添加 1。这个看起来很简单。 如果要旋转它,那就复杂多了。想象一下,您的对象将来自 50000 个顶点,而不仅仅是 4 个 => 超级复杂!

所以人们发明了一些被广泛使用的程序。我们为我们拥有的每个对象创建转换矩阵。在 2D 中,矩阵是 3x3。在 3D 中,矩阵是 4x4。

矩阵是如何工作的?首先创建顶点,然后使用

初始化矩阵
// js example
var model1M = mat3.create([
 1, 0, 0,
 0, 1, 0,
 0, 0, 1]);

这意味着 "no transformation done" 呢。然后通过矩阵操作平移、旋转、缩放对象。 记住,转换顺序很重要!!

move & rotate != rotate & move

一旦你想渲染,你发送矩阵到着色器。

// this is how you send 1 float value
gl.uniform1f( xIndex, -0.25 );    // move to the left

// this is how we send 3x3 matrix
var mvmi = gl.getUniformLocation( program, "modelViewMatrix" );
gl.uniformMatrix3fv(mvmi, false, model1M);

在着色器中:

// you have to modify what is in vec4
gl_Position = modelViewMatrix * vec4( position, 1.0 );

完成了。

问题是 mat3 在 js 中不存在。转换数学: http://upload.wikimedia.org/wikipedia/commons/2/2c/2D_affine_transformation_matrix.svg

您需要先完成所有的数学运算。但更简单的是下载库,例如 http://glmatrix.net/ and include gl-matrix-min.js. Then follow documentation http://glmatrix.net/docs/2.2.0/symbols/mat3.html .

简单的食谱:

var DEG_TO_RAD = 0.0174532925;

// create matrix, you dont have to type numbers in
var modelMatrix = mat3.create();

// move
mat3.translate(modelMatrix, modelMatrix, [-0.5, -0.5]);

// rotate by 45 degrees
mat3.rotate(modelMatrix, modelMatrix, 45*DEG_TO_RAD);

// make square smaller
mat3.scale(modelMatrix, modelMatrix, [0.4, 0.4]);