Skip to content
Open
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
83 changes: 68 additions & 15 deletions sample/particles/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,23 @@ canvas.width = canvas.clientWidth * devicePixelRatio;
canvas.height = canvas.clientHeight * devicePixelRatio;
const presentationFormat = 'rgba16float';

const simulationParams = {
simulate: true,
deltaTime: 0.04,
colorSpace: 'srgb' as string,
toneMappingMode: 'standard' as GPUCanvasToneMappingMode,
brightnessFactor: 1.0,
};

function configureContext() {
context.configure({
device,
colorSpace: simulationParams.colorSpace as PredefinedColorSpace,
format: presentationFormat,
toneMapping: { mode: simulationParams.toneMappingMode },
});
hdrFolder.name = getHdrFolderName();
updateColorSpaceName();
}

const particlesBuffer = device.createBuffer({
Expand Down Expand Up @@ -189,18 +199,27 @@ const mipLevelCount =
const texture = device.createTexture({
size: [imageBitmap.width, imageBitmap.height, 1],
mipLevelCount,
format: 'rgba8unorm',
format: 'rgba16float',
usage:
GPUTextureUsage.TEXTURE_BINDING |
GPUTextureUsage.STORAGE_BINDING |
GPUTextureUsage.COPY_DST |
GPUTextureUsage.RENDER_ATTACHMENT,
});
device.queue.copyExternalImageToTexture(
{ source: imageBitmap },
{ texture: texture },
[imageBitmap.width, imageBitmap.height]
);
// Copies the image into mip level 0, converting its colors to the current
// color space. The alpha channel (used for the probability map) is unaffected
// by the color space, so the probability map doesn't need regenerating.
function copyImageToTexture() {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Give this a more descriptive name like "reinitLogoTexture" rather than describing what it does.

Also rename texture to logoTexture

device.queue.copyExternalImageToTexture(
{ source: imageBitmap },
{
texture: texture,
colorSpace: simulationParams.colorSpace as PredefinedColorSpace,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Doesn't doing this mean that the colorSpace option will never make a visual difference? webgpu.png is sRGB, so if we color-manage it correctly, it's always going to stay in sRGB.

We should use an image that is Display-P3 or wider (something like https://webkit.org/blog-files/color-gamut/Webkit-logo-P3.png from https://webkit.org/blog-files/color-gamut/) so we can see a difference.

But actually, there should* still be no difference because both the texture and the canvas are float formats so they don't get clamped. Would need to change the texture back to unorm.

* I tried hacking in the webkit image (keeping the float format) and it does make a visible difference so I'm not sure if I'm missing something or there is a chrome bug.

},
[imageBitmap.width, imageBitmap.height]
);
}
copyImageToTexture();

//////////////////////////////////////////////////////////////////////////////
// Probability map generation
Expand Down Expand Up @@ -275,7 +294,7 @@ device.queue.copyExternalImageToTexture(
// tex_in / tex_out
binding: 3,
resource: texture.createView({
format: 'rgba8unorm',
format: 'rgba16float',
dimension: '2d',
baseMipLevel: level,
mipLevelCount: 1,
Expand Down Expand Up @@ -303,13 +322,6 @@ device.queue.copyExternalImageToTexture(
//////////////////////////////////////////////////////////////////////////////
// Simulation compute pipeline
//////////////////////////////////////////////////////////////////////////////
const simulationParams = {
simulate: true,
deltaTime: 0.04,
toneMappingMode: 'standard' as GPUCanvasToneMappingMode,
brightnessFactor: 1.0,
};

const simulationUBOBufferSize =
1 * 4 + // deltaTime
1 * 4 + // brightnessFactor
Expand All @@ -325,7 +337,30 @@ const gui = new GUI();
gui.width = 325;
gui.add(simulationParams, 'simulate');
gui.add(simulationParams, 'deltaTime');
const hdrFolder = gui.addFolder('');
const colorFolder = gui.addFolder('Color settings');
colorFolder
.add(
simulationParams,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Let's also split colorSpace and toneMappingMode into a separate settings object, they are not "simulation params".

'colorSpace',
['srgb', 'srgb-linear', 'display-p3', 'display-p3-linear'].filter(
isColorSpaceSupported

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can we show all options even if they're disabled but somehow mark them as not available (and blank the screen when they're selected or something like that)

)
)
.onChange(() => {
configureContext();
copyImageToTexture();
});
colorFolder.open();
const p3MediaQuery = window.matchMedia('(color-gamut: p3)');
function updateColorSpaceName() {
const wantsP3 = simulationParams.colorSpace.startsWith('display-p3');
colorFolder.name =
wantsP3 && !p3MediaQuery.matches
? "Color settings ⚠️ Display isn't wide gamut"
: 'Color settings';
}
p3MediaQuery.onchange = updateColorSpaceName;
const hdrFolder = gui.addFolder('HDR settings');
hdrFolder
.add(simulationParams, 'toneMappingMode', ['standard', 'extended'])
.onChange(configureContext);
Expand Down Expand Up @@ -446,3 +481,21 @@ function assert(cond: boolean, msg = '') {
throw new Error(msg);
}
}

// Configuring a canvas context with an unsupported color space throws a
// TypeError, so probe each one on a throwaway OffscreenCanvas context.
function isColorSpaceSupported(colorSpace: string) {
const ctx = new OffscreenCanvas(1, 1).getContext('webgpu');
try {
ctx.configure({
device,
format: presentationFormat,
colorSpace: colorSpace as PredefinedColorSpace,
});
return true;
} catch {
return false;
} finally {
ctx.unconfigure();
}
}
2 changes: 1 addition & 1 deletion sample/particles/meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export default {
name: 'Particles (HDR)',
tocName: 'particles (HDR)',
description:
'This example demonstrates rendering of particles (using HDR capabilities when possible) simulated with compute shaders.',
'This example demonstrates rendering of particles simulated with compute shaders, using HDR and wide color gamut canvas capabilities when possible.',
filename: __DIRNAME__,
sources: [
{ path: 'main.ts' },
Expand Down
2 changes: 1 addition & 1 deletion sample/particles/probabilityMap.wgsl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ struct UBO {
@binding(1) @group(0) var<storage, read> buf_in : array<f32>;
@binding(2) @group(0) var<storage, read_write> buf_out : array<f32>;
@binding(3) @group(0) var tex_in : texture_2d<f32>;
@binding(3) @group(0) var tex_out : texture_storage_2d<rgba8unorm, write>;
@binding(3) @group(0) var tex_out : texture_storage_2d<rgba16float, write>;

////////////////////////////////////////////////////////////////////////////////
// import_level
Expand Down
Loading