Skip to content

Commit

Permalink
Adjusted syntax of variables the preprocessor uses for injection (#7386)
Browse files Browse the repository at this point in the history
Co-authored-by: Martin Valigursky <[email protected]>
  • Loading branch information
mvaligursky and Martin Valigursky authored Feb 27, 2025
1 parent 841c59b commit 08eeea6
Show file tree
Hide file tree
Showing 9 changed files with 78 additions and 43 deletions.
41 changes: 25 additions & 16 deletions src/core/preprocessor.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ const IF = /(ifdef|ifndef|if)[ \t]*([^\r\n]+)\r?\n/g;
// #endif/#else or #elif EXPRESSION
const ENDIF = /(endif|else|elif)(?:[ \t]+([^\r\n]*))?\r?\n?/g;

// identifier
const IDENTIFIER = /([\w-]+)/;
// identifier in form of IDENTIFIER or {IDENTIFIER}
const IDENTIFIER = /\{?[\w-]+\}?/;

// [!]defined(EXPRESSION)
const DEFINED = /(!|\s)?defined\(([\w-]+)\)/;
Expand Down Expand Up @@ -94,8 +94,11 @@ class Preprocessor {
});
}

// extracted defines with name in {} which are to be replaced with their values
const injectDefines = new Map();

// preprocess defines / ifdefs ..
source = this._preprocess(source, defines, includes, options.stripDefines);
source = this._preprocess(source, defines, injectDefines, includes, options.stripDefines);

// extract defines that evaluate to an integer number
const intDefines = new Map();
Expand All @@ -105,14 +108,6 @@ class Preprocessor {
}
});

// extract defines with name starting with _INJECT_
const injectDefines = new Map();
defines.forEach((value, key) => {
if (key.startsWith('_INJECT_')) {
injectDefines.set(key, value);
}
});

// strip comments again after the includes have been resolved
source = this.stripComments(source);

Expand Down Expand Up @@ -190,12 +185,14 @@ class Preprocessor {
* @param {Map<string, string>} defines - Supplied defines which are used in addition to those
* defined in the source code. Maps a define name to its value. Note that the map is modified
* by the function.
* @param {Map<string, string>} injectDefines - An object to collect defines that are to be
* replaced with their values.
* @param {Map<string, string>} [includes] - An object containing key-value pairs of include names and their
* content.
* @param {boolean} [stripDefines] - If true, strips all defines from the source.
* @returns {string} Returns preprocessed source code.
*/
static _preprocess(source, defines = new Map(), includes, stripDefines) {
static _preprocess(source, defines = new Map(), injectDefines, includes, stripDefines) {

const originalSource = source;

Expand All @@ -222,17 +219,29 @@ class Preprocessor {
// split it to identifier name and a value
IDENTIFIER.lastIndex = define.index;
const identifierValue = IDENTIFIER.exec(expression);
const identifier = identifierValue[1];
const identifier = identifierValue[0];
let value = expression.substring(identifier.length).trim();
if (value === '') value = 'true';

// are we inside if-blocks that are accepted
const keep = Preprocessor._keep(stack);
let stripThisDefine = stripDefines;

if (keep) {
defines.set(identifier, value);

if (stripDefines) {
// replacement identifier (inside {}) - always remove it from code
const replacementDefine = identifier.startsWith('{') && identifier.endsWith('}');
if (replacementDefine) {
stripThisDefine = true;
}

if (replacementDefine) {
injectDefines.set(identifier, value);
} else {
defines.set(identifier, value);
}

if (stripThisDefine) {
// cut out the define line
source = source.substring(0, define.index - 1) + source.substring(DEFINE.lastIndex);

Expand All @@ -244,7 +253,7 @@ class Preprocessor {
Debug.trace(TRACEID, `${keyword}: [${identifier}] ${value} ${keep ? '' : 'IGNORED'}`);

// continue on the next line
if (!stripDefines) {
if (!stripThisDefine) {
KEYWORD.lastIndex = define.index + define[0].length;
}
break;
Expand Down
4 changes: 2 additions & 2 deletions src/scene/shader-lib/chunks-wgsl/skybox/frag/skybox.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,13 @@ export default /* wgsl */`
#endif
dir.x *= -1.0;
linear = _INJECT_SKYBOX_DECODE_FNC(textureSample(texture_cubeMap, texture_cubeMap_sampler, dir));
linear = {SKYBOX_DECODE_FNC}(textureSample(texture_cubeMap, texture_cubeMap_sampler, dir));
#else // env-atlas
dir = input.vViewDir * vec3f(-1.0, 1.0, 1.0);
let uv : vec2f = toSphericalUv(normalize(dir));
linear = _INJECT_SKYBOX_DECODE_FNC(textureSample(texture_envAtlas, texture_envAtlas_sampler, mapRoughnessUv(uv, uniform.mipLevel)));
linear = {SKYBOX_DECODE_FNC}(textureSample(texture_envAtlas, texture_envAtlas_sampler, mapRoughnessUv(uv, uniform.mipLevel)));
#endif
Expand Down
46 changes: 36 additions & 10 deletions src/scene/shader-lib/chunks/lit/frag/clusteredLight.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,25 +98,51 @@ struct ClusterLightData {
mat4 lightProjectionMatrix;
// macros for light properties
#define isClusteredLightCastShadow(light) ( light.shadowIntensity > 0.0 )
#define isClusteredLightCookie(light) (light.cookie > 0.5 )
#define isClusteredLightCookieRgb(light) (light.cookieRgb > 0.5 )
#define isClusteredLightSpot(light) ( light.lightType > 0.5 )
#define isClusteredLightFalloffLinear(light) ( light.falloffMode < 0.5 )
bool isClusteredLightCastShadow(in ClusterLightData light) {
return light.shadowIntensity > 0.0;
}
bool isClusteredLightCookie(in ClusterLightData light) {
return light.cookie > 0.5;
}
bool isClusteredLightCookieRgb(in ClusterLightData light) {
return light.cookieRgb > 0.5;
}
bool isClusteredLightSpot(in ClusterLightData light) {
return light.lightType > 0.5;
}
bool isClusteredLightFalloffLinear(in ClusterLightData light) {
return light.falloffMode < 0.5;
}
// macros to test light shape
// Note: Following functions need to be called serially in listed order as they do not test both '>' and '<'
#define isClusteredLightArea(light) ( light.shape > 0.1 )
#define isClusteredLightRect(light) ( light.shape < 0.3 )
#define isClusteredLightDisk(light) ( light.shape < 0.6 )
bool isClusteredLightArea(in ClusterLightData light) {
return light.shape > 0.1;
}
bool isClusteredLightRect(in ClusterLightData light) {
return light.shape < 0.3;
}
bool isClusteredLightDisk(in ClusterLightData light) {
return light.shape < 0.6;
}
// macro to test light mask (mesh accepts dynamic vs lightmapped lights)
#ifdef CLUSTER_MESH_DYNAMIC_LIGHTS
// accept lights marked as dynamic or both dynamic and lightmapped
#define acceptLightMask(light) ( light.mask < 0.75)
bool acceptLightMask(in ClusterLightData light) {
return light.mask < 0.75;
}
#else
// accept lights marked as lightmapped or both dynamic and lightmapped
#define acceptLightMask(light) ( light.mask > 0.25)
bool acceptLightMask(in ClusterLightData light) {
return light.mask > 0.25;
}
#endif
vec4 decodeClusterLowRange4Vec4(vec4 d0, vec4 d1, vec4 d2, vec4 d3) {
Expand Down
6 changes: 3 additions & 3 deletions src/scene/shader-lib/chunks/lit/vert/uvTransform.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// chunk that generates uv coordinate transformed by uv transform matrix
export default /* glsl */`
vUV_INJECT_TRANSFORM_UV_{i}__INJECT_TRANSFORM_ID_{i} = vec2(
dot(vec3(uv_INJECT_TRANSFORM_UV_{i}, 1), _INJECT_TRANSFORM_NAME_{i}0),
dot(vec3(uv_INJECT_TRANSFORM_UV_{i}, 1), _INJECT_TRANSFORM_NAME_{i}1)
vUV{TRANSFORM_UV_{i}}_{TRANSFORM_ID_{i}} = vec2(
dot(vec3(uv{TRANSFORM_UV_{i}}, 1), {TRANSFORM_NAME_{i}}0),
dot(vec3(uv{TRANSFORM_UV_{i}}, 1), {TRANSFORM_NAME_{i}}1)
);
`;
4 changes: 2 additions & 2 deletions src/scene/shader-lib/chunks/lit/vert/uvTransformUniforms.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// uniform declaration for uv transform matrix, 3x2 matrix
export default /* glsl */`
uniform vec3 _INJECT_TRANSFORM_NAME_{i}0;
uniform vec3 _INJECT_TRANSFORM_NAME_{i}1;
uniform vec3 {TRANSFORM_NAME_{i}}0;
uniform vec3 {TRANSFORM_NAME_{i}}1;
`;
4 changes: 2 additions & 2 deletions src/scene/shader-lib/chunks/skybox/frag/skybox.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,14 @@ export default /* glsl */`
#endif
dir.x *= -1.0;
vec3 linear = _INJECT_SKYBOX_DECODE_FNC(textureCube(texture_cubeMap, dir));
vec3 linear = {SKYBOX_DECODE_FNC}(textureCube(texture_cubeMap, dir));
#else // env-atlas
vec3 dir = vViewDir * vec3(-1.0, 1.0, 1.0);
vec2 uv = toSphericalUv(normalize(dir));
vec3 linear = _INJECT_SKYBOX_DECODE_FNC(texture2D(texture_envAtlas, mapRoughnessUv(uv, mipLevel)));
vec3 linear = {SKYBOX_DECODE_FNC}(texture2D(texture_envAtlas, mapRoughnessUv(uv, mipLevel)));
#endif
Expand Down
6 changes: 3 additions & 3 deletions src/scene/shader-lib/programs/lit-shader.js
Original file line number Diff line number Diff line change
Expand Up @@ -256,9 +256,9 @@ class LitShader {

// defines used by the included chunks
const varName = `texture_${name}MapTransform`;
vDefines.set(`_INJECT_TRANSFORM_NAME_${numTransforms}`, varName);
vDefines.set(`_INJECT_TRANSFORM_UV_${numTransforms}`, uv);
vDefines.set(`_INJECT_TRANSFORM_ID_${numTransforms}`, id);
vDefines.set(`{TRANSFORM_NAME_${numTransforms}}`, varName);
vDefines.set(`{TRANSFORM_UV_${numTransforms}}`, uv);
vDefines.set(`{TRANSFORM_ID_${numTransforms}}`, id);

numTransforms++;
}
Expand Down
2 changes: 1 addition & 1 deletion src/scene/skybox/sky-mesh.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class SkyMesh {
});

// defines
material.setDefine('_INJECT_SKYBOX_DECODE_FNC', ChunkUtils.decodeFunc(texture.encoding));
material.setDefine('{SKYBOX_DECODE_FNC}', ChunkUtils.decodeFunc(texture.encoding));
if (type !== SKYTYPE_INFINITE) material.setDefine('SKYMESH', '');
if (texture.cubemap) material.setDefine('SKY_CUBEMAP', '');

Expand Down
8 changes: 4 additions & 4 deletions test/core/preprocessor.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ describe('Preprocessor', function () {
const srcData = `
#define LOOP_COUNT 3
#define _INJECT_COUNT 2
#define _INJECT_STRING hello
#define {COUNT} 2
#define {STRING} hello
#define FEATURE1
#define FEATURE2
#define AND1
Expand Down Expand Up @@ -126,8 +126,8 @@ describe('Preprocessor', function () {
CMP5
#endif
TESTINJECTION _INJECT_COUNT
INJECTSTRING _INJECT_STRING(x)
TESTINJECTION {COUNT}
INJECTSTRING {STRING}(x)
`;

it('returns false for MORPH_A', function () {
Expand Down

0 comments on commit 08eeea6

Please sign in to comment.