Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for DEPTH16 texture format and its used for PCF shadow maps #7142

Merged
merged 1 commit into from
Nov 27, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => {
options: [
{ v: pc.SHADOW_PCF1, t: 'PCF1' },
{ v: pc.SHADOW_PCF3, t: 'PCF3' },
{ v: pc.SHADOW_PCF5, t: 'PCF5' }
{ v: pc.SHADOW_PCF5, t: 'PCF5' },
{ v: pc.SHADOW_PCF1_FLOAT16, t: 'PCF1_FLOAT16' },
{ v: pc.SHADOW_PCF3_FLOAT16, t: 'PCF3_FLOAT16' },
{ v: pc.SHADOW_PCF5_FLOAT16, t: 'PCF5_FLOAT16' }
]
})
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => {
options: [
{ v: pc.SHADOW_PCF1, t: 'PCF1' },
{ v: pc.SHADOW_PCF3, t: 'PCF3' },
{ v: pc.SHADOW_PCF5, t: 'PCF5' }
{ v: pc.SHADOW_PCF5, t: 'PCF5' },
{ v: pc.SHADOW_PCF1_FLOAT16, t: 'PCF1_FLOAT16' },
{ v: pc.SHADOW_PCF3_FLOAT16, t: 'PCF3_FLOAT16' },
{ v: pc.SHADOW_PCF5_FLOAT16, t: 'PCF5_FLOAT16' }
]
})
)
Expand Down
3 changes: 3 additions & 0 deletions examples/src/examples/graphics/shadow-cascades.controls.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ export const controls = ({ observer, ReactPCUI, React, jsx, fragment }) => {
{ v: pc.SHADOW_PCF1, t: 'PCF1' },
{ v: pc.SHADOW_PCF3, t: 'PCF3' },
{ v: pc.SHADOW_PCF5, t: 'PCF5' },
{ v: pc.SHADOW_PCF1_FLOAT16, t: 'PCF1_FLOAT16' },
{ v: pc.SHADOW_PCF3_FLOAT16, t: 'PCF3_FLOAT16' },
{ v: pc.SHADOW_PCF5_FLOAT16, t: 'PCF5_FLOAT16' },
{ v: pc.SHADOW_VSM8, t: 'VSM8' },
{ v: pc.SHADOW_VSM16, t: 'VSM16' },
{ v: pc.SHADOW_VSM32, t: 'VSM32' }
Expand Down
20 changes: 10 additions & 10 deletions src/framework/components/light/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -547,16 +547,16 @@ class LightComponent extends Component {
/**
* Sets the type of shadows being rendered by this light. Can be:
*
* - {@link SHADOW_PCF3}: Render depth, can be used for PCF 3x3 sampling.
* - {@link SHADOW_VSM8}: Render packed variance shadow map. All shadow receivers must also cast
* shadows for this mode to work correctly.
* - {@link SHADOW_VSM16}: Render 16-bit exponential variance shadow map. Requires
* OES_texture_half_float extension. Falls back to {@link SHADOW_VSM8}, if not supported.
* - {@link SHADOW_VSM32}: Render 32-bit exponential variance shadow map. Requires
* OES_texture_float extension. Falls back to {@link SHADOW_VSM16}, if not supported.
* - {@link SHADOW_PCF5}: Render depth buffer only, can be used for hardware-accelerated PCF 5x5
* sampling.
* - {@link SHADOW_PCSS}: Render depth as color, and use the software sampled PCSS method for shadows.
* - {@link SHADOW_PCF1}
* - {@link SHADOW_PCF3}
* - {@link SHADOW_PCF5}
* - {@link SHADOW_PCF1_FLOAT16}
* - {@link SHADOW_PCF3_FLOAT16}
* - {@link SHADOW_PCF5_FLOAT16}
* - {@link SHADOW_VSM8}
* - {@link SHADOW_VSM16}
* - {@link SHADOW_VSM32}
* - {@link SHADOW_PCSS}
*
* @type {number}
*/
Expand Down
11 changes: 10 additions & 1 deletion src/platform/graphics/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -1069,6 +1069,14 @@ export const PIXELFORMAT_BC7 = 67;
*/
export const PIXELFORMAT_BC7_SRGBA = 68;

/**
* A 16-bit depth buffer format.
*
* @type {number}
* @category Graphics
*/
export const PIXELFORMAT_DEPTH16 = 69;

/**
* Information about pixel formats.
*
Expand Down Expand Up @@ -1100,12 +1108,13 @@ export const pixelFormatInfo = new Map([
[PIXELFORMAT_RGBA32F, { name: 'RGBA32F', size: 16 }],
[PIXELFORMAT_R32F, { name: 'R32F', size: 4 }],
[PIXELFORMAT_DEPTH, { name: 'DEPTH', size: 4 }],
[PIXELFORMAT_DEPTH16, { name: 'DEPTH16', size: 2 }],
[PIXELFORMAT_DEPTHSTENCIL, { name: 'DEPTHSTENCIL', size: 4 }],
[PIXELFORMAT_111110F, { name: '111110F', size: 4 }],
[PIXELFORMAT_SRGB8, { name: 'SRGB8', size: 4, ldr: true, srgb: true }],
[PIXELFORMAT_SRGBA8, { name: 'SRGBA8', size: 4, ldr: true, srgb: true }],
[PIXELFORMAT_BGRA8, { name: 'BGRA8', size: 4, ldr: true }],
[PIXELFORMAT_SBGRA8, { name: 'SBGRA8', size: 4, ldr: true, srgb: true }],
[PIXELFORMAT_SBGRA8, { name: 'SBGRA8', size: 4, ldr: true, srgb: true }],

// compressed formats
[PIXELFORMAT_DXT1, { name: 'DXT1', blockSize: 8, ldr: true, srgbFormat: PIXELFORMAT_DXT1_SRGB }],
Expand Down
4 changes: 2 additions & 2 deletions src/platform/graphics/render-target.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Debug } from '../../core/debug.js';
import { TRACEID_RENDER_TARGET_ALLOC } from '../../core/constants.js';
import { PIXELFORMAT_DEPTH, PIXELFORMAT_DEPTHSTENCIL, PIXELFORMAT_R32F, isSrgbPixelFormat } from './constants.js';
import { PIXELFORMAT_DEPTH, PIXELFORMAT_DEPTH16, PIXELFORMAT_DEPTHSTENCIL, PIXELFORMAT_R32F, isSrgbPixelFormat } from './constants.js';
import { DebugGraphics } from './debug-graphics.js';
import { GraphicsDevice } from './graphics-device.js';
import { TextureUtils } from './texture-utils.js';
Expand Down Expand Up @@ -191,7 +191,7 @@ class RenderTarget {

if (this._depthBuffer) {
const format = this._depthBuffer._format;
if (format === PIXELFORMAT_DEPTH) {
if (format === PIXELFORMAT_DEPTH || format === PIXELFORMAT_DEPTH16) {
this._depth = true;
this._stencil = false;
} else if (format === PIXELFORMAT_DEPTHSTENCIL) {
Expand Down
10 changes: 8 additions & 2 deletions src/platform/graphics/webgl/webgl-texture.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import {
PIXELFORMAT_DXT1_SRGB, PIXELFORMAT_DXT3_SRGBA, PIXELFORMAT_DXT5_SRGBA, PIXELFORMAT_PVRTC_2BPP_SRGB_1,
PIXELFORMAT_PVRTC_2BPP_SRGBA_1, PIXELFORMAT_PVRTC_4BPP_SRGB_1, PIXELFORMAT_PVRTC_4BPP_SRGBA_1,
PIXELFORMAT_ETC2_SRGB, PIXELFORMAT_ETC2_SRGBA, PIXELFORMAT_ASTC_4x4_SRGB, PIXELFORMAT_SBGRA8,
PIXELFORMAT_BC6F, PIXELFORMAT_BC6UF, PIXELFORMAT_BC7, PIXELFORMAT_BC7_SRGBA
PIXELFORMAT_BC6F, PIXELFORMAT_BC6UF, PIXELFORMAT_BC7, PIXELFORMAT_BC7_SRGBA,
PIXELFORMAT_DEPTH16
} from '../constants.js';

/**
Expand Down Expand Up @@ -323,9 +324,14 @@ class WebglTexture {
break;
case PIXELFORMAT_DEPTH:
this._glFormat = gl.DEPTH_COMPONENT;
this._glInternalFormat = gl.DEPTH_COMPONENT32F; // should allow 16/24 bits?
this._glInternalFormat = gl.DEPTH_COMPONENT32F;
this._glPixelType = gl.FLOAT;
break;
case PIXELFORMAT_DEPTH16:
this._glFormat = gl.DEPTH_COMPONENT;
this._glInternalFormat = gl.DEPTH_COMPONENT16;
this._glPixelType = gl.UNSIGNED_SHORT;
break;
case PIXELFORMAT_DEPTHSTENCIL:
this._glFormat = gl.DEPTH_STENCIL;
this._glInternalFormat = gl.DEPTH24_STENCIL8;
Expand Down
4 changes: 3 additions & 1 deletion src/platform/graphics/webgpu/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ import {
PIXELFORMAT_PVRTC_2BPP_SRGBA_1, PIXELFORMAT_PVRTC_4BPP_SRGB_1, PIXELFORMAT_PVRTC_4BPP_SRGBA_1,
PIXELFORMAT_ETC2_SRGB, PIXELFORMAT_ETC2_SRGBA, PIXELFORMAT_SBGRA8,
PIXELFORMAT_BC6F, PIXELFORMAT_BC6UF, PIXELFORMAT_BC7, PIXELFORMAT_BC7_SRGBA,
PIXELFORMAT_ASTC_4x4_SRGB
PIXELFORMAT_ASTC_4x4_SRGB,
PIXELFORMAT_DEPTH16
} from '../constants.js';

// map of PIXELFORMAT_*** to GPUTextureFormat
Expand All @@ -39,6 +40,7 @@ gpuTextureFormats[PIXELFORMAT_RGB32F] = '';
gpuTextureFormats[PIXELFORMAT_RGBA32F] = 'rgba32float';
gpuTextureFormats[PIXELFORMAT_R32F] = 'r32float';
gpuTextureFormats[PIXELFORMAT_DEPTH] = 'depth32float';
gpuTextureFormats[PIXELFORMAT_DEPTH16] = 'depth16unorm';
gpuTextureFormats[PIXELFORMAT_DEPTHSTENCIL] = 'depth24plus-stencil8';
gpuTextureFormats[PIXELFORMAT_111110F] = 'rg11b10ufloat';
gpuTextureFormats[PIXELFORMAT_SRGB8] = '';
Expand Down
83 changes: 62 additions & 21 deletions src/scene/constants.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { PIXELFORMAT_DEPTH, PIXELFORMAT_DEPTH16, PIXELFORMAT_R32F, PIXELFORMAT_RGBA16F, PIXELFORMAT_RGBA32F, PIXELFORMAT_RGBA8 } from '../platform/graphics/constants.js';

/**
* Subtract the color of the source fragment from the destination fragment and write the result to
* the frame buffer.
Expand Down Expand Up @@ -273,7 +275,8 @@ export const LIGHTFALLOFF_LINEAR = 0;
export const LIGHTFALLOFF_INVERSESQUARED = 1;

/**
* Render depth buffer only, can be used for PCF 3x3 sampling.
* A shadow sampling technique using 32bit shadow map that averages depth comparisons from a 3x3
* grid of texels for softened shadow edges.
*
* @type {number}
* @category Graphics
Expand All @@ -282,71 +285,109 @@ export const SHADOW_PCF3 = 0;
export const SHADOW_DEPTH = 0; // alias for SHADOW_PCF3 for backwards compatibility

/**
* Render packed variance shadow map. All shadow receivers must also cast shadows for this mode to
* work correctly.
* A shadow sampling technique using a 16-bit exponential variance shadow map packed into
* {@link PIXELFORMAT_RGBA8} that leverages variance to approximate shadow boundaries, enabling soft
* shadows. All shadow receivers must also cast shadows for this mode to work correctly.
*
* @type {number}
* @category Graphics
*/
export const SHADOW_VSM8 = 1;

/**
* Render 16-bit exponential variance shadow map. Requires OES_texture_half_float extension. Falls
* back to {@link SHADOW_VSM8}, if not supported.
* A shadow sampling technique using a 16-bit exponential variance shadow map that leverages
* variance to approximate shadow boundaries, enabling soft shadows. Only supported when
* {@link GraphicsDevice#textureHalfFloatRenderable} is true. Falls back to {@link SHADOW_VSM8}, if not
* supported.
*
* @type {number}
* @category Graphics
*/
export const SHADOW_VSM16 = 2;

/**
* Render 32-bit exponential variance shadow map. Requires OES_texture_float extension. Falls back
* to {@link SHADOW_VSM16}, if not supported.
* A shadow sampling technique using a 32-bit exponential variance shadow map that leverages
* variance to approximate shadow boundaries, enabling soft shadows. Only supported when
* {@link GraphicsDevice#textureFloatRenderable} is true. Falls back to {@link SHADOW_VSM16}, if not
* supported.
*
* @type {number}
* @category Graphics
*/
export const SHADOW_VSM32 = 3;

/**
* Render depth buffer only, can be used for hardware-accelerated PCF 5x5 sampling.
* A shadow sampling technique using 32bit shadow map that averages depth comparisons from a 5x5
* grid of texels for softened shadow edges.
*
* @type {number}
* @category Graphics
*/
export const SHADOW_PCF5 = 4;

/**
* Render depth buffer only, can be used for PCF 1x1 sampling.
* A shadow sampling technique using a 32-bit shadow map that performs a single depth comparison for
* sharp shadow edges.
*
* @type {number}
* @category Graphics
*/
export const SHADOW_PCF1 = 5;

/**
* Render depth as color for PCSS software filtering.
* A shadow sampling technique using a 32-bit shadow map that adjusts filter size based on blocker
* distance, producing realistic, soft shadow edges that vary with the light's occlusion.
*
* @type {number}
* @category Graphics
*/
export const SHADOW_PCSS = 6;

/**
* map of engine SHADOW__*** to a string representation
* A shadow sampling technique using a 16-bit shadow map that performs a single depth comparison for
* sharp shadow edges.
*
* @type {object}
* @ignore
* @type {number}
* @category Graphics
*/
export const SHADOW_PCF1_FLOAT16 = 7;

/**
* A shadow sampling technique using 16-bit shadow map that averages depth comparisons from a 3x3
* grid of texels for softened shadow edges.
*
* @type {number}
* @category Graphics
*/
export const SHADOW_PCF3_FLOAT16 = 8;

/**
* A shadow sampling technique using 16-bit shadow map that averages depth comparisons from a 3x3
* grid of texels for softened shadow edges.
*
* @type {number}
* @category Graphics
*/
export const shadowTypeToString = {};
shadowTypeToString[SHADOW_PCF3] = 'PCF3';
shadowTypeToString[SHADOW_VSM8] = 'VSM8';
shadowTypeToString[SHADOW_VSM16] = 'VSM16';
shadowTypeToString[SHADOW_VSM32] = 'VSM32';
shadowTypeToString[SHADOW_PCF5] = 'PCF5';
shadowTypeToString[SHADOW_PCF1] = 'PCF1';
shadowTypeToString[SHADOW_PCSS] = 'PCSS';
export const SHADOW_PCF5_FLOAT16 = 9;

/**
* Information about shadow types.
*
* @type {Map<number, { name: string, format: number, pcf?: boolean, vsm?: boolean }>}
* @ignore
*/
export const shadowTypeInfo = new Map([
[SHADOW_PCF1, { name: 'PCF1', format: PIXELFORMAT_DEPTH, pcf: true }],
[SHADOW_PCF3, { name: 'PCF3', format: PIXELFORMAT_DEPTH, pcf: true }],
[SHADOW_PCF5, { name: 'PCF5', format: PIXELFORMAT_DEPTH, pcf: true }],
[SHADOW_PCF1_FLOAT16, { name: 'PCF1_FLOAT16', format: PIXELFORMAT_DEPTH16, pcf: true }],
[SHADOW_PCF3_FLOAT16, { name: 'PCF3_FLOAT16', format: PIXELFORMAT_DEPTH16, pcf: true }],
[SHADOW_PCF5_FLOAT16, { name: 'PCF5_FLOAT16', format: PIXELFORMAT_DEPTH16, pcf: true }],
[SHADOW_VSM8, { name: 'VSM8', format: PIXELFORMAT_RGBA8, vsm: true }],
[SHADOW_VSM16, { name: 'VSM16', format: PIXELFORMAT_RGBA16F, vsm: true }],
[SHADOW_VSM32, { name: 'VSM32', format: PIXELFORMAT_RGBA32F, vsm: true }],
[SHADOW_PCSS, { name: 'PCSS', format: PIXELFORMAT_R32F }]
]);

/**
* Box filter.
Expand Down
29 changes: 17 additions & 12 deletions src/scene/light.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ import {
BLUR_GAUSSIAN,
LIGHTTYPE_DIRECTIONAL, LIGHTTYPE_OMNI, LIGHTTYPE_SPOT,
MASK_BAKE, MASK_AFFECT_DYNAMIC,
SHADOW_PCF1, SHADOW_PCF3, SHADOW_PCF5, SHADOW_VSM8, SHADOW_VSM16, SHADOW_VSM32, SHADOW_PCSS,
SHADOW_PCF1, SHADOW_PCF3, SHADOW_VSM8, SHADOW_VSM16, SHADOW_VSM32, SHADOW_PCSS,
SHADOWUPDATE_NONE, SHADOWUPDATE_REALTIME, SHADOWUPDATE_THISFRAME,
LIGHTSHAPE_PUNCTUAL, LIGHTFALLOFF_LINEAR
LIGHTSHAPE_PUNCTUAL, LIGHTFALLOFF_LINEAR,
shadowTypeInfo,
SHADOW_PCF1_FLOAT16,
SHADOW_PCF3_FLOAT16
} from './constants.js';
import { ShadowRenderer } from './renderer/shadow-renderer.js';
import { DepthState } from '../platform/graphics/depth-state.js';
Expand Down Expand Up @@ -50,7 +53,7 @@ let id = 0;
* Class storing shadow rendering related private information
*/
class LightRenderData {
constructor(device, camera, face, light) {
constructor(camera, face, light) {

// light this data belongs to
this.light = light;
Expand All @@ -62,7 +65,7 @@ class LightRenderData {
this.camera = camera;

// camera used to cull / render the shadow map
this.shadowCamera = ShadowRenderer.createShadowCamera(device, light._shadowType, light._type, face);
this.shadowCamera = ShadowRenderer.createShadowCamera(light._shadowType, light._type, face);

// shadow view-projection matrix
this.shadowMatrix = new Mat4();
Expand Down Expand Up @@ -386,7 +389,8 @@ class Light {
const device = this.device;

// omni light supports PCF1, PCF3 and PCSS only
if (this._type === LIGHTTYPE_OMNI && value !== SHADOW_PCF1 && value !== SHADOW_PCF3 && value !== SHADOW_PCSS) {
if (this._type === LIGHTTYPE_OMNI && value !== SHADOW_PCF1 && value !== SHADOW_PCF3 &&
value !== SHADOW_PCF1_FLOAT16 && value !== SHADOW_PCF3_FLOAT16 && value !== SHADOW_PCSS) {
value = SHADOW_PCF3;
}

Expand All @@ -400,8 +404,9 @@ class Light {
value = SHADOW_VSM8;
}

this._isVsm = value === SHADOW_VSM8 || value === SHADOW_VSM16 || value === SHADOW_VSM32;
this._isPcf = value === SHADOW_PCF1 || value === SHADOW_PCF3 || value === SHADOW_PCF5;
const shadowInfo = shadowTypeInfo.get(value);
this._isVsm = shadowInfo?.vsm ?? false;
this._isPcf = shadowInfo?.pcf ?? false;

this._shadowType = value;
this._destroyShadowMap();
Expand Down Expand Up @@ -724,7 +729,7 @@ class Light {
}

// create new one
const rd = new LightRenderData(this.device, camera, face, this);
const rd = new LightRenderData(camera, face, this);
this._renderData.push(rd);
return rd;
}
Expand Down Expand Up @@ -963,8 +968,7 @@ class Light {
// Bit
// 31 : sign bit (leave)
// 29 - 30 : type
// 28 : cast shadows
// 25 - 27 : shadow type
// 25 - 28 : shadow type
// 23 - 24 : falloff mode
// 22 : normal offset bias
// 21 : cookie
Expand All @@ -977,9 +981,9 @@ class Light {
// 8 - 9 : light num cascades
// 7 : disable specular
// 6 - 4 : mask
// 3 : cast shadows
let key =
(this._type << 29) |
((this._castShadows ? 1 : 0) << 28) |
(this._shadowType << 25) |
(this._falloffMode << 23) |
((this._normalOffsetBias !== 0.0 ? 1 : 0) << 22) |
Expand All @@ -990,7 +994,8 @@ class Light {
((this._shape) << 10) |
((this.numCascades - 1) << 8) |
((this.affectSpecularity ? 1 : 0) << 7) |
((this.mask) << 6);
((this.mask) << 6) |
((this._castShadows ? 1 : 0) << 3);

if (this._cookieChannel.length === 3) {
key |= (chanId[this._cookieChannel.charAt(1)] << 16);
Expand Down
Loading