Skip to content

Commit

Permalink
Partially refactored the lighting / shadowing part of the lit-shader …
Browse files Browse the repository at this point in the history
…generation (#7352)

Co-authored-by: Martin Valigursky <[email protected]>
  • Loading branch information
mvaligursky and Martin Valigursky authored Feb 22, 2025
1 parent 135d33f commit 7c86e72
Show file tree
Hide file tree
Showing 26 changed files with 438 additions and 295 deletions.
19 changes: 19 additions & 0 deletions src/platform/graphics/graphics-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,14 @@ class GraphicsDevice extends EventHandler {
*/
_shadersDirty = false;

/**
* A list of shader defines based on the capabilities of the device.
*
* @type {Map<string, string>}
* @ignore
*/
capsDefines = new Map();

static EVENT_RESIZE = 'resizecanvas';

constructor(canvas, options) {
Expand Down Expand Up @@ -477,6 +485,17 @@ class GraphicsDevice extends EventHandler {
});
}

/**
* Initialize the map of device capabilities, which are supplied to shaders as defines.
*
* @ignore
*/
initCapsDefines() {
const { capsDefines } = this;
capsDefines.clear();
if (this.textureFloatFilterable) capsDefines.set('CAPS_TEXTURE_FLOAT_FILTERABLE', '');
}

/**
* Destroy the graphics device.
*/
Expand Down
15 changes: 12 additions & 3 deletions src/platform/graphics/shader-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,8 @@ class ShaderUtils {
let vertCode;
let fragCode;

const vertexDefinesCode = ShaderUtils.getDefinesCode(options.vertexDefines);
const fragmentDefinesCode = ShaderUtils.getDefinesCode(options.fragmentDefines);
const vertexDefinesCode = ShaderUtils.getDefinesCode(device, options.vertexDefines);
const fragmentDefinesCode = ShaderUtils.getDefinesCode(device, options.fragmentDefines);
const wgsl = options.shaderLanguage === SHADERLANGUAGE_WGSL;

if (wgsl) {
Expand Down Expand Up @@ -160,15 +160,24 @@ class ShaderUtils {
}

/**
* @param {GraphicsDevice} device - The graphics device.
* @param {Map<string, string>} [defines] - A map containing key-value pairs.
* @returns {string} The shader code for the defines.
* @private
*/
static getDefinesCode(defines) {
static getDefinesCode(device, defines) {
let code = '';

device.capsDefines.forEach((value, key) => {
code += `#define ${key} ${value}\n`;
});
code += '\n';

defines?.forEach((value, key) => {
code += `#define ${key} ${value}\n`;
});
code += '\n';

return code;
}

Expand Down
2 changes: 2 additions & 0 deletions src/platform/graphics/webgl/webgl-graphics-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,8 @@ class WebglGraphicsDevice extends GraphicsDevice {
if (this.maxTextures <= 8) {
this.supportsAreaLights = false;
}

this.initCapsDefines();
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/platform/graphics/webgpu/webgpu-graphics-device.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ class WebgpuGraphicsDevice extends GraphicsDevice {
// WGSL features
const wgslFeatures = navigator.gpu.wgslLanguageFeatures;
this.supportsStorageTextureRead = wgslFeatures?.has('readonly_and_readwrite_storage_textures');

this.initCapsDefines();
}

async initWebGpu(glslangUrl, twgslUrl) {
Expand Down
31 changes: 22 additions & 9 deletions src/scene/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,12 @@ export const LIGHTTYPE_SPOT = 2;
// private - the number of light types
export const LIGHTTYPE_COUNT = 3;

export const lightTypeNames = {
[LIGHTTYPE_DIRECTIONAL]: 'DIRECTIONAL',
[LIGHTTYPE_OMNI]: 'OMNI',
[LIGHTTYPE_SPOT]: 'SPOT'
};

/**
* Infinitesimally small point light source shape.
*
Expand Down Expand Up @@ -258,6 +264,13 @@ export const LIGHTSHAPE_DISK = 2;
*/
export const LIGHTSHAPE_SPHERE = 3;

export const lightShapeNames = {
[LIGHTSHAPE_PUNCTUAL]: 'PUNCTUAL',
[LIGHTSHAPE_RECT]: 'RECT',
[LIGHTSHAPE_DISK]: 'DISK',
[LIGHTSHAPE_SPHERE]: 'SPHERE'
};

/**
* Linear distance falloff model for light attenuation.
*
Expand Down Expand Up @@ -384,15 +397,15 @@ export const SHADOW_PCF5_16F = 9;
* @ignore
*/
export const shadowTypeInfo = new Map([
[SHADOW_PCF1_32F, { name: 'PCF1_32F', format: PIXELFORMAT_DEPTH, pcf: true }],
[SHADOW_PCF3_32F, { name: 'PCF3_32F', format: PIXELFORMAT_DEPTH, pcf: true }],
[SHADOW_PCF5_32F, { name: 'PCF5_32F', format: PIXELFORMAT_DEPTH, pcf: true }],
[SHADOW_PCF1_16F, { name: 'PCF1_16F', format: PIXELFORMAT_DEPTH16, pcf: true }],
[SHADOW_PCF3_16F, { name: 'PCF3_16F', format: PIXELFORMAT_DEPTH16, pcf: true }],
[SHADOW_PCF5_16F, { name: 'PCF5_16F', format: PIXELFORMAT_DEPTH16, pcf: true }],
[SHADOW_VSM_16F, { name: 'VSM_16F', format: PIXELFORMAT_RGBA16F, vsm: true }],
[SHADOW_VSM_32F, { name: 'VSM_32F', format: PIXELFORMAT_RGBA32F, vsm: true }],
[SHADOW_PCSS_32F, { name: 'PCSS_32F', format: PIXELFORMAT_R32F, pcss: true }]
[SHADOW_PCF1_32F, { name: 'PCF1_32F', kind: 'PCF1', format: PIXELFORMAT_DEPTH, pcf: true }],
[SHADOW_PCF3_32F, { name: 'PCF3_32F', kind: 'PCF3', format: PIXELFORMAT_DEPTH, pcf: true }],
[SHADOW_PCF5_32F, { name: 'PCF5_32F', kind: 'PCF5', format: PIXELFORMAT_DEPTH, pcf: true }],
[SHADOW_PCF1_16F, { name: 'PCF1_16F', kind: 'PCF1', format: PIXELFORMAT_DEPTH16, pcf: true }],
[SHADOW_PCF3_16F, { name: 'PCF3_16F', kind: 'PCF3', format: PIXELFORMAT_DEPTH16, pcf: true }],
[SHADOW_PCF5_16F, { name: 'PCF5_16F', kind: 'PCF5', format: PIXELFORMAT_DEPTH16, pcf: true }],
[SHADOW_VSM_16F, { name: 'VSM_16F', kind: 'VSM', format: PIXELFORMAT_RGBA16F, vsm: true }],
[SHADOW_VSM_32F, { name: 'VSM_32F', kind: 'VSM', format: PIXELFORMAT_RGBA32F, vsm: true }],
[SHADOW_PCSS_32F, { name: 'PCSS_32F', kind: 'PCSS', format: PIXELFORMAT_R32F, pcss: true }]
]);

/**
Expand Down
18 changes: 10 additions & 8 deletions src/scene/shader-lib/chunks-wgsl/chunks-wgsl.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ import immediateLineVS from './internal/vert/immediateLine.js';
// import iridescencePS from './standard/frag/iridescence.js';
// import iridescenceThicknessPS from './standard/frag/iridescenceThickness.js';
// import iorPS from './standard/frag/ior.js';
// import lightDeclarationPS from './lit/frag/lightDeclaration.js';
// import lightDiffuseLambertPS from './lit/frag/lightDiffuseLambert.js';
// import lightDirPointPS from './lit/frag/lightDirPoint.js';
// import lightingPS from './lit/frag/lighting/lighting.js';
// import lightmapAddPS from './lit/frag/lightmapAdd.js';
// import lightmapDirAddPS from './lit/frag/lightmapDirAdd.js';
// import lightmapDirPS from './standard/frag/lightmapDir.js';
Expand Down Expand Up @@ -159,13 +161,12 @@ import immediateLineVS from './internal/vert/immediateLine.js';
// import screenDepthPS from './common/frag/screenDepth.js';
// import shadowCascadesPS from './lit/frag/shadowCascades.js';
// import shadowEVSMPS from './lit/frag/shadowEVSM.js';
// import shadowEVSMnPS from './lit/frag/shadowEVSMn.js';
// import shadowPCF1PS from './lit/frag/shadowPCF1.js';
// import shadowPCF3PS from './lit/frag/shadowPCF3.js';
// import shadowPCF5PS from './lit/frag/shadowPCF5.js';
// import shadowPCSSPS from './lit/frag/shadowPCSS.js';
// import shadowSampleCoordPS from './lit/frag/shadowSampleCoord.js';
// import shadowSoftPS from './lit/frag/shadowSoft.js';
// import shadowStandardPS from './lit/frag/shadowStandard.js';
// import shadowStandardGL2PS from './lit/frag/shadowStandardGL2.js';
// import shadowVSM_commonPS from './lit/frag/shadowVSM_common.js';
// import skinBatchVS from './common/vert/skinBatch.js';
// import skinVS from './common/vert/skin.js';
import skyboxPS from './skybox/frag/skybox.js';
Expand Down Expand Up @@ -283,8 +284,10 @@ const shaderChunksWGSL = {
// iridescencePS,
// iridescenceThicknessPS,
// iorPS,
// lightDeclarationPS,
// lightDiffuseLambertPS,
// lightDirPointPS,
// lightingPS,
// lightmapAddPS,
// lightmapDirAddPS,
// lightmapDirPS,
Expand Down Expand Up @@ -371,13 +374,12 @@ const shaderChunksWGSL = {
// screenDepthPS,
// shadowCascadesPS,
// shadowEVSMPS,
// shadowEVSMnPS,
// shadowPCF1PS,
// shadowPCF3PS
// shadowPCF5PS,
// shadowPCSSPS,
// shadowSampleCoordPS,
// shadowSoftPS,
// shadowStandardPS,
// shadowStandardGL2PS,
// shadowVSM_commonPS,
// skinBatchVS,
// skinVS,
skyboxPS,
Expand Down
9 changes: 5 additions & 4 deletions src/scene/shader-lib/chunks/chunk-validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,6 @@ const chunkVersions = {
shadowCoordPS: CHUNKAPI_1_62,
shadowCoordPerspZBufferPS: CHUNKAPI_1_62,
shadowEVSMPS: CHUNKAPI_1_62,
shadowEVSMnPS: CHUNKAPI_1_62,
shadowStandardPS: CHUNKAPI_1_62,
shadowStandardGL2PS: CHUNKAPI_1_62,
spotPS: CHUNKAPI_1_62,
TBNPS: CHUNKAPI_1_62,
TBNObjectSpacePS: CHUNKAPI_1_62,
Expand Down Expand Up @@ -114,7 +111,11 @@ const removedChunks = {
fogNonePS: CHUNKAPI_2_5,
gamma1_0PS: CHUNKAPI_2_5,
gamma2_2PS: CHUNKAPI_2_5,
storeEVSMPS: CHUNKAPI_2_6
storeEVSMPS: CHUNKAPI_2_6,
shadowEVSMnPS: CHUNKAPI_2_6,
shadowVSM_commonPS: CHUNKAPI_2_6,
shadowStandardPS: CHUNKAPI_2_6,
shadowStandardGL2PS: CHUNKAPI_2_6
};

// compare two "major.minor" semantic version strings and return true if a is a smaller version than b.
Expand Down
28 changes: 15 additions & 13 deletions src/scene/shader-lib/chunks/chunks.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ import iridescenceDiffractionPS from './lit/frag/iridescenceDiffraction.js';
import iridescencePS from './standard/frag/iridescence.js';
import iridescenceThicknessPS from './standard/frag/iridescenceThickness.js';
import iorPS from './standard/frag/ior.js';
import lightDeclarationPS from './lit/frag/lighting/lightDeclaration.js';
import lightDiffuseLambertPS from './lit/frag/lightDiffuseLambert.js';
import lightDirPointPS from './lit/frag/lightDirPoint.js';
import lightingPS from './lit/frag/lighting/lighting.js';
import lightmapAddPS from './lit/frag/lightmapAdd.js';
import lightmapDirAddPS from './lit/frag/lightmapDirAdd.js';
import lightmapDirPS from './standard/frag/lightmapDir.js';
Expand Down Expand Up @@ -157,15 +159,14 @@ import refractionDynamicPS from './lit/frag/refractionDynamic.js';
import reprojectPS from './common/frag/reproject.js';
import sampleCatmullRomPS from './common/frag/sampleCatmullRom.js';
import screenDepthPS from './common/frag/screenDepth.js';
import shadowCascadesPS from './lit/frag/shadowCascades.js';
import shadowEVSMPS from './lit/frag/shadowEVSM.js';
import shadowEVSMnPS from './lit/frag/shadowEVSMn.js';
import shadowPCSSPS from './lit/frag/shadowPCSS.js';
import shadowSampleCoordPS from './lit/frag/shadowSampleCoord.js';
import shadowSoftPS from './lit/frag/shadowSoft.js';
import shadowStandardPS from './lit/frag/shadowStandard.js';
import shadowStandardGL2PS from './lit/frag/shadowStandardGL2.js';
import shadowVSM_commonPS from './lit/frag/shadowVSM_common.js';
import shadowCascadesPS from './lit/frag/lighting/shadowCascades.js';
import shadowEVSMPS from './lit/frag/lighting/shadowEVSM.js';
import shadowPCF1PS from './lit/frag/lighting/shadowPCF1.js';
import shadowPCF3PS from './lit/frag/lighting/shadowPCF3.js';
import shadowPCF5PS from './lit/frag/lighting/shadowPCF5.js';
import shadowPCSSPS from './lit/frag/lighting/shadowPCSS.js';
import shadowSampleCoordPS from './lit/frag/lighting/shadowSampleCoord.js';
import shadowSoftPS from './lit/frag/lighting/shadowSoft.js';
import skinBatchVS from './common/vert/skinBatch.js';
import skinVS from './common/vert/skin.js';
import skyboxPS from './skybox/frag/skybox.js';
Expand Down Expand Up @@ -283,8 +284,10 @@ const shaderChunks = {
iridescencePS,
iridescenceThicknessPS,
iorPS,
lightDeclarationPS,
lightDiffuseLambertPS,
lightDirPointPS,
lightingPS,
lightmapAddPS,
lightmapDirAddPS,
lightmapDirPS,
Expand Down Expand Up @@ -371,13 +374,12 @@ const shaderChunks = {
screenDepthPS,
shadowCascadesPS,
shadowEVSMPS,
shadowEVSMnPS,
shadowPCF1PS,
shadowPCF3PS,
shadowPCF5PS,
shadowPCSSPS,
shadowSampleCoordPS,
shadowSoftPS,
shadowStandardPS,
shadowStandardGL2PS,
shadowVSM_commonPS,
skinBatchVS,
skinVS,
skyboxPS,
Expand Down
3 changes: 1 addition & 2 deletions src/scene/shader-lib/chunks/common/frag/spherical.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
export default /* glsl */`
// equirectangular helper functions
const float PI = 3.141592653589793;
vec2 toSpherical(vec3 dir) {
return vec2(dir.xz == vec2(0.0) ? 0.0 : atan(dir.x, dir.z), asin(dir.y));
}
vec2 toSphericalUv(vec3 dir) {
const float PI = 3.141592653589793;
vec2 uv = toSpherical(dir) / vec2(PI * 2.0, PI) + 0.5;
return vec2(uv.x, 1.0 - uv.y);
}
Expand Down
1 change: 1 addition & 0 deletions src/scene/shader-lib/chunks/lit/frag/lightSheen.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export default /* glsl */`
float sheenD(vec3 normal, vec3 h, float roughness) {
const float PI = 3.141592653589793;
float invR = 1.0 / (roughness * roughness);
float cos2h = max(dot(normal, h), 0.0);
cos2h *= cos2h;
Expand Down
93 changes: 93 additions & 0 deletions src/scene/shader-lib/chunks/lit/frag/lighting/lightDeclaration.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// uniforms for a light with index {i}, driven by defines
export default /* glsl */`
#if defined(LIGHT{i})
uniform vec3 light{i}_color;
#if LIGHT{i}TYPE == DIRECTIONAL
uniform vec3 light{i}_direction;
#else
uniform vec3 light{i}_position;
uniform float light{i}_radius;
#if LIGHT{i}TYPE == SPOT
uniform vec3 light{i}_direction;
uniform float light{i}_innerConeAngle;
uniform float light{i}_outerConeAngle;
#endif
#endif
// area lights
#if LIGHT{i}SHAPE != PUNCTUAL
#if LIGHT{i}TYPE == DIRECTIONAL
uniform vec3 light{i}_position;
#endif
uniform vec3 light{i}_halfWidth;
uniform vec3 light{i}_halfHeight;
#endif
// shadow casting
#if defined(LIGHT{i}CASTSHADOW)
uniform mat4 light{i}_shadowMatrix;
uniform float light{i}_shadowIntensity;
uniform vec4 light{i}_shadowParams; // width, height, bias, radius
#if LIGHT{i}SHADOWTYPE == PCSS_32F
uniform float light{i}_shadowSearchArea;
uniform vec4 light{i}_cameraParams;
#if LIGHT{i}TYPE == DIRECTIONAL
uniform vec4 light{i}_softShadowParams;
#endif
#endif
// directional (cascaded) shadows
#if LIGHT{i}TYPE == DIRECTIONAL
uniform mat4 light{i}_shadowMatrixPalette[4];
uniform vec4 light{i}_shadowCascadeDistances;
uniform int light{i}_shadowCascadeCount;
uniform float light{i}_shadowCascadeBlend;
#endif
#if LIGHT{i}TYPE == OMNI
#if defined(LIGHT{i}SHADOW_PCF)
uniform samplerCubeShadow light{i}_shadowMap;
#else
uniform samplerCube light{i}_shadowMap;
#endif
#else
#if defined(LIGHT{i}SHADOW_PCF)
uniform sampler2DShadow light{i}_shadowMap;
#else
uniform sampler2D light{i}_shadowMap;
#endif
#endif
#endif
// cookie
#if defined(LIGHT{i}COOKIE)
#if defined(LIGHT{i}COOKIE_CUBEMAP)
#if LIGHT{i}TYPE == OMNI
uniform samplerCube light{i}_cookie;
uniform float light{i}_cookieIntensity;
#if !defined(LIGHT{i}CASTSHADOW)
uniform mat4 light{i}_shadowMatrix;
#endif
#endif
#else
#if LIGHT{i}TYPE == SPOT
uniform sampler2D light{i}_cookie;
uniform float light{i}_cookieIntensity;
#if !defined(LIGHT{i}CASTSHADOW)
uniform mat4 light{i}_shadowMatrix;
#endif
#if defined(LIGHT{i}COOKIE_TRANSFORM)
uniform vec4 light{i}_cookieMatrix;
uniform vec2 light{i}_cookieOffset;
#endif
#endif
#endif
#endif
#endif
`;
Loading

0 comments on commit 7c86e72

Please sign in to comment.