Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/webgpu_xr_rollercoaster.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@

let mesh, material, geometry;

const renderer = new THREE.WebGPURenderer( { antialias: true, forceWebGL: true, colorBufferType: THREE.UnsignedByteType, multiview: false } );
const renderer = new THREE.WebGPURenderer( { antialias: true, forceWebGL: true, outputBufferType: THREE.UnsignedByteType, multiview: false } );
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight );
renderer.setAnimationLoop( animate );
Expand Down
2 changes: 1 addition & 1 deletion src/nodes/display/PassNode.js
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,7 @@ class PassNode extends TempNode {

this.renderTarget.samples = this.options.samples === undefined ? renderer.samples : this.options.samples;

this.renderTarget.texture.type = renderer.getColorBufferType();
this.renderTarget.texture.type = renderer.getOutputBufferType();

return this.scope === PassNode.COLOR ? this.getTextureNode() : this.getLinearDepthNode();

Expand Down
32 changes: 23 additions & 9 deletions src/renderers/common/Renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ class Renderer {
* @property {number} [samples=0] - When `antialias` is `true`, `4` samples are used by default. This parameter can set to any other integer value than 0
* to overwrite the default.
* @property {?Function} [getFallback=null] - This callback function can be used to provide a fallback backend, if the primary backend can't be targeted.
* @property {number} [colorBufferType=HalfFloatType] - Defines the type of color buffers. The default `HalfFloatType` is recommend for best
* @property {number} [outputBufferType=HalfFloatType] - Defines the type of output buffers. The default `HalfFloatType` is recommend for best
* quality. To save memory and bandwidth, `UnsignedByteType` might be used. This will reduce rendering quality though.
* @property {boolean} [multiview=false] - If set to `true`, the renderer will use multiview during WebXR rendering if supported.
*/
Expand Down Expand Up @@ -97,7 +97,7 @@ class Renderer {
antialias = false,
samples = 0,
getFallback = null,
colorBufferType = HalfFloatType,
outputBufferType = HalfFloatType,
multiview = false
} = parameters;

Expand Down Expand Up @@ -584,15 +584,15 @@ class Renderer {
this.onDeviceLost = this._onDeviceLost;

/**
* Defines the type of color buffers. The default `HalfFloatType` is recommend for
* Defines the type of output buffers. The default `HalfFloatType` is recommend for
* best quality. To save memory and bandwidth, `UnsignedByteType` might be used.
* This will reduce rendering quality though.
*
* @private
* @type {number}
* @default HalfFloatType
*/
this._colorBufferType = colorBufferType;
this._outputBufferType = outputBufferType;

/**
* A cache for shadow nodes per material
Expand Down Expand Up @@ -1084,13 +1084,27 @@ class Renderer {
}

/**
* Returns the color buffer type.
* Returns the output buffer type.
*
* @return {number} The color buffer type.
* @return {number} The output buffer type.
*/
getColorBufferType() {
getOutputBufferType() {

return this._colorBufferType;
return this._outputBufferType;

}

/**
* Returns the output buffer type.
*
* @deprecated since r182. Use `.getOutputBufferType()` instead.
* @return {number} The output buffer type.
*/
getColorBufferType() { // @deprecated, r182

warnOnce( 'Renderer: ".getColorBufferType()" has been renamed to ".getOutputBufferType()".' );

return this.getOutputBufferType();

}

Expand Down Expand Up @@ -1266,7 +1280,7 @@ class Renderer {
frameBufferTarget = new RenderTarget( width, height, {
depthBuffer: depth,
stencilBuffer: stencil,
type: this._colorBufferType,
type: this._outputBufferType,
format: RGBAFormat,
colorSpace: ColorManagement.workingColorSpace,
generateMipmaps: false,
Expand Down
2 changes: 1 addition & 1 deletion src/renderers/webgpu/WebGPURenderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class WebGPURenderer extends Renderer {
* @property {boolean} [forceWebGL=false] - If set to `true`, the renderer uses a WebGL 2 backend no matter if WebGPU is supported or not.
* @property {boolean} [multiview=false] - If set to `true`, the renderer will use multiview during WebXR rendering if supported.
* @property {number} [outputType=undefined] - Texture type for output to canvas. By default, device's preferred format is used; other formats may incur overhead.
* @property {number} [colorBufferType=HalfFloatType] - Defines the type of color buffers. The default `HalfFloatType` is recommend for best
* @property {number} [outputBufferType=HalfFloatType] - Defines the type of output buffers. The default `HalfFloatType` is recommend for best
* quality. To save memory and bandwidth, `UnsignedByteType` might be used. This will reduce rendering quality though.
*/

Expand Down
18 changes: 13 additions & 5 deletions src/renderers/webgpu/utils/WebGPUUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -220,23 +220,31 @@ class WebGPUUtils {
*/
getPreferredCanvasFormat() {

const outputType = this.backend.parameters.outputType;
const parameters = this.backend.parameters;

if ( outputType === undefined ) {
let bufferType = parameters.outputBufferType;

if ( bufferType === undefined ) {

bufferType = parameters.outputType;

}
Comment on lines +225 to +231
Copy link
Collaborator

@donmccurdy donmccurdy Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, I think we're going to create problems having outputBufferType override outputType. It must be possible to specify a higher-precision format for the frame buffer used before tone mapping, without necessarily having a higher-precision canvas format / drawing buffer.

I am a bit worried by how similar the "output" names are, too, but I'll put that comment in #32461.

Copy link
Collaborator Author

@sunag sunag Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

outputType would not be essential for defining the output buffer; if the user does not define outputBufferType, it will use the most appropriate one for output rendering. I think this is still consistent with the observation above.

Possible scenarios:

// canvas buffer 16bpc + 16bpc screen output target
const renderer = new THREE.WebGPURenderer( {
	outputType: THREE.HalfFloatType,
	outputBufferType: THREE.HalfFloatType
} );

// canvas buffer 16bpc + 8bpc screen output target
const renderer = new THREE.WebGPURenderer( {
	outputType: THREE.UnsignedByteType,
	outputBufferType: THREE.HalfFloatType
} );

// canvas buffer 8bpc + 16bpc screen output target
const renderer = new THREE.WebGPURenderer( {
	outputType: THREE.HalfFloatType,
	outputBufferType: THREE.UnsignedByteType
} );

// canvas buffer 8bpc + 8bpc screen output target
const renderer = new THREE.WebGPURenderer( {
	outputType: THREE.UnsignedByteType,
	outputBufferType: THREE.UnsignedByteType
} );

// reason for this conditional, most appropriate selection if not defined outputBufferType

// canvas buffer 16bpc + 16bpc output target
const renderer = new THREE.WebGPURenderer( {
	outputType: THREE.HalfFloatType
} );

// canvas buffer 8bpc + 8bpc output target
const renderer = new THREE.WebGPURenderer( {
	outputType: THREE.UnsignedByteType,
} );

Copy link
Collaborator

@donmccurdy donmccurdy Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the case I was thinking of:

// working buffer 16bpc + 8bpc screen output target
const renderer = new THREE.WebGPURenderer( {
	outputType: THREE.UnsignedByteType,
	outputBufferType: THREE.HalfFloatType
} );

From a glance at the code it looks like outputType would be overridden by outputBufferType to HalfFloatType when configuring the WebGPU canvas context. I haven't tested this locally yet, though, and will try to do that.

EDIT: Tested and confirmed the issue.

Copy link
Collaborator

@Mugen87 Mugen87 Dec 8, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about reverting the changes to getPreferredCanvasFormat() until there is an agreement on how to proceed?

I must also say the naming outputType and outputBufferType is a bit confusing to me. When outputType is mainly about the canvas, maybe canvasType is more clear?


if ( bufferType === undefined ) {

return navigator.gpu.getPreferredCanvasFormat();

} else if ( outputType === UnsignedByteType ) {
} else if ( bufferType === UnsignedByteType ) {

return GPUTextureFormat.BGRA8Unorm;

} else if ( outputType === HalfFloatType ) {
} else if ( bufferType === HalfFloatType ) {

return GPUTextureFormat.RGBA16Float;

} else {

throw new Error( 'Unsupported outputType' );
throw new Error( 'Unsupported output buffer type.' );

}

Expand Down