Orthogonal projection matrix

Projection of the real world into the clipped space matrix through the camera world — objects of different depths do not have the perspective rules of near larger and far smaller.

The thinking process

Clipping space: Clipping space is used to display WebGL graphics. It is a cube box with width, height and depth of 2, starting from the center of the canvas. When the image range exceeds the clipping space (greater than 1 or less than -1), the image will not be displayed.

The establishment of orthogonal projection matrix requires (left, right, top, bottom, near, far) a rectangular box with left and right, up and down, near clipping plane and far clipping plane.

Orthogonal projection is the projection of the real world into a clipped space

The total length, width and depth of the cropped space are all 2. The real world is defined by itself, and we only need to scale in a certain proportion

The ratio of the real world to the clipped space is calculated by projecting the right minus left (1 – (-1)) in the clipped space to the right minus left in the real world

Const w = (1.0 - (-1.0))/(right-left) = 2 / (right-left) const h = (1.0 - (-1.0))/(top-bottom) = 2 / (top) Top) const p = (1.0 - (-1.0))/(far-near) = 2 / (far-near)Copy the code

The real world displacement in the clipping space is as follows (the displacement in the clipping space plus the value of the origin (center point) of the coordinates in the clipping space) times the scale in this direction

const x = (( right - left )/2 +left) * w const y = (( top - bottom )/2 +bottom) * h const z = (( far - near )/2 +near) *  pCopy the code

And then you get the projection matrix

te[ 0 ] = w;  te[ 4 ] = 0;  te[ 8 ] = 0;  te[ 12 ] = - x;
te[ 1 ] = 0;  te[ 5 ] = h;  te[ 9 ] = 0;  te[ 13 ] = - y;
te[ 2 ] = 0;  te[ 6 ] = 0;  te[ 10 ] = -p;  te[ 14 ] = - z;
te[ 3 ] = 0;  te[ 7 ] = 0;  te[ 11 ] = 0; te[ 15 ] = 1;
Copy the code

The source code

makeOrthographic( left, right, top, bottom, near, far ) { const te = this.elements; Const w = 1.0 / (right-left); Const h = 1.0 / (top-bottom); Const p = 1.0 / (far-near); const x = ( right + left ) * w; const y = ( top + bottom ) * h; const z = ( far + near ) * p; te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y; te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = - 2 * p; te[ 14 ] = - z; te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1; return this; }Copy the code

Compare the calculated results

{ const projectionMatrix = new Matrix4() projectionMatrix.makeOrthographic( -3, 3, 4, -4, -2, 2) console.log(projectionMatrix.elements); / / [0.3333333333333333, 0, 0, 0, 0, 0.25, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1]} {makeOrthographic (3, 3, 4, 4, 2, 2) function makeOrthographic(left, right, top, bottom, near, far ) { const w = 2 / ( right - left ) const h = 2 / ( top - bottom ) const p = 2 / ( far - near ) const x = (( right - left )/2 +left) * w const y = (( top - bottom )/2 +bottom) * h const z = (( far - near )/2 +near) * p const te = []; te[ 0 ] = w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; te[ 1 ] = 0; te[ 5 ] = h; te[ 9 ] = 0; te[ 13 ] = - y; te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = -p; te[ 14 ] = - z; te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1; console.log(te); / / [0.3333333333333333, 0, 0, 0, 0, 0.25, 0, 0, 0, 0, 0.5, 0, 0, 0, 0, 1]}}Copy the code

The result is slightly different from the source code, but it is not hard to find that the calculation results are the same

// Const w = 2 / (right-left) const h = 2 / (top-bottom) const p = 2 / (far-near) const x = (right) -left)/2 +left) * w const y = ((top-bottom)/2 +bottom) * h const z = (far-near)/2 +near) * p When the width, height and depth of the clipping space in the zoom ratio is 1 // simplify the same as in the source code, Const w = 1 / (right-left) const h = 1 / (top-bottom) const p = 1 / (far-near) const w = 1 / (right) const h = 1 / (top-bottom) const p = 1 / (far-near) const x = (( right - left )/2 +left) * 2w // (( right - left ) + 2left) * w // ( right + left ) * w const y = (( top - bottom )/2 +bottom) * 2h // ( top - bottom + 2bottom) * h // ( top + bottom ) * h const z = (( far - near )/2 +near) * 2p // ( far - near + 2near) * p // ( far + near ) * p; }Copy the code

\