Просмотр исходного кода

WebGLOutput: Optimize MSAA support. (#34030)

Michael Herzog 1 неделя назад
Родитель
Сommit
1d6e89cb3a
1 измененных файлов с 37 добавлено и 44 удалено
  1. 37 44
      src/renderers/webgl/WebGLOutput.js

+ 37 - 44
src/renderers/webgl/WebGLOutput.js

@@ -8,16 +8,13 @@ import {
 	NeutralToneMapping,
 	CustomToneMapping,
 	SRGBTransfer,
-	HalfFloatType,
-	DepthStencilFormat,
-	UnsignedInt248Type
+	HalfFloatType
 } from '../../constants.js';
 import { BufferGeometry } from '../../core/BufferGeometry.js';
 import { Float32BufferAttribute } from '../../core/BufferAttribute.js';
 import { RawShaderMaterial } from '../../materials/RawShaderMaterial.js';
 import { Mesh } from '../../objects/Mesh.js';
 import { OrthographicCamera } from '../../cameras/OrthographicCamera.js';
-import { DepthTexture } from '../../textures/DepthTexture.js';
 import { WebGLRenderTarget } from '../WebGLRenderTarget.js';
 import { ColorManagement } from '../../math/ColorManagement.js';
 
@@ -33,37 +30,21 @@ const toneMappingMap = {
 
 function WebGLOutput( type, width, height, antialias, depth, stencil ) {
 
-	// make sure depth texture matches renderer settings
-
-	let depthTexture;
-
-	if ( depth === true ) {
-
-		depthTexture = new DepthTexture( width, height );
-
-		if ( stencil === true ) {
-
-			depthTexture.format = DepthStencilFormat;
-			depthTexture.type = UnsignedInt248Type;
-
-		}
-
-	}
-
-	// render targets for scene and post-processing
-	const targetA = new WebGLRenderTarget( width, height, {
+	// render target for the scene pass (potentially multisampled)
+	const targetScene = new WebGLRenderTarget( width, height, {
 		type: type,
 		depthBuffer: depth,
 		stencilBuffer: stencil,
 		samples: antialias ? 4 : 0,
-		depthTexture: depthTexture
+		storeMultisampledDepthBuffer: false,
+		storeMultisampledStencilBuffer: false,
+		resolveDepthBuffer: false,
+		resolveStencilBuffer: false
 	} );
 
-	const targetB = new WebGLRenderTarget( width, height, {
-		type: HalfFloatType,
-		depthBuffer: false,
-		stencilBuffer: false
-	} );
+	// single-sampled ping-pong buffers for post-processing effects, allocated on demand
+	let targetA = null;
+	let targetB = null;
 
 	// create fullscreen triangle geometry
 	const geometry = new BufferGeometry();
@@ -140,8 +121,10 @@ function WebGLOutput( type, width, height, antialias, depth, stencil ) {
 
 	this.setSize = function ( width, height ) {
 
-		targetA.setSize( width, height );
-		targetB.setSize( width, height );
+		targetScene.setSize( width, height );
+
+		if ( targetA !== null ) targetA.setSize( width, height );
+		if ( targetB !== null ) targetB.setSize( width, height );
 
 		for ( let i = 0; i < _effects.length; i ++ ) {
 
@@ -157,8 +140,15 @@ function WebGLOutput( type, width, height, antialias, depth, stencil ) {
 		_effects = effects;
 		_hasRenderPass = _effects.length > 0 && _effects[ 0 ].isRenderPass === true;
 
-		const width = targetA.width;
-		const height = targetA.height;
+		const width = targetScene.width;
+		const height = targetScene.height;
+
+		if ( _effects.length > 0 && targetA === null ) {
+
+			targetA = new WebGLRenderTarget( width, height, { type: HalfFloatType, depthBuffer: false, stencilBuffer: false } );
+			targetB = new WebGLRenderTarget( width, height, { type: HalfFloatType, depthBuffer: false, stencilBuffer: false } );
+
+		}
 
 		for ( let i = 0; i < _effects.length; i ++ ) {
 
@@ -184,7 +174,7 @@ function WebGLOutput( type, width, height, antialias, depth, stencil ) {
 			const width = renderTarget.width;
 			const height = renderTarget.height;
 
-			if ( targetA.width !== width || targetA.height !== height ) {
+			if ( targetScene.width !== width || targetScene.height !== height ) {
 
 				this.setSize( width, height );
 
@@ -192,10 +182,10 @@ function WebGLOutput( type, width, height, antialias, depth, stencil ) {
 
 		}
 
-		// if first effect is a RenderPass, it will set its own render target
+		// if the first effect is a RenderPass, it renders the scene itself (see end())
 		if ( _hasRenderPass === false ) {
 
-			renderer.setRenderTarget( targetA );
+			renderer.setRenderTarget( targetScene );
 
 		}
 
@@ -220,9 +210,10 @@ function WebGLOutput( type, width, height, antialias, depth, stencil ) {
 
 		_isCompositing = true;
 
-		// run post-processing effects
-		let readBuffer = targetA;
-		let writeBuffer = targetB;
+		// run post-processing effects - the scene lives in the multisampled targetScene,
+		// effects ping-pong between the single-sampled targetA and targetB
+		let readBuffer = targetScene;
+		let writeBuffer = targetA;
 
 		for ( let i = 0; i < _effects.length; i ++ ) {
 
@@ -234,9 +225,9 @@ function WebGLOutput( type, width, height, antialias, depth, stencil ) {
 
 			if ( effect.needsSwap !== false ) {
 
-				const temp = readBuffer;
+				// keep targetScene out of the rotation so only the scene pass is multisampled
 				readBuffer = writeBuffer;
-				writeBuffer = temp;
+				writeBuffer = ( writeBuffer === targetA ) ? targetB : targetA;
 
 			}
 
@@ -277,9 +268,11 @@ function WebGLOutput( type, width, height, antialias, depth, stencil ) {
 
 	this.dispose = function () {
 
-		if ( targetA.depthTexture ) targetA.depthTexture.dispose();
-		targetA.dispose();
-		targetB.dispose();
+		targetScene.dispose();
+
+		if ( targetA !== null ) targetA.dispose();
+		if ( targetB !== null ) targetB.dispose();
+
 		geometry.dispose();
 		material.dispose();
 

粤ICP备19079148号