Skip to content

Commit

Permalink
WebGLRenderer: add reverse-z via EXT_clip_control (#29445)
Browse files Browse the repository at this point in the history
* WebGLRenderer: add reverse-z via EXT_clip_control

* WebGLRenderer: move conversion methods to utils
  • Loading branch information
CodyJasonBennett authored Sep 21, 2024
1 parent 33a60fa commit 01777f0
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 4 deletions.
29 changes: 26 additions & 3 deletions src/renderers/WebGLRenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ import { WebGLUtils } from './webgl/WebGLUtils.js';
import { WebXRManager } from './webxr/WebXRManager.js';
import { WebGLMaterials } from './webgl/WebGLMaterials.js';
import { WebGLUniformsGroups } from './webgl/WebGLUniformsGroups.js';
import { createCanvasElement, probeAsync, warnOnce } from '../utils.js';
import { createCanvasElement, probeAsync, toNormalizedProjectionMatrix, toReversedProjectionMatrix, warnOnce } from '../utils.js';
import { ColorManagement } from '../math/ColorManagement.js';

class WebGLRenderer {
Expand Down Expand Up @@ -196,6 +196,7 @@ class WebGLRenderer {

// camera matrices cache

const _currentProjectionMatrix = new Matrix4();
const _projScreenMatrix = new Matrix4();

const _vector3 = new Vector3();
Expand Down Expand Up @@ -291,6 +292,8 @@ class WebGLRenderer {

state = new WebGLState( _gl );

if ( capabilities.reverseDepthBuffer ) state.buffers.depth.setReversed( true );

info = new WebGLInfo( _gl );
properties = new WebGLProperties();
textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info );
Expand Down Expand Up @@ -590,7 +593,13 @@ class WebGLRenderer {

}

if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT;
if ( depth ) {

bits |= _gl.DEPTH_BUFFER_BIT;
_gl.clearDepth( this.capabilities.reverseDepthBuffer ? 0 : 1 );

}

if ( stencil ) {

bits |= _gl.STENCIL_BUFFER_BIT;
Expand Down Expand Up @@ -1971,7 +1980,21 @@ class WebGLRenderer {

// common camera uniforms

p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );
if ( capabilities.reverseDepthBuffer ) {

_currentProjectionMatrix.copy( camera.projectionMatrix );

toNormalizedProjectionMatrix( _currentProjectionMatrix );
toReversedProjectionMatrix( _currentProjectionMatrix );

p_uniforms.setValue( _gl, 'projectionMatrix', _currentProjectionMatrix );

} else {

p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix );

}

p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse );

const uCamPos = p_uniforms.map.cameraPosition;
Expand Down
9 changes: 9 additions & 0 deletions src/renderers/webgl/WebGLCapabilities.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,14 @@ function WebGLCapabilities( gl, extensions, parameters, utils ) {
}

const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true;
const reverseDepthBuffer = parameters.reverseDepthBuffer === true && extensions.has( 'EXT_clip_control' );

if ( reverseDepthBuffer === true ) {

const ext = extensions.get( 'EXT_clip_control' );
ext.clipControlEXT( ext.LOWER_LEFT_EXT, ext.ZERO_TO_ONE_EXT );

}

const maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS );
const maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
Expand Down Expand Up @@ -119,6 +127,7 @@ function WebGLCapabilities( gl, extensions, parameters, utils ) {

precision: precision,
logarithmicDepthBuffer: logarithmicDepthBuffer,
reverseDepthBuffer: reverseDepthBuffer,

maxTextures: maxTextures,
maxVertexTextures: maxVertexTextures,
Expand Down
21 changes: 21 additions & 0 deletions src/renderers/webgl/WebGLState.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@ import { NotEqualDepth, GreaterDepth, GreaterEqualDepth, EqualDepth, LessEqualDe
import { Color } from '../../math/Color.js';
import { Vector4 } from '../../math/Vector4.js';

const reversedFuncs = {
[ NeverDepth ]: AlwaysDepth,
[ LessDepth ]: GreaterDepth,
[ EqualDepth ]: NotEqualDepth,
[ LessEqualDepth ]: GreaterEqualDepth,

[ AlwaysDepth ]: NeverDepth,
[ GreaterDepth ]: LessDepth,
[ NotEqualDepth ]: EqualDepth,
[ GreaterEqualDepth ]: LessEqualDepth,
};

function WebGLState( gl ) {

function ColorBuffer() {
Expand Down Expand Up @@ -66,13 +78,20 @@ function WebGLState( gl ) {
function DepthBuffer() {

let locked = false;
let reversed = false;

let currentDepthMask = null;
let currentDepthFunc = null;
let currentDepthClear = null;

return {

setReversed: function ( value ) {

reversed = value;

},

setTest: function ( depthTest ) {

if ( depthTest ) {
Expand Down Expand Up @@ -100,6 +119,8 @@ function WebGLState( gl ) {

setFunc: function ( depthFunc ) {

if ( reversed ) depthFunc = reversedFuncs[ depthFunc ];

if ( currentDepthFunc !== depthFunc ) {

switch ( depthFunc ) {
Expand Down
34 changes: 33 additions & 1 deletion src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,36 @@ function probeAsync( gl, sync, interval ) {

}

export { arrayMin, arrayMax, arrayNeedsUint32, getTypedArray, createElementNS, createCanvasElement, warnOnce, probeAsync };
function toNormalizedProjectionMatrix( projectionMatrix ) {

const m = projectionMatrix.elements;

// Convert [-1, 1] to [0, 1] projection matrix
m[ 2 ] = 0.5 * m[ 2 ] + 0.5 * m[ 3 ];
m[ 6 ] = 0.5 * m[ 6 ] + 0.5 * m[ 7 ];
m[ 10 ] = 0.5 * m[ 10 ] + 0.5 * m[ 11 ];
m[ 14 ] = 0.5 * m[ 14 ] + 0.5 * m[ 15 ];

}

function toReversedProjectionMatrix( projectionMatrix ) {

const m = projectionMatrix.elements;
const isPerspectiveMatrix = m[ 11 ] === - 1;

// Reverse [0, 1] projection matrix
if ( isPerspectiveMatrix ) {

m[ 10 ] = - m[ 10 ] - 1;
m[ 14 ] = - m[ 14 ];

} else {

m[ 10 ] = - m[ 10 ];
m[ 14 ] = - m[ 14 ] + 1;

}

}

export { arrayMin, arrayMax, arrayNeedsUint32, getTypedArray, createElementNS, createCanvasElement, warnOnce, probeAsync, toNormalizedProjectionMatrix, toReversedProjectionMatrix };

0 comments on commit 01777f0

Please sign in to comment.