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
\