Skip to content

Instantly share code, notes, and snippets.

@CodyJasonBennett
Created September 19, 2022 10:03
Show Gist options
  • Save CodyJasonBennett/3476ff353a6c2b88e4ec23ec114ea004 to your computer and use it in GitHub Desktop.
Save CodyJasonBennett/3476ff353a6c2b88e4ec23ec114ea004 to your computer and use it in GitHub Desktop.
three WebGPU matrix polyfill test
function polyfills() {
THREE.Camera.prototype.clippingSpace = 'webgl'
THREE.PerspectiveCamera.prototype.updateProjectionMatrix = function() {
const near = this.near;
let top = near * Math.tan( THREE.MathUtils.DEG2RAD * 0.5 * this.fov ) / this.zoom;
let height = 2 * top;
let width = this.aspect * height;
let left = - 0.5 * width;
const view = this.view;
if ( this.view !== null && this.view.enabled ) {
const fullWidth = view.fullWidth,
fullHeight = view.fullHeight;
left += view.offsetX * width / fullWidth;
top -= view.offsetY * height / fullHeight;
width *= view.width / fullWidth;
height *= view.height / fullHeight;
}
const skew = this.filmOffset;
if ( skew !== 0 ) left += near * skew / this.getFilmWidth();
const normalized = this.clippingSpace === 'webgpu'
this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, normalized );
this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
}
THREE.OrthographicCamera.prototype.updateProjectionMatrix = function() {
const dx = ( this.right - this.left ) / ( 2 * this.zoom );
const dy = ( this.top - this.bottom ) / ( 2 * this.zoom );
const cx = ( this.right + this.left ) / 2;
const cy = ( this.top + this.bottom ) / 2;
let left = cx - dx;
let right = cx + dx;
let top = cy + dy;
let bottom = cy - dy;
if ( this.view !== null && this.view.enabled ) {
const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom;
const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom;
left += scaleW * this.view.offsetX;
right = left + scaleW * this.view.width;
top -= scaleH * this.view.offsetY;
bottom = top - scaleH * this.view.height;
}
const normalized = this.clippingSpace === 'webgpu'
this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, normalized );
this.projectionMatrixInverse.copy( this.projectionMatrix ).invert();
}
THREE.Matrix4.prototype.makePerspective = function ( left, right, top, bottom, near, far, normalized = false ) {
const te = this.elements;
const x = 2 * near / ( right - left );
const y = 2 * near / ( top - bottom );
const a = ( right + left ) / ( right - left );
const b = ( top + bottom ) / ( top - bottom );
let c, d
if ( normalized === true ) {
c = - far / ( far - near )
d = ( - far * near ) / ( far - near )
} else {
c = - ( far + near ) / ( far - near )
d = ( -2 * far * near ) / ( far - near )
}
te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0;
te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0;
te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d;
te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0;
return this;
};
THREE.Matrix4.prototype.makeOrthographic = function ( left, right, top, bottom, near, far, normalized = false ) {
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;
let z, zInv
if ( normalized === true ) {
z = near * p
zInv = -1 * p
} else {
z = ( far + near ) * p
zInv = -2 * 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] = zInv; te[ 14 ] = - z;
te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1;
return this;
};
THREE.Frustum.prototype.setFromProjectionMatrix = function ( m, normalized = false ) {
const planes = this.planes;
const me = m.elements;
const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ];
const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ];
const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ];
const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ];
planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize();
planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize();
planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize();
planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize();
planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize();
if ( normalized === true ) {
planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize();
} else {
planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize();
}
return this;
};
}
// Default
console.log(
new THREE.PerspectiveCamera().projectionMatrix.toArray(),
new THREE.OrthographicCamera().projectionMatrix.toArray()
)
// Default should be the same (opt-out for WebGL)
console.log(
new THREE.PerspectiveCamera().projectionMatrix.toArray(),
new THREE.OrthographicCamera().projectionMatrix.toArray()
)
// WebGPU should be opt-in
const p = new THREE.PerspectiveCamera()
p.clippingSpace = 'webgpu'
p.updateProjectionMatrix()
const o = new THREE.OrthographicCamera()
o.clippingSpace = 'webgpu'
o.updateProjectionMatrix()
console.log( p.projectionMatrix.toArray(), o.projectionMatrix.toArray() )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment